aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-04-04 19:47:22 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-04-04 19:47:22 -0400
commit0edc2b19fe684355406d09c9195b353c630d99ed (patch)
tree232693ceb5e2ee139825cf95be1054583e8ee82e /src
parentd97285eb65d56b9e3a1208c4de3b991e93057495 (diff)
downloadzig-0edc2b19fe684355406d09c9195b353c630d99ed.tar.gz
zig-0edc2b19fe684355406d09c9195b353c630d99ed.zip
support module level assembly
closes #256
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp2
-rw-r--r--src/codegen.cpp6
-rw-r--r--src/ir.cpp21
3 files changed, 27 insertions, 2 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index c92ab364c5..d3d1a907d1 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1460,6 +1460,8 @@ struct CodeGen {
ConstExprValue const_void_val;
ConstExprValue panic_msg_vals[PanicMsgIdCount];
+
+ Buf global_asm;
};
enum VarLinkage {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 5e803795f1..83b7e01614 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -73,6 +73,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
g->is_test_build = false;
g->want_h_file = true;
+ buf_resize(&g->global_asm, 0);
+
// reserve index 0 to indicate no error
g->error_decls.append(nullptr);
@@ -3725,6 +3727,10 @@ static void do_code_gen(CodeGen *g) {
}
assert(!g->errors.length);
+ if (buf_len(&g->global_asm) != 0) {
+ LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
+ }
+
ZigLLVMDIBuilderFinalize(g->dbuilder);
if (g->verbose) {
diff --git a/src/ir.cpp b/src/ir.cpp
index 4f3f756d49..6f5f5fbbd2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9896,13 +9896,30 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) {
assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr);
+ AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
+
+ bool global_scope = (scope_fn_entry(asm_instruction->base.scope) == nullptr);
+ if (global_scope) {
+ if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 ||
+ asm_expr->clobber_list.length != 0)
+ {
+ ir_add_error(ira, &asm_instruction->base,
+ buf_sprintf("global assembly cannot have inputs, outputs, or clobbers"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ buf_append_char(&ira->codegen->global_asm, '\n');
+ buf_append_buf(&ira->codegen->global_asm, asm_expr->asm_template);
+
+ ir_build_const_from(ira, &asm_instruction->base);
+ return ira->codegen->builtin_types.entry_void;
+ }
+
if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base))
return ira->codegen->builtin_types.entry_invalid;
// TODO validate the output types and variable types
- AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
-
IrInstruction **input_list = allocate<IrInstruction *>(asm_expr->input_list.length);
IrInstruction **output_types = allocate<IrInstruction *>(asm_expr->output_list.length);