Commit a2035eefba

Andrew Kelley <superjoe30@gmail.com>
2016-02-02 04:13:36
codegen: avoid table lookup in assembly expression
1 parent 74eaf43
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 {
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;
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;