| author | |
| committer | |
| log | f0a141f79978d6d04b7cac1986b9bda770d3d6f9 |
| tree | 43b99a9c9095517a21869dac8ab0e7e0de7ab7e7 |
| parent | 2aa18b909765a48878d3f30f638e79d6eee1b584 |
| parent | 276eb4402b3c54adef10033d1ec54bf2053cc563 |
| signature |
closes #3084
closes #30303 files changed, 69 insertions(+), 10 deletions(-)
src/ir.cpp+35| ... | ... | @@ -6743,6 +6743,25 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t |
| 6743 | 6743 | return ErrorNone; |
| 6744 | 6744 | } |
| 6745 | 6745 | |
| 6746 | static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { | |
| 6747 | const char *ptr = buf_ptr(src_template) + tok->start + 2; | |
| 6748 | size_t len = tok->end - tok->start - 2; | |
| 6749 | size_t result = 0; | |
| 6750 | for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { | |
| 6751 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); | |
| 6752 | if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { | |
| 6753 | return result; | |
| 6754 | } | |
| 6755 | } | |
| 6756 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { | |
| 6757 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); | |
| 6758 | if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { | |
| 6759 | return result; | |
| 6760 | } | |
| 6761 | } | |
| 6762 | return SIZE_MAX; | |
| 6763 | } | |
| 6764 | ||
| 6746 | 6765 | static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 6747 | 6766 | Error err; |
| 6748 | 6767 | assert(node->type == NodeTypeAsmExpr); |
| ... | ... | @@ -6830,6 +6849,22 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 6830 | 6849 | input_list[i] = input_value; |
| 6831 | 6850 | } |
| 6832 | 6851 | |
| 6852 | for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) { | |
| 6853 | AsmToken asm_token = tok_list.at(token_i); | |
| 6854 | if (asm_token.id == AsmTokenIdVar) { | |
| 6855 | size_t index = find_asm_index(irb->codegen, node, &asm_token, template_buf); | |
| 6856 | if (index == SIZE_MAX) { | |
| 6857 | const char *ptr = buf_ptr(template_buf) + asm_token.start + 2; | |
| 6858 | uint32_t len = asm_token.end - asm_token.start - 2; | |
| 6859 | ||
| 6860 | add_node_error(irb->codegen, node, | |
| 6861 | buf_sprintf("could not find '%.*s' in the inputs or outputs.", | |
| 6862 | len, ptr)); | |
| 6863 | return irb->codegen->invalid_instruction; | |
| 6864 | } | |
| 6865 | } | |
| 6866 | } | |
| 6867 | ||
| 6833 | 6868 | return ir_build_asm(irb, scope, node, template_buf, tok_list.items, tok_list.length, |
| 6834 | 6869 | input_list, output_types, output_vars, return_count, is_volatile); |
| 6835 | 6870 | } |
test/compile_errors.zig+19| ... | ... | @@ -2,6 +2,25 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addCase(x: { | |
| 6 | var tc = cases.create("variable in inline assembly template cannot be found", | |
| 7 | \\export fn entry() void { | |
| 8 | \\ var sp = asm volatile ( | |
| 9 | \\ "mov %[foo], sp" | |
| 10 | \\ : [bar] "=r" (-> usize) | |
| 11 | \\ ); | |
| 12 | \\} | |
| 13 | , "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs."); | |
| 14 | tc.target = tests.Target{ | |
| 15 | .Cross = tests.CrossTarget{ | |
| 16 | .arch = .x86_64, | |
| 17 | .os = .linux, | |
| 18 | .abi = .gnu, | |
| 19 | }, | |
| 20 | }; | |
| 21 | break :x tc; | |
| 22 | }); | |
| 23 | ||
| 5 | 24 | cases.add( |
| 6 | 25 | "indirect recursion of async functions detected", |
| 7 | 26 | \\var frame: ?anyframe = null; |
test/tests.zig+15-10| ... | ... | @@ -2,6 +2,8 @@ const std = @import("std"); |
| 2 | 2 | const debug = std.debug; |
| 3 | 3 | const warn = debug.warn; |
| 4 | 4 | const build = std.build; |
| 5 | pub const Target = build.Target; | |
| 6 | pub const CrossTarget = build.CrossTarget; | |
| 5 | 7 | const Buffer = std.Buffer; |
| 6 | 8 | const io = std.io; |
| 7 | 9 | const fs = std.fs; |
| ... | ... | @@ -20,24 +22,18 @@ const runtime_safety = @import("runtime_safety.zig"); |
| 20 | 22 | const translate_c = @import("translate_c.zig"); |
| 21 | 23 | const gen_h = @import("gen_h.zig"); |
| 22 | 24 | |
| 23 | const TestTarget = struct { | |
| 24 | os: builtin.Os, | |
| 25 | arch: builtin.Arch, | |
| 26 | abi: builtin.Abi, | |
| 27 | }; | |
| 28 | ||
| 29 | const test_targets = [_]TestTarget{ | |
| 30 | TestTarget{ | |
| 25 | const test_targets = [_]CrossTarget{ | |
| 26 | CrossTarget{ | |
| 31 | 27 | .os = .linux, |
| 32 | 28 | .arch = .x86_64, |
| 33 | 29 | .abi = .gnu, |
| 34 | 30 | }, |
| 35 | TestTarget{ | |
| 31 | CrossTarget{ | |
| 36 | 32 | .os = .macosx, |
| 37 | 33 | .arch = .x86_64, |
| 38 | 34 | .abi = .gnu, |
| 39 | 35 | }, |
| 40 | TestTarget{ | |
| 36 | CrossTarget{ | |
| 41 | 37 | .os = .windows, |
| 42 | 38 | .arch = .x86_64, |
| 43 | 39 | .abi = .msvc, |
| ... | ... | @@ -568,6 +564,7 @@ pub const CompileErrorContext = struct { |
| 568 | 564 | link_libc: bool, |
| 569 | 565 | is_exe: bool, |
| 570 | 566 | is_test: bool, |
| 567 | target: Target = .Native, | |
| 571 | 568 | |
| 572 | 569 | const SourceFile = struct { |
| 573 | 570 | filename: []const u8, |
| ... | ... | @@ -655,6 +652,14 @@ pub const CompileErrorContext = struct { |
| 655 | 652 | zig_args.append("--output-dir") catch unreachable; |
| 656 | 653 | zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable; |
| 657 | 654 | |
| 655 | switch (self.case.target) { | |
| 656 | .Native => {}, | |
| 657 | .Cross => { | |
| 658 | try zig_args.append("-target"); | |
| 659 | try zig_args.append(try self.case.target.zigTriple(b.allocator)); | |
| 660 | }, | |
| 661 | } | |
| 662 | ||
| 658 | 663 | switch (self.build_mode) { |
| 659 | 664 | Mode.Debug => {}, |
| 660 | 665 | Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable, |