diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 3ece8d150b..829ad2acbe 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1495,13 +1495,13 @@ fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { return &node.base; } -/// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN +/// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const asm_token = eatToken(it, .Keyword_asm) orelse return null; const volatile_token = eatToken(it, .Keyword_volatile); _ = try expectToken(it, tree, .LParen); - const template = try expectNode(arena, it, tree, parseStringLiteral, AstError{ - .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index }, + const template = try expectNode(arena, it, tree, parseExpr, AstError{ + .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index }, }); const node = try arena.create(Node.Asm); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 0d38ec5ccb..4e20d16354 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,3 +1,26 @@ +test "zig fmt: asm expression with comptime content" { + try testCanonical( + \\comptime { + \\ asm ("foo" ++ "bar"); + \\} + \\pub fn main() void { + \\ asm volatile ("foo" ++ "bar"); + \\ asm volatile ("foo" ++ "bar" + \\ : [_] "" (x) + \\ ); + \\ asm volatile ("foo" ++ "bar" + \\ : [_] "" (x) + \\ : [_] "" (y) + \\ ); + \\ asm volatile ("foo" ++ "bar" + \\ : [_] "" (x) + \\ : [_] "" (y) + \\ : "h", "e", "l", "l", "o" + \\ ); + \\} + \\ + ); +} test "zig fmt: var struct field" { try testCanonical( \\pub const Pointer = struct { diff --git a/src/all_types.hpp b/src/all_types.hpp index cc11741870..5a248f9cd2 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -949,7 +949,7 @@ struct AsmToken { struct AstNodeAsmExpr { Token *volatile_token; - Token *asm_template; + AstNode *asm_template; ZigList output_list; ZigList input_list; ZigList clobber_list; @@ -2496,8 +2496,8 @@ enum IrInstructionId { IrInstructionIdArrayType, IrInstructionIdAnyFrameType, IrInstructionIdSliceType, - IrInstructionIdGlobalAsm, - IrInstructionIdAsm, + IrInstructionIdAsmSrc, + IrInstructionIdAsmGen, IrInstructionIdSizeOf, IrInstructionIdTestNonNull, IrInstructionIdOptionalUnwrapPtr, @@ -3049,13 +3049,19 @@ struct IrInstructionSliceType { bool is_allow_zero; }; -struct IrInstructionGlobalAsm { +struct IrInstructionAsmSrc { IrInstruction base; - Buf *asm_code; + IrInstruction *asm_template; + IrInstruction **input_list; + IrInstruction **output_types; + ZigVar **output_vars; + size_t return_count; + bool has_side_effects; + bool is_global; }; -struct IrInstructionAsm { +struct IrInstructionAsmGen { IrInstruction base; Buf *asm_template; diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 531fcf1852..a8fb899ec3 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -884,7 +884,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { { AstNodeAsmExpr *asm_expr = &node->data.asm_expr; const char *volatile_str = (asm_expr->volatile_token != nullptr) ? " volatile" : ""; - fprintf(ar->f, "asm%s (\"%s\"\n", volatile_str, buf_ptr(&asm_expr->asm_template->data.str_lit.str)); + fprintf(ar->f, "asm%s (", volatile_str); + render_node_ungrouped(ar, asm_expr->asm_template); + fprintf(ar->f, ")"); print_indent(ar); fprintf(ar->f, ": "); for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 06834a7e4b..dc29e8f4b1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4437,7 +4437,7 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ return SIZE_MAX; } -static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstructionAsm *instruction) { +static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutable *executable, IrInstructionAsmGen *instruction) { AstNode *asm_node = instruction->base.source_node; assert(asm_node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; @@ -6135,7 +6135,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdPtrCastSrc: case IrInstructionIdCmpxchgSrc: case IrInstructionIdLoadPtr: - case IrInstructionIdGlobalAsm: case IrInstructionIdHasDecl: case IrInstructionIdUndeclaredIdent: case IrInstructionIdCallSrc: @@ -6156,6 +6155,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdAwaitSrc: case IrInstructionIdSplatSrc: case IrInstructionIdMergeErrSets: + case IrInstructionIdAsmSrc: zig_unreachable(); case IrInstructionIdDeclVarGen: @@ -6192,8 +6192,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction); case IrInstructionIdUnionFieldPtr: return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction); - case IrInstructionIdAsm: - return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); + case IrInstructionIdAsmGen: + return ir_render_asm_gen(g, executable, (IrInstructionAsmGen *)instruction); case IrInstructionIdTestNonNull: return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); case IrInstructionIdOptionalUnwrapPtr: diff --git a/src/ir.cpp b/src/ir.cpp index a40836c9e1..044caa4d4e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -339,10 +339,10 @@ static void destroy_instruction(IrInstruction *inst) { return destroy(reinterpret_cast(inst), name); case IrInstructionIdAnyFrameType: return destroy(reinterpret_cast(inst), name); - case IrInstructionIdGlobalAsm: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAsm: - return destroy(reinterpret_cast(inst), name); + case IrInstructionIdAsmSrc: + return destroy(reinterpret_cast(inst), name); + case IrInstructionIdAsmGen: + return destroy(reinterpret_cast(inst), name); case IrInstructionIdSizeOf: return destroy(reinterpret_cast(inst), name); case IrInstructionIdTestNonNull: @@ -1028,12 +1028,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) { return IrInstructionIdSliceType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionGlobalAsm *) { - return IrInstructionIdGlobalAsm; +static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmSrc *) { + return IrInstructionIdAsmSrc; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAsm *) { - return IrInstructionIdAsm; +static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmGen *) { + return IrInstructionIdAsmGen; } static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) { @@ -2268,18 +2268,39 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_global_asm(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *asm_code) { - IrInstructionGlobalAsm *instruction = ir_build_instruction(irb, scope, source_node); - instruction->asm_code = asm_code; +static IrInstruction *ir_build_asm_src(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *asm_template, IrInstruction **input_list, IrInstruction **output_types, + ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) +{ + IrInstructionAsmSrc *instruction = ir_build_instruction(irb, scope, source_node); + instruction->asm_template = asm_template; + instruction->input_list = input_list; + instruction->output_types = output_types; + instruction->output_vars = output_vars; + instruction->return_count = return_count; + instruction->has_side_effects = has_side_effects; + instruction->is_global = is_global; + + assert(source_node->type == NodeTypeAsmExpr); + for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { + IrInstruction *output_type = output_types[i]; + if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); + } + + for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { + IrInstruction *input_value = input_list[i]; + ir_ref_instruction(input_value, irb->current_basic_block); + } + return &instruction->base; } -static IrInstruction *ir_build_asm(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Buf *asm_template, AsmToken *token_list, size_t token_list_len, IrInstruction **input_list, IrInstruction **output_types, ZigVar **output_vars, size_t return_count, bool has_side_effects) { - IrInstructionAsm *instruction = ir_build_instruction(irb, scope, source_node); + IrInstructionAsmGen *instruction = ir_build_instruction(&ira->new_irb, scope, source_node); instruction->asm_template = asm_template; instruction->token_list = token_list; instruction->token_list_len = token_list_len; @@ -2292,12 +2313,12 @@ static IrInstruction *ir_build_asm(IrBuilder *irb, Scope *scope, AstNode *source assert(source_node->type == NodeTypeAsmExpr); for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { IrInstruction *output_type = output_types[i]; - if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); + if (output_type) ir_ref_instruction(output_type, ira->new_irb.current_basic_block); } for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { IrInstruction *input_value = input_list[i]; - ir_ref_instruction(input_value, irb->current_basic_block); + ir_ref_instruction(input_value, ira->new_irb.current_basic_block); } return &instruction->base; @@ -7494,7 +7515,7 @@ static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, Ast return ir_build_const_undefined(irb, scope, node); } -static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_template, +static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template, ZigList *tok_list) { // TODO Connect the errors in this function back up to the actual source location @@ -7542,7 +7563,7 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t cur_tok->end = i; state = StateStart; } else { - add_node_error(irb->codegen, source_node, + add_node_error(ira->codegen, source_node, buf_create_from_str("expected a '%' or '['")); return ErrorSemanticAnalyzeFail; } @@ -7565,7 +7586,7 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t { // do nothing } else { - add_node_error(irb->codegen, source_node, + add_node_error(ira->codegen, source_node, buf_sprintf("invalid substitution character: '%c'", c)); return ErrorSemanticAnalyzeFail; } @@ -7578,7 +7599,7 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t break; case StatePercent: case StateVar: - add_node_error(irb->codegen, source_node, buf_sprintf("unexpected end of assembly template")); + add_node_error(ira->codegen, source_node, buf_sprintf("unexpected end of assembly template")); return ErrorSemanticAnalyzeFail; case StateTemplate: cur_tok->end = buf_len(asm_template); @@ -7607,14 +7628,16 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ } static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *node) { - Error err; assert(node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &node->data.asm_expr; + + IrInstruction *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); + if (asm_template == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + bool is_volatile = asm_expr->volatile_token != nullptr; bool in_fn_scope = (scope_fn_entry(scope) != nullptr); - Buf *template_buf = &asm_expr->asm_template->data.str_lit.str; - if (!in_fn_scope) { if (is_volatile) { add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, @@ -7630,12 +7653,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod return irb->codegen->invalid_instruction; } - return ir_build_global_asm(irb, scope, node, template_buf); - } - - ZigList tok_list = {}; - if ((err = parse_asm_template(irb, node, template_buf, &tok_list))) { - return irb->codegen->invalid_instruction; + return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, + nullptr, 0, is_volatile, true); } IrInstruction **input_list = allocate(asm_expr->input_list.length); @@ -7693,24 +7712,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod input_list[i] = input_value; } - for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) { - AsmToken asm_token = tok_list.at(token_i); - if (asm_token.id == AsmTokenIdVar) { - size_t index = find_asm_index(irb->codegen, node, &asm_token, template_buf); - if (index == SIZE_MAX) { - const char *ptr = buf_ptr(template_buf) + asm_token.start + 2; - uint32_t len = asm_token.end - asm_token.start - 2; - - add_node_error(irb->codegen, node, - buf_sprintf("could not find '%.*s' in the inputs or outputs", - len, ptr)); - return irb->codegen->invalid_instruction; - } - } - } - - return ir_build_asm(irb, scope, node, template_buf, tok_list.items, tok_list.length, - input_list, output_types, output_vars, return_count, is_volatile); + return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types, + output_vars, return_count, is_volatile, false); } static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, @@ -20150,21 +20153,49 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, return result; } -static IrInstruction *ir_analyze_instruction_global_asm(IrAnalyze *ira, IrInstructionGlobalAsm *instruction) { - buf_append_char(&ira->codegen->global_asm, '\n'); - buf_append_buf(&ira->codegen->global_asm, instruction->asm_code); +static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsmSrc *asm_instruction) { + Error err; - return ir_const_void(ira, &instruction->base); -} - -static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) { assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); + AstNode *node = asm_instruction->base.source_node; AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr; + Buf *template_buf = ir_resolve_str(ira, asm_instruction->asm_template->child); + if (template_buf == nullptr) + return ira->codegen->invalid_instruction; + + if (asm_instruction->is_global) { + buf_append_char(&ira->codegen->global_asm, '\n'); + buf_append_buf(&ira->codegen->global_asm, template_buf); + + return ir_const_void(ira, &asm_instruction->base); + } + if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base)) return ira->codegen->invalid_instruction; + ZigList tok_list = {}; + if ((err = parse_asm_template(ira, node, template_buf, &tok_list))) { + return ira->codegen->invalid_instruction; + } + + for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) { + AsmToken asm_token = tok_list.at(token_i); + if (asm_token.id == AsmTokenIdVar) { + size_t index = find_asm_index(ira->codegen, node, &asm_token, template_buf); + if (index == SIZE_MAX) { + const char *ptr = buf_ptr(template_buf) + asm_token.start + 2; + uint32_t len = asm_token.end - asm_token.start - 2; + + add_node_error(ira->codegen, node, + buf_sprintf("could not find '%.*s' in the inputs or outputs", + len, ptr)); + return ira->codegen->invalid_instruction; + } + } + } + // TODO validate the output types and variable types IrInstruction **input_list = allocate(asm_expr->input_list.length); @@ -20197,9 +20228,9 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs input_list[i] = input_value; } - IrInstruction *result = ir_build_asm(&ira->new_irb, + IrInstruction *result = ir_build_asm_gen(ira, asm_instruction->base.scope, asm_instruction->base.source_node, - asm_instruction->asm_template, asm_instruction->token_list, asm_instruction->token_list_len, + template_buf, tok_list.items, tok_list.length, input_list, output_types, asm_instruction->output_vars, asm_instruction->return_count, asm_instruction->has_side_effects); result->value->type = return_type; @@ -27722,6 +27753,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction case IrInstructionIdSplatGen: case IrInstructionIdVectorExtractElem: case IrInstructionIdVectorStoreElem: + case IrInstructionIdAsmGen: zig_unreachable(); case IrInstructionIdReturn: @@ -27768,10 +27800,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_any_frame_type(ira, (IrInstructionAnyFrameType *)instruction); case IrInstructionIdSliceType: return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); - case IrInstructionIdGlobalAsm: - return ir_analyze_instruction_global_asm(ira, (IrInstructionGlobalAsm *)instruction); - case IrInstructionIdAsm: - return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction); + case IrInstructionIdAsmSrc: + return ir_analyze_instruction_asm(ira, (IrInstructionAsmSrc *)instruction); case IrInstructionIdArrayType: return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction); case IrInstructionIdSizeOf: @@ -28183,7 +28213,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdAssertZero: case IrInstructionIdAssertNonNull: case IrInstructionIdResizeSlice: - case IrInstructionIdGlobalAsm: case IrInstructionIdUndeclaredIdent: case IrInstructionIdEndExpr: case IrInstructionIdPtrOfArrayToSlice: @@ -28303,9 +28332,15 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdVectorExtractElem: return false; - case IrInstructionIdAsm: + case IrInstructionIdAsmSrc: { - IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction; + IrInstructionAsmSrc *asm_instruction = (IrInstructionAsmSrc *)instruction; + return asm_instruction->has_side_effects; + } + + case IrInstructionIdAsmGen: + { + IrInstructionAsmGen *asm_instruction = (IrInstructionAsmGen *)instruction; return asm_instruction->has_side_effects; } case IrInstructionIdUnwrapErrPayload: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 1ce111e1fd..bacdd82251 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -124,10 +124,10 @@ const char* ir_instruction_type_str(IrInstructionId id) { return "AnyFrameType"; case IrInstructionIdSliceType: return "SliceType"; - case IrInstructionIdGlobalAsm: - return "GlobalAsm"; - case IrInstructionIdAsm: - return "Asm"; + case IrInstructionIdAsmSrc: + return "AsmSrc"; + case IrInstructionIdAsmGen: + return "AsmGen"; case IrInstructionIdSizeOf: return "SizeOf"; case IrInstructionIdTestNonNull: @@ -888,11 +888,50 @@ static void ir_print_any_frame_type(IrPrint *irp, IrInstructionAnyFrameType *ins } } -static void ir_print_global_asm(IrPrint *irp, IrInstructionGlobalAsm *instruction) { - fprintf(irp->f, "asm(\"%s\")", buf_ptr(instruction->asm_code)); +static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) { + assert(instruction->base.source_node->type == NodeTypeAsmExpr); + AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr; + const char *volatile_kw = instruction->has_side_effects ? " volatile" : ""; + fprintf(irp->f, "asm%s (", volatile_kw); + ir_print_other_instruction(irp, instruction->asm_template); + + for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { + AsmOutput *asm_output = asm_expr->output_list.at(i); + if (i != 0) fprintf(irp->f, ", "); + + fprintf(irp->f, "[%s] \"%s\" (", + buf_ptr(asm_output->asm_symbolic_name), + buf_ptr(asm_output->constraint)); + if (asm_output->return_type) { + fprintf(irp->f, "-> "); + ir_print_other_instruction(irp, instruction->output_types[i]); + } else { + fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name)); + } + fprintf(irp->f, ")"); + } + + fprintf(irp->f, " : "); + for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { + AsmInput *asm_input = asm_expr->input_list.at(i); + + if (i != 0) fprintf(irp->f, ", "); + fprintf(irp->f, "[%s] \"%s\" (", + buf_ptr(asm_input->asm_symbolic_name), + buf_ptr(asm_input->constraint)); + ir_print_other_instruction(irp, instruction->input_list[i]); + fprintf(irp->f, ")"); + } + fprintf(irp->f, " : "); + for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) { + Buf *reg_name = asm_expr->clobber_list.at(i); + if (i != 0) fprintf(irp->f, ", "); + fprintf(irp->f, "\"%s\"", buf_ptr(reg_name)); + } + fprintf(irp->f, ")"); } -static void ir_print_asm(IrPrint *irp, IrInstructionAsm *instruction) { +static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { assert(instruction->base.source_node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr; const char *volatile_kw = instruction->has_side_effects ? " volatile" : ""; @@ -2121,11 +2160,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool case IrInstructionIdAnyFrameType: ir_print_any_frame_type(irp, (IrInstructionAnyFrameType *)instruction); break; - case IrInstructionIdGlobalAsm: - ir_print_global_asm(irp, (IrInstructionGlobalAsm *)instruction); + case IrInstructionIdAsmSrc: + ir_print_asm_src(irp, (IrInstructionAsmSrc *)instruction); break; - case IrInstructionIdAsm: - ir_print_asm(irp, (IrInstructionAsm *)instruction); + case IrInstructionIdAsmGen: + ir_print_asm_gen(irp, (IrInstructionAsmGen *)instruction); break; case IrInstructionIdSizeOf: ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); diff --git a/src/parser.cpp b/src/parser.cpp index 429566ecc1..665e048a89 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1891,7 +1891,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { Token *volatile_token = eat_token_if(pc, TokenIdKeywordVolatile); expect_token(pc, TokenIdLParen); - Token *asm_template = expect_token(pc, TokenIdStringLiteral); + AstNode *asm_template = ast_expect(pc, ast_parse_expr); AstNode *res = ast_parse_asm_output(pc); if (res == nullptr) res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);