Commit 26c8930b95
Changed files (8)
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);
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 {
src/all_types.hpp
@@ -949,7 +949,7 @@ struct AsmToken {
struct AstNodeAsmExpr {
Token *volatile_token;
- Token *asm_template;
+ AstNode *asm_template;
ZigList<AsmOutput*> output_list;
ZigList<AsmInput*> input_list;
ZigList<Buf*> 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;
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) {
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:
src/ir.cpp
@@ -339,10 +339,10 @@ static void destroy_instruction(IrInstruction *inst) {
return destroy(reinterpret_cast<IrInstructionSliceType *>(inst), name);
case IrInstructionIdAnyFrameType:
return destroy(reinterpret_cast<IrInstructionAnyFrameType *>(inst), name);
- case IrInstructionIdGlobalAsm:
- return destroy(reinterpret_cast<IrInstructionGlobalAsm *>(inst), name);
- case IrInstructionIdAsm:
- return destroy(reinterpret_cast<IrInstructionAsm *>(inst), name);
+ case IrInstructionIdAsmSrc:
+ return destroy(reinterpret_cast<IrInstructionAsmSrc *>(inst), name);
+ case IrInstructionIdAsmGen:
+ return destroy(reinterpret_cast<IrInstructionAsmGen *>(inst), name);
case IrInstructionIdSizeOf:
return destroy(reinterpret_cast<IrInstructionSizeOf *>(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<IrInstructionGlobalAsm>(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<IrInstructionAsmSrc>(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<IrInstructionAsm>(irb, scope, source_node);
+ IrInstructionAsmGen *instruction = ir_build_instruction<IrInstructionAsmGen>(&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<AsmToken> *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<AsmToken> 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<IrInstruction *>(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);
-
- return ir_const_void(ira, &instruction->base);
-}
+static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsmSrc *asm_instruction) {
+ Error err;
-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<AsmToken> 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<IrInstruction *>(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:
+ {
+ IrInstructionAsmSrc *asm_instruction = (IrInstructionAsmSrc *)instruction;
+ return asm_instruction->has_side_effects;
+ }
+
+ case IrInstructionIdAsmGen:
{
- IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction;
+ IrInstructionAsmGen *asm_instruction = (IrInstructionAsmGen *)instruction;
return asm_instruction->has_side_effects;
}
case IrInstructionIdUnwrapErrPayload:
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);
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);