diff --git a/src/all_types.hpp b/src/all_types.hpp index 49d2db132..e099f7967 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -535,6 +535,9 @@ struct AsmOutput { Buf constraint; Buf variable_name; AstNode *return_type; // null unless "=r" and return + + // populated by semantic analyzer + VariableTableEntry *variable; }; struct AsmInput { diff --git a/src/analyze.cpp b/src/analyze.cpp index 81874e0fd..49d04057e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2431,19 +2431,6 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, return g->builtin_types.entry_invalid; } -static TypeTableEntry *analyze_variable_name(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode *node, Buf *variable_name) -{ - VariableTableEntry *var = find_variable(context, variable_name); - if (var) { - return var->type; - } else { - add_node_error(g, node, - buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); - return g->builtin_types.entry_invalid; - } -} - static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { switch (op) { case BinOpTypeAssign: @@ -4402,6 +4389,42 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, return return_type; } +static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, + TypeTableEntry *expected_type, AstNode *node) +{ + node->data.asm_expr.return_count = 0; + TypeTableEntry *return_type = g->builtin_types.entry_void; + for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) { + AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); + if (asm_output->return_type) { + node->data.asm_expr.return_count += 1; + return_type = analyze_type_expr(g, import, context, asm_output->return_type); + if (node->data.asm_expr.return_count > 1) { + add_node_error(g, node, + buf_sprintf("inline assembly allows up to one output value")); + break; + } + } else { + Buf *variable_name = &asm_output->variable_name; + VariableTableEntry *var = find_variable(context, variable_name); + if (var) { + asm_output->variable = var; + return var->type; + } else { + add_node_error(g, node, + buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); + return g->builtin_types.entry_invalid; + } + } + } + for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) { + AsmInput *asm_input = node->data.asm_expr.input_list.at(i); + analyze_expression(g, import, context, nullptr, asm_input->expr); + } + + return return_type; +} + // When you call analyze_expression, the node you pass might no longer be the child node // you thought it was due to implicit casting rewriting the AST. static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, @@ -4441,30 +4464,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, return_type = analyze_continue_expr(g, import, context, expected_type, node); break; case NodeTypeAsmExpr: - { - node->data.asm_expr.return_count = 0; - return_type = g->builtin_types.entry_void; - for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) { - AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); - if (asm_output->return_type) { - node->data.asm_expr.return_count += 1; - return_type = analyze_type_expr(g, import, context, asm_output->return_type); - if (node->data.asm_expr.return_count > 1) { - add_node_error(g, node, - buf_sprintf("inline assembly allows up to one output value")); - break; - } - } else { - analyze_variable_name(g, import, context, node, &asm_output->variable_name); - } - } - for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) { - AsmInput *asm_input = node->data.asm_expr.input_list.at(i); - analyze_expression(g, import, context, nullptr, asm_input->expr); - } - - break; - } + return_type = analyze_asm_expr(g, import, context, expected_type, node); + break; case NodeTypeBinOpExpr: return_type = analyze_bin_op_expr(g, import, context, expected_type, node); break; diff --git a/src/codegen.cpp b/src/codegen.cpp index 16797881c..b32bebc30 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1822,7 +1822,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) { } if (!is_return) { - VariableTableEntry *variable = find_variable( node->block_context, &asm_output->variable_name); + VariableTableEntry *variable = asm_output->variable; assert(variable); param_types[param_index] = LLVMTypeOf(variable->value_ref); param_values[param_index] = variable->value_ref;