From 2addec8ea1f35241e9399c5da6855c427481985f Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Sat, 17 Aug 2019 14:16:51 +0200 Subject: [PATCH] compiler error when variable in asm template cannot be found --- src/ir.cpp | 35 +++++++++++++++++++++++++++++++++++ test/compile_errors.zig | 12 ++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 8f27c9ea2..cdddce1b1 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 cecb37620..690db2c4e 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,18 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "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." + ); + cases.add( "indirect recursion of async functions detected", \\var frame: ?anyframe = null;