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