| ... | @@ -2431,19 +2431,6 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -2431,19 +2431,6 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, |
| 2431 | return g->builtin_types.entry_invalid; | 2431 | return g->builtin_types.entry_invalid; |
| 2432 | } | 2432 | } |
| 2433 | | 2433 | |
| 2434 | static 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 | | | |
| 2447 | static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | 2434 | static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 2448 | switch (op) { | 2435 | switch (op) { |
| 2449 | case BinOpTypeAssign: | 2436 | case BinOpTypeAssign: |
| ... | @@ -4402,6 +4389,42 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -4402,6 +4389,42 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, |
| 4402 | return return_type; | 4389 | return return_type; |
| 4403 | } | 4390 | } |
| 4404 | | 4391 | |
| | 4392 | static 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 | |
| 4405 | // When you call analyze_expression, the node you pass might no longer be the child node | 4428 | // When you call analyze_expression, the node you pass might no longer be the child node |
| 4406 | // you thought it was due to implicit casting rewriting the AST. | 4429 | // you thought it was due to implicit casting rewriting the AST. |
| 4407 | static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 4430 | static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| ... | @@ -4441,30 +4464,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -4441,30 +4464,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 4441 | return_type = analyze_continue_expr(g, import, context, expected_type, node); | 4464 | return_type = analyze_continue_expr(g, import, context, expected_type, node); |
| 4442 | break; | 4465 | break; |
| 4443 | case NodeTypeAsmExpr: | 4466 | case NodeTypeAsmExpr: |
| 4444 | { | 4467 | return_type = analyze_asm_expr(g, import, context, expected_type, node); |
| 4445 | node->data.asm_expr.return_count = 0; | 4468 | break; |
| 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 | } | | |
| 4468 | case NodeTypeBinOpExpr: | 4469 | case NodeTypeBinOpExpr: |
| 4469 | return_type = analyze_bin_op_expr(g, import, context, expected_type, node); | 4470 | return_type = analyze_bin_op_expr(g, import, context, expected_type, node); |
| 4470 | break; | 4471 | break; |