Commit 2addec8ea1

Timon Kruiper <timonkruiper@gmail.com>
2019-08-17 14:16:51
compiler error when variable in asm template cannot be found
1 parent 2aa18b9
Changed files (2)
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);
 }
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;