diff --git a/src/ir.cpp b/src/ir.cpp index 8f27c9ea2c..cdddce1b18 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6743,6 +6743,25 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t return ErrorNone; } +static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { + const char *ptr = buf_ptr(src_template) + tok->start + 2; + size_t len = tok->end - tok->start - 2; + size_t result = 0; + for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { + AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); + if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { + return result; + } + } + for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { + AsmInput *asm_input = node->data.asm_expr.input_list.at(i); + if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { + return result; + } + } + return SIZE_MAX; +} + static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeAsmExpr); @@ -6830,6 +6849,22 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod input_list[i] = input_value; } + for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) { + AsmToken asm_token = tok_list.at(token_i); + if (asm_token.id == AsmTokenIdVar) { + size_t index = find_asm_index(irb->codegen, node, &asm_token, template_buf); + if (index == SIZE_MAX) { + const char *ptr = buf_ptr(template_buf) + asm_token.start + 2; + uint32_t len = asm_token.end - asm_token.start - 2; + + add_node_error(irb->codegen, node, + buf_sprintf("could not find '%.*s' in the inputs or outputs.", + len, ptr)); + return irb->codegen->invalid_instruction; + } + } + } + return ir_build_asm(irb, scope, node, template_buf, tok_list.items, tok_list.length, input_list, output_types, output_vars, return_count, is_volatile); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index cecb37620c..a6a1d0219b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,25 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addCase(x: { + var tc = cases.create("variable in inline assembly template cannot be found", + \\export fn entry() void { + \\ var sp = asm volatile ( + \\ "mov %[foo], sp" + \\ : [bar] "=r" (-> usize) + \\ ); + \\} + , "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs."); + tc.target = tests.Target{ + .Cross = tests.CrossTarget{ + .arch = .x86_64, + .os = .linux, + .abi = .gnu, + }, + }; + break :x tc; + }); + cases.add( "indirect recursion of async functions detected", \\var frame: ?anyframe = null; diff --git a/test/tests.zig b/test/tests.zig index c8aea33591..f7ef05d3cd 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2,6 +2,8 @@ const std = @import("std"); const debug = std.debug; const warn = debug.warn; const build = std.build; +pub const Target = build.Target; +pub const CrossTarget = build.CrossTarget; const Buffer = std.Buffer; const io = std.io; const fs = std.fs; @@ -20,24 +22,18 @@ const runtime_safety = @import("runtime_safety.zig"); const translate_c = @import("translate_c.zig"); const gen_h = @import("gen_h.zig"); -const TestTarget = struct { - os: builtin.Os, - arch: builtin.Arch, - abi: builtin.Abi, -}; - -const test_targets = [_]TestTarget{ - TestTarget{ +const test_targets = [_]CrossTarget{ + CrossTarget{ .os = .linux, .arch = .x86_64, .abi = .gnu, }, - TestTarget{ + CrossTarget{ .os = .macosx, .arch = .x86_64, .abi = .gnu, }, - TestTarget{ + CrossTarget{ .os = .windows, .arch = .x86_64, .abi = .msvc, @@ -568,6 +564,7 @@ pub const CompileErrorContext = struct { link_libc: bool, is_exe: bool, is_test: bool, + target: Target = .Native, const SourceFile = struct { filename: []const u8, @@ -655,6 +652,14 @@ pub const CompileErrorContext = struct { zig_args.append("--output-dir") catch unreachable; zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable; + switch (self.case.target) { + .Native => {}, + .Cross => { + try zig_args.append("-target"); + try zig_args.append(try self.case.target.zigTriple(b.allocator)); + }, + } + switch (self.build_mode) { Mode.Debug => {}, Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable,