authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 20:13:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 20:13:36-07:00
loga2035eefba0fe8f29d0bcffbe254c066fc97069b
tree63993adc8abbf5e8dfc6564215c505d9ba1a23bf
parent74eaf4376800ab1a3405a69e4f65ecfecb1e1db9

codegen: avoid table lookup in assembly expression


3 files changed, 42 insertions(+), 38 deletions(-)

src/all_types.hpp+3
......@@ -535,6 +535,9 @@ struct AsmOutput {
535535 Buf constraint;
536536 Buf variable_name;
537537 AstNode *return_type; // null unless "=r" and return
538
539 // populated by semantic analyzer
540 VariableTableEntry *variable;
538541};
539542
540543struct AsmInput {
src/analyze.cpp+38-37
......@@ -2431,19 +2431,6 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
24312431 return g->builtin_types.entry_invalid;
24322432}
24332433
2434static TypeTableEntry *analyze_variable_name(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2435 AstNode *node, Buf *variable_name)
2436{
2437 VariableTableEntry *var = find_variable(context, variable_name);
2438 if (var) {
2439 return var->type;
2440 } else {
2441 add_node_error(g, node,
2442 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
2443 return g->builtin_types.entry_invalid;
2444 }
2445}
2446
24472434static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
24482435 switch (op) {
24492436 case BinOpTypeAssign:
......@@ -4402,6 +4389,42 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
44024389 return return_type;
44034390}
44044391
4392static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4393 TypeTableEntry *expected_type, AstNode *node)
4394{
4395 node->data.asm_expr.return_count = 0;
4396 TypeTableEntry *return_type = g->builtin_types.entry_void;
4397 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
4398 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
4399 if (asm_output->return_type) {
4400 node->data.asm_expr.return_count += 1;
4401 return_type = analyze_type_expr(g, import, context, asm_output->return_type);
4402 if (node->data.asm_expr.return_count > 1) {
4403 add_node_error(g, node,
4404 buf_sprintf("inline assembly allows up to one output value"));
4405 break;
4406 }
4407 } else {
4408 Buf *variable_name = &asm_output->variable_name;
4409 VariableTableEntry *var = find_variable(context, variable_name);
4410 if (var) {
4411 asm_output->variable = var;
4412 return var->type;
4413 } else {
4414 add_node_error(g, node,
4415 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
4416 return g->builtin_types.entry_invalid;
4417 }
4418 }
4419 }
4420 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
4421 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
4422 analyze_expression(g, import, context, nullptr, asm_input->expr);
4423 }
4424
4425 return return_type;
4426}
4427
44054428// When you call analyze_expression, the node you pass might no longer be the child node
44064429// you thought it was due to implicit casting rewriting the AST.
44074430static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -4441,30 +4464,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
44414464 return_type = analyze_continue_expr(g, import, context, expected_type, node);
44424465 break;
44434466 case NodeTypeAsmExpr:
4444 {
4445 node->data.asm_expr.return_count = 0;
4446 return_type = g->builtin_types.entry_void;
4447 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
4448 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
4449 if (asm_output->return_type) {
4450 node->data.asm_expr.return_count += 1;
4451 return_type = analyze_type_expr(g, import, context, asm_output->return_type);
4452 if (node->data.asm_expr.return_count > 1) {
4453 add_node_error(g, node,
4454 buf_sprintf("inline assembly allows up to one output value"));
4455 break;
4456 }
4457 } else {
4458 analyze_variable_name(g, import, context, node, &asm_output->variable_name);
4459 }
4460 }
4461 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
4462 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
4463 analyze_expression(g, import, context, nullptr, asm_input->expr);
4464 }
4465
4466 break;
4467 }
4467 return_type = analyze_asm_expr(g, import, context, expected_type, node);
4468 break;
44684469 case NodeTypeBinOpExpr:
44694470 return_type = analyze_bin_op_expr(g, import, context, expected_type, node);
44704471 break;
src/codegen.cpp+1-1
......@@ -1822,7 +1822,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
18221822 }
18231823
18241824 if (!is_return) {
1825 VariableTableEntry *variable = find_variable( node->block_context, &asm_output->variable_name);
1825 VariableTableEntry *variable = asm_output->variable;
18261826 assert(variable);
18271827 param_types[param_index] = LLVMTypeOf(variable->value_ref);
18281828 param_values[param_index] = variable->value_ref;