| author | |
| committer | |
| log | 0edc2b19fe684355406d09c9195b353c630d99ed |
| tree | 232693ceb5e2ee139825cf95be1054583e8ee82e |
| parent | d97285eb65d56b9e3a1208c4de3b991e93057495 |
closes #2566 files changed, 65 insertions(+), 2 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -1460,6 +1460,8 @@ struct CodeGen { |
| 1460 | 1460 | ConstExprValue const_void_val; |
| 1461 | 1461 | |
| 1462 | 1462 | ConstExprValue panic_msg_vals[PanicMsgIdCount]; |
| 1463 | ||
| 1464 | Buf global_asm; | |
| 1463 | 1465 | }; |
| 1464 | 1466 | |
| 1465 | 1467 | enum VarLinkage { |
src/codegen.cpp+6| ... | ... | @@ -73,6 +73,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 73 | 73 | g->is_test_build = false; |
| 74 | 74 | g->want_h_file = true; |
| 75 | 75 | |
| 76 | buf_resize(&g->global_asm, 0); | |
| 77 | ||
| 76 | 78 | // reserve index 0 to indicate no error |
| 77 | 79 | g->error_decls.append(nullptr); |
| 78 | 80 | |
| ... | ... | @@ -3725,6 +3727,10 @@ static void do_code_gen(CodeGen *g) { |
| 3725 | 3727 | } |
| 3726 | 3728 | assert(!g->errors.length); |
| 3727 | 3729 | |
| 3730 | if (buf_len(&g->global_asm) != 0) { | |
| 3731 | LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm)); | |
| 3732 | } | |
| 3733 | ||
| 3728 | 3734 | ZigLLVMDIBuilderFinalize(g->dbuilder); |
| 3729 | 3735 | |
| 3730 | 3736 | if (g->verbose) { |
src/ir.cpp+19-2| ... | ... | @@ -9896,13 +9896,30 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 9896 | 9896 | static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) { |
| 9897 | 9897 | assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); |
| 9898 | 9898 | |
| 9899 | AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr; | |
| 9900 | ||
| 9901 | bool global_scope = (scope_fn_entry(asm_instruction->base.scope) == nullptr); | |
| 9902 | if (global_scope) { | |
| 9903 | if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || | |
| 9904 | asm_expr->clobber_list.length != 0) | |
| 9905 | { | |
| 9906 | ir_add_error(ira, &asm_instruction->base, | |
| 9907 | buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); | |
| 9908 | return ira->codegen->builtin_types.entry_invalid; | |
| 9909 | } | |
| 9910 | ||
| 9911 | buf_append_char(&ira->codegen->global_asm, '\n'); | |
| 9912 | buf_append_buf(&ira->codegen->global_asm, asm_expr->asm_template); | |
| 9913 | ||
| 9914 | ir_build_const_from(ira, &asm_instruction->base); | |
| 9915 | return ira->codegen->builtin_types.entry_void; | |
| 9916 | } | |
| 9917 | ||
| 9899 | 9918 | if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base)) |
| 9900 | 9919 | return ira->codegen->builtin_types.entry_invalid; |
| 9901 | 9920 | |
| 9902 | 9921 | // TODO validate the output types and variable types |
| 9903 | 9922 | |
| 9904 | AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr; | |
| 9905 | ||
| 9906 | 9923 | IrInstruction **input_list = allocate<IrInstruction *>(asm_expr->input_list.length); |
| 9907 | 9924 | IrInstruction **output_types = allocate<IrInstruction *>(asm_expr->output_list.length); |
| 9908 | 9925 |
test/cases/asm.zig created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | comptime { | |
| 4 | if (@compileVar("arch") == Arch.x86_64) { | |
| 5 | asm volatile ( | |
| 6 | \\.globl aoeu; | |
| 7 | \\.type aoeu, @function; | |
| 8 | \\.set aoeu, derp; | |
| 9 | ); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | test "module level assembly" { | |
| 14 | if (@compileVar("arch") == Arch.x86_64) { | |
| 15 | assert(aoeu() == 1234); | |
| 16 | } | |
| 17 | } | |
| 18 | ||
| 19 | extern fn aoeu() -> i32; | |
| 20 | ||
| 21 | export fn derp() -> i32 { | |
| 22 | return 1234; | |
| 23 | } |
test/run_tests.cpp+14| ... | ... | @@ -1834,6 +1834,20 @@ fn foo(e: error) -> u2 { |
| 1834 | 1834 | } |
| 1835 | 1835 | export fn entry() -> usize { @sizeOf(@typeOf(foo)) } |
| 1836 | 1836 | )SOURCE", 1, ".tmp_source.zig:5:14: error: too many error values to fit in 'u2'"); |
| 1837 | ||
| 1838 | add_compile_fail_case("asm at compile time", R"SOURCE( | |
| 1839 | comptime { | |
| 1840 | doSomeAsm(); | |
| 1841 | } | |
| 1842 | ||
| 1843 | fn doSomeAsm() { | |
| 1844 | asm volatile ( | |
| 1845 | \\.globl aoeu; | |
| 1846 | \\.type aoeu, @function; | |
| 1847 | \\.set aoeu, derp; | |
| 1848 | ); | |
| 1849 | } | |
| 1850 | )SOURCE", 1, ".tmp_source.zig:7:5: error: unable to evaluate constant expression"); | |
| 1837 | 1851 | } |
| 1838 | 1852 | |
| 1839 | 1853 | ////////////////////////////////////////////////////////////////////////////// |
test/self_hosted.zig+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | comptime { |
| 2 | 2 | _ = @import("cases/array.zig"); |
| 3 | _ = @import("cases/asm.zig"); | |
| 3 | 4 | _ = @import("cases/atomics.zig"); |
| 4 | 5 | _ = @import("cases/bool.zig"); |
| 5 | 6 | _ = @import("cases/cast.zig"); |