authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-12-02 21:07:44+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-02 19:53:06-05:00
log26c8930b9594ab320b0e3add682e99063491142e
tree7c7162c26e30f92598cdcbf4a2309512bcdfd373
parentb7be57766b8c6d7fee27fd7c23e8c999a134bb27

Accept comptime-known expression for asm


8 files changed, 193 insertions(+), 88 deletions(-)

lib/std/zig/parse.zig+3-3
......@@ -1495,13 +1495,13 @@ fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
14951495 return &node.base;
14961496}
14971497
1498/// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
1498/// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN
14991499fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15001500 const asm_token = eatToken(it, .Keyword_asm) orelse return null;
15011501 const volatile_token = eatToken(it, .Keyword_volatile);
15021502 _ = try expectToken(it, tree, .LParen);
1503 const template = try expectNode(arena, it, tree, parseStringLiteral, AstError{
1504 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },
1503 const template = try expectNode(arena, it, tree, parseExpr, AstError{
1504 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
15051505 });
15061506
15071507 const node = try arena.create(Node.Asm);
lib/std/zig/parser_test.zig+23
......@@ -1,3 +1,26 @@
1test "zig fmt: asm expression with comptime content" {
2 try testCanonical(
3 \\comptime {
4 \\ asm ("foo" ++ "bar");
5 \\}
6 \\pub fn main() void {
7 \\ asm volatile ("foo" ++ "bar");
8 \\ asm volatile ("foo" ++ "bar"
9 \\ : [_] "" (x)
10 \\ );
11 \\ asm volatile ("foo" ++ "bar"
12 \\ : [_] "" (x)
13 \\ : [_] "" (y)
14 \\ );
15 \\ asm volatile ("foo" ++ "bar"
16 \\ : [_] "" (x)
17 \\ : [_] "" (y)
18 \\ : "h", "e", "l", "l", "o"
19 \\ );
20 \\}
21 \\
22 );
23}
124test "zig fmt: var struct field" {
225 try testCanonical(
326 \\pub const Pointer = struct {
src/all_types.hpp+12-6
......@@ -949,7 +949,7 @@ struct AsmToken {
949949
950950struct AstNodeAsmExpr {
951951 Token *volatile_token;
952 Token *asm_template;
952 AstNode *asm_template;
953953 ZigList<AsmOutput*> output_list;
954954 ZigList<AsmInput*> input_list;
955955 ZigList<Buf*> clobber_list;
......@@ -2496,8 +2496,8 @@ enum IrInstructionId {
24962496 IrInstructionIdArrayType,
24972497 IrInstructionIdAnyFrameType,
24982498 IrInstructionIdSliceType,
2499 IrInstructionIdGlobalAsm,
2500 IrInstructionIdAsm,
2499 IrInstructionIdAsmSrc,
2500 IrInstructionIdAsmGen,
25012501 IrInstructionIdSizeOf,
25022502 IrInstructionIdTestNonNull,
25032503 IrInstructionIdOptionalUnwrapPtr,
......@@ -3049,13 +3049,19 @@ struct IrInstructionSliceType {
30493049 bool is_allow_zero;
30503050};
30513051
3052struct IrInstructionGlobalAsm {
3052struct IrInstructionAsmSrc {
30533053 IrInstruction base;
30543054
3055 Buf *asm_code;
3055 IrInstruction *asm_template;
3056 IrInstruction **input_list;
3057 IrInstruction **output_types;
3058 ZigVar **output_vars;
3059 size_t return_count;
3060 bool has_side_effects;
3061 bool is_global;
30563062};
30573063
3058struct IrInstructionAsm {
3064struct IrInstructionAsmGen {
30593065 IrInstruction base;
30603066
30613067 Buf *asm_template;
src/ast_render.cpp+3-1
......@@ -884,7 +884,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
884884 {
885885 AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
886886 const char *volatile_str = (asm_expr->volatile_token != nullptr) ? " volatile" : "";
887 fprintf(ar->f, "asm%s (\"%s\"\n", volatile_str, buf_ptr(&asm_expr->asm_template->data.str_lit.str));
887 fprintf(ar->f, "asm%s (", volatile_str);
888 render_node_ungrouped(ar, asm_expr->asm_template);
889 fprintf(ar->f, ")");
888890 print_indent(ar);
889891 fprintf(ar->f, ": ");
890892 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
src/codegen.cpp+4-4
......@@ -4437,7 +4437,7 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_
44374437 return SIZE_MAX;
44384438}
44394439
4440static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstructionAsm *instruction) {
4440static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutable *executable, IrInstructionAsmGen *instruction) {
44414441 AstNode *asm_node = instruction->base.source_node;
44424442 assert(asm_node->type == NodeTypeAsmExpr);
44434443 AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr;
......@@ -6135,7 +6135,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61356135 case IrInstructionIdPtrCastSrc:
61366136 case IrInstructionIdCmpxchgSrc:
61376137 case IrInstructionIdLoadPtr:
6138 case IrInstructionIdGlobalAsm:
61396138 case IrInstructionIdHasDecl:
61406139 case IrInstructionIdUndeclaredIdent:
61416140 case IrInstructionIdCallSrc:
......@@ -6156,6 +6155,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61566155 case IrInstructionIdAwaitSrc:
61576156 case IrInstructionIdSplatSrc:
61586157 case IrInstructionIdMergeErrSets:
6158 case IrInstructionIdAsmSrc:
61596159 zig_unreachable();
61606160
61616161 case IrInstructionIdDeclVarGen:
......@@ -6192,8 +6192,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61926192 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
61936193 case IrInstructionIdUnionFieldPtr:
61946194 return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);
6195 case IrInstructionIdAsm:
6196 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
6195 case IrInstructionIdAsmGen:
6196 return ir_render_asm_gen(g, executable, (IrInstructionAsmGen *)instruction);
61976197 case IrInstructionIdTestNonNull:
61986198 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
61996199 case IrInstructionIdOptionalUnwrapPtr:
src/ir.cpp+97-62
......@@ -339,10 +339,10 @@ static void destroy_instruction(IrInstruction *inst) {
339339 return destroy(reinterpret_cast<IrInstructionSliceType *>(inst), name);
340340 case IrInstructionIdAnyFrameType:
341341 return destroy(reinterpret_cast<IrInstructionAnyFrameType *>(inst), name);
342 case IrInstructionIdGlobalAsm:
343 return destroy(reinterpret_cast<IrInstructionGlobalAsm *>(inst), name);
344 case IrInstructionIdAsm:
345 return destroy(reinterpret_cast<IrInstructionAsm *>(inst), name);
342 case IrInstructionIdAsmSrc:
343 return destroy(reinterpret_cast<IrInstructionAsmSrc *>(inst), name);
344 case IrInstructionIdAsmGen:
345 return destroy(reinterpret_cast<IrInstructionAsmGen *>(inst), name);
346346 case IrInstructionIdSizeOf:
347347 return destroy(reinterpret_cast<IrInstructionSizeOf *>(inst), name);
348348 case IrInstructionIdTestNonNull:
......@@ -1028,12 +1028,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
10281028 return IrInstructionIdSliceType;
10291029}
10301030
1031static constexpr IrInstructionId ir_instruction_id(IrInstructionGlobalAsm *) {
1032 return IrInstructionIdGlobalAsm;
1031static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmSrc *) {
1032 return IrInstructionIdAsmSrc;
10331033}
10341034
1035static constexpr IrInstructionId ir_instruction_id(IrInstructionAsm *) {
1036 return IrInstructionIdAsm;
1035static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmGen *) {
1036 return IrInstructionIdAsmGen;
10371037}
10381038
10391039static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) {
......@@ -2268,18 +2268,39 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode
22682268 return &instruction->base;
22692269}
22702270
2271static IrInstruction *ir_build_global_asm(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *asm_code) {
2272 IrInstructionGlobalAsm *instruction = ir_build_instruction<IrInstructionGlobalAsm>(irb, scope, source_node);
2273 instruction->asm_code = asm_code;
2271static IrInstruction *ir_build_asm_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2272 IrInstruction *asm_template, IrInstruction **input_list, IrInstruction **output_types,
2273 ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global)
2274{
2275 IrInstructionAsmSrc *instruction = ir_build_instruction<IrInstructionAsmSrc>(irb, scope, source_node);
2276 instruction->asm_template = asm_template;
2277 instruction->input_list = input_list;
2278 instruction->output_types = output_types;
2279 instruction->output_vars = output_vars;
2280 instruction->return_count = return_count;
2281 instruction->has_side_effects = has_side_effects;
2282 instruction->is_global = is_global;
2283
2284 assert(source_node->type == NodeTypeAsmExpr);
2285 for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) {
2286 IrInstruction *output_type = output_types[i];
2287 if (output_type) ir_ref_instruction(output_type, irb->current_basic_block);
2288 }
2289
2290 for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) {
2291 IrInstruction *input_value = input_list[i];
2292 ir_ref_instruction(input_value, irb->current_basic_block);
2293 }
2294
22742295 return &instruction->base;
22752296}
22762297
2277static IrInstruction *ir_build_asm(IrBuilder *irb, Scope *scope, AstNode *source_node,
2298static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
22782299 Buf *asm_template, AsmToken *token_list, size_t token_list_len,
22792300 IrInstruction **input_list, IrInstruction **output_types, ZigVar **output_vars, size_t return_count,
22802301 bool has_side_effects)
22812302{
2282 IrInstructionAsm *instruction = ir_build_instruction<IrInstructionAsm>(irb, scope, source_node);
2303 IrInstructionAsmGen *instruction = ir_build_instruction<IrInstructionAsmGen>(&ira->new_irb, scope, source_node);
22832304 instruction->asm_template = asm_template;
22842305 instruction->token_list = token_list;
22852306 instruction->token_list_len = token_list_len;
......@@ -2292,12 +2313,12 @@ static IrInstruction *ir_build_asm(IrBuilder *irb, Scope *scope, AstNode *source
22922313 assert(source_node->type == NodeTypeAsmExpr);
22932314 for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) {
22942315 IrInstruction *output_type = output_types[i];
2295 if (output_type) ir_ref_instruction(output_type, irb->current_basic_block);
2316 if (output_type) ir_ref_instruction(output_type, ira->new_irb.current_basic_block);
22962317 }
22972318
22982319 for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) {
22992320 IrInstruction *input_value = input_list[i];
2300 ir_ref_instruction(input_value, irb->current_basic_block);
2321 ir_ref_instruction(input_value, ira->new_irb.current_basic_block);
23012322 }
23022323
23032324 return &instruction->base;
......@@ -7494,7 +7515,7 @@ static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, Ast
74947515 return ir_build_const_undefined(irb, scope, node);
74957516}
74967517
7497static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_template,
7518static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template,
74987519 ZigList<AsmToken> *tok_list)
74997520{
75007521 // 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
75427563 cur_tok->end = i;
75437564 state = StateStart;
75447565 } else {
7545 add_node_error(irb->codegen, source_node,
7566 add_node_error(ira->codegen, source_node,
75467567 buf_create_from_str("expected a '%' or '['"));
75477568 return ErrorSemanticAnalyzeFail;
75487569 }
......@@ -7565,7 +7586,7 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t
75657586 {
75667587 // do nothing
75677588 } else {
7568 add_node_error(irb->codegen, source_node,
7589 add_node_error(ira->codegen, source_node,
75697590 buf_sprintf("invalid substitution character: '%c'", c));
75707591 return ErrorSemanticAnalyzeFail;
75717592 }
......@@ -7578,7 +7599,7 @@ static Error parse_asm_template(IrBuilder *irb, AstNode *source_node, Buf *asm_t
75787599 break;
75797600 case StatePercent:
75807601 case StateVar:
7581 add_node_error(irb->codegen, source_node, buf_sprintf("unexpected end of assembly template"));
7602 add_node_error(ira->codegen, source_node, buf_sprintf("unexpected end of assembly template"));
75827603 return ErrorSemanticAnalyzeFail;
75837604 case StateTemplate:
75847605 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_
76077628}
76087629
76097630static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
7610 Error err;
76117631 assert(node->type == NodeTypeAsmExpr);
76127632 AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
7633
7634 IrInstruction *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope);
7635 if (asm_template == irb->codegen->invalid_instruction)
7636 return irb->codegen->invalid_instruction;
7637
76137638 bool is_volatile = asm_expr->volatile_token != nullptr;
76147639 bool in_fn_scope = (scope_fn_entry(scope) != nullptr);
76157640
7616 Buf *template_buf = &asm_expr->asm_template->data.str_lit.str;
7617
76187641 if (!in_fn_scope) {
76197642 if (is_volatile) {
76207643 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
76307653 return irb->codegen->invalid_instruction;
76317654 }
76327655
7633 return ir_build_global_asm(irb, scope, node, template_buf);
7634 }
7635
7636 ZigList<AsmToken> tok_list = {};
7637 if ((err = parse_asm_template(irb, node, template_buf, &tok_list))) {
7638 return irb->codegen->invalid_instruction;
7656 return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr,
7657 nullptr, 0, is_volatile, true);
76397658 }
76407659
76417660 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
76937712 input_list[i] = input_value;
76947713 }
76957714
7696 for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) {
7697 AsmToken asm_token = tok_list.at(token_i);
7698 if (asm_token.id == AsmTokenIdVar) {
7699 size_t index = find_asm_index(irb->codegen, node, &asm_token, template_buf);
7700 if (index == SIZE_MAX) {
7701 const char *ptr = buf_ptr(template_buf) + asm_token.start + 2;
7702 uint32_t len = asm_token.end - asm_token.start - 2;
7703
7704 add_node_error(irb->codegen, node,
7705 buf_sprintf("could not find '%.*s' in the inputs or outputs",
7706 len, ptr));
7707 return irb->codegen->invalid_instruction;
7708 }
7709 }
7710 }
7711
7712 return ir_build_asm(irb, scope, node, template_buf, tok_list.items, tok_list.length,
7713 input_list, output_types, output_vars, return_count, is_volatile);
7715 return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types,
7716 output_vars, return_count, is_volatile, false);
77147717}
77157718
77167719static 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,
2015020153 return result;
2015120154}
2015220155
20153static IrInstruction *ir_analyze_instruction_global_asm(IrAnalyze *ira, IrInstructionGlobalAsm *instruction) {
20154 buf_append_char(&ira->codegen->global_asm, '\n');
20155 buf_append_buf(&ira->codegen->global_asm, instruction->asm_code);
20156
20157 return ir_const_void(ira, &instruction->base);
20158}
20156static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsmSrc *asm_instruction) {
20157 Error err;
2015920158
20160static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) {
2016120159 assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr);
2016220160
20161 AstNode *node = asm_instruction->base.source_node;
2016320162 AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
2016420163
20164 Buf *template_buf = ir_resolve_str(ira, asm_instruction->asm_template->child);
20165 if (template_buf == nullptr)
20166 return ira->codegen->invalid_instruction;
20167
20168 if (asm_instruction->is_global) {
20169 buf_append_char(&ira->codegen->global_asm, '\n');
20170 buf_append_buf(&ira->codegen->global_asm, template_buf);
20171
20172 return ir_const_void(ira, &asm_instruction->base);
20173 }
20174
2016520175 if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base))
2016620176 return ira->codegen->invalid_instruction;
2016720177
20178 ZigList<AsmToken> tok_list = {};
20179 if ((err = parse_asm_template(ira, node, template_buf, &tok_list))) {
20180 return ira->codegen->invalid_instruction;
20181 }
20182
20183 for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) {
20184 AsmToken asm_token = tok_list.at(token_i);
20185 if (asm_token.id == AsmTokenIdVar) {
20186 size_t index = find_asm_index(ira->codegen, node, &asm_token, template_buf);
20187 if (index == SIZE_MAX) {
20188 const char *ptr = buf_ptr(template_buf) + asm_token.start + 2;
20189 uint32_t len = asm_token.end - asm_token.start - 2;
20190
20191 add_node_error(ira->codegen, node,
20192 buf_sprintf("could not find '%.*s' in the inputs or outputs",
20193 len, ptr));
20194 return ira->codegen->invalid_instruction;
20195 }
20196 }
20197 }
20198
2016820199 // TODO validate the output types and variable types
2016920200
2017020201 IrInstruction **input_list = allocate<IrInstruction *>(asm_expr->input_list.length);
......@@ -20197,9 +20228,9 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs
2019720228 input_list[i] = input_value;
2019820229 }
2019920230
20200 IrInstruction *result = ir_build_asm(&ira->new_irb,
20231 IrInstruction *result = ir_build_asm_gen(ira,
2020120232 asm_instruction->base.scope, asm_instruction->base.source_node,
20202 asm_instruction->asm_template, asm_instruction->token_list, asm_instruction->token_list_len,
20233 template_buf, tok_list.items, tok_list.length,
2020320234 input_list, output_types, asm_instruction->output_vars, asm_instruction->return_count,
2020420235 asm_instruction->has_side_effects);
2020520236 result->value->type = return_type;
......@@ -27722,6 +27753,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2772227753 case IrInstructionIdSplatGen:
2772327754 case IrInstructionIdVectorExtractElem:
2772427755 case IrInstructionIdVectorStoreElem:
27756 case IrInstructionIdAsmGen:
2772527757 zig_unreachable();
2772627758
2772727759 case IrInstructionIdReturn:
......@@ -27768,10 +27800,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2776827800 return ir_analyze_instruction_any_frame_type(ira, (IrInstructionAnyFrameType *)instruction);
2776927801 case IrInstructionIdSliceType:
2777027802 return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
27771 case IrInstructionIdGlobalAsm:
27772 return ir_analyze_instruction_global_asm(ira, (IrInstructionGlobalAsm *)instruction);
27773 case IrInstructionIdAsm:
27774 return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction);
27803 case IrInstructionIdAsmSrc:
27804 return ir_analyze_instruction_asm(ira, (IrInstructionAsmSrc *)instruction);
2777527805 case IrInstructionIdArrayType:
2777627806 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
2777727807 case IrInstructionIdSizeOf:
......@@ -28183,7 +28213,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2818328213 case IrInstructionIdAssertZero:
2818428214 case IrInstructionIdAssertNonNull:
2818528215 case IrInstructionIdResizeSlice:
28186 case IrInstructionIdGlobalAsm:
2818728216 case IrInstructionIdUndeclaredIdent:
2818828217 case IrInstructionIdEndExpr:
2818928218 case IrInstructionIdPtrOfArrayToSlice:
......@@ -28303,9 +28332,15 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2830328332 case IrInstructionIdVectorExtractElem:
2830428333 return false;
2830528334
28306 case IrInstructionIdAsm:
28335 case IrInstructionIdAsmSrc:
28336 {
28337 IrInstructionAsmSrc *asm_instruction = (IrInstructionAsmSrc *)instruction;
28338 return asm_instruction->has_side_effects;
28339 }
28340
28341 case IrInstructionIdAsmGen:
2830728342 {
28308 IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction;
28343 IrInstructionAsmGen *asm_instruction = (IrInstructionAsmGen *)instruction;
2830928344 return asm_instruction->has_side_effects;
2831028345 }
2831128346 case IrInstructionIdUnwrapErrPayload:
src/ir_print.cpp+50-11
......@@ -124,10 +124,10 @@ const char* ir_instruction_type_str(IrInstructionId id) {
124124 return "AnyFrameType";
125125 case IrInstructionIdSliceType:
126126 return "SliceType";
127 case IrInstructionIdGlobalAsm:
128 return "GlobalAsm";
129 case IrInstructionIdAsm:
130 return "Asm";
127 case IrInstructionIdAsmSrc:
128 return "AsmSrc";
129 case IrInstructionIdAsmGen:
130 return "AsmGen";
131131 case IrInstructionIdSizeOf:
132132 return "SizeOf";
133133 case IrInstructionIdTestNonNull:
......@@ -888,11 +888,50 @@ static void ir_print_any_frame_type(IrPrint *irp, IrInstructionAnyFrameType *ins
888888 }
889889}
890890
891static void ir_print_global_asm(IrPrint *irp, IrInstructionGlobalAsm *instruction) {
892 fprintf(irp->f, "asm(\"%s\")", buf_ptr(instruction->asm_code));
891static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) {
892 assert(instruction->base.source_node->type == NodeTypeAsmExpr);
893 AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr;
894 const char *volatile_kw = instruction->has_side_effects ? " volatile" : "";
895 fprintf(irp->f, "asm%s (", volatile_kw);
896 ir_print_other_instruction(irp, instruction->asm_template);
897
898 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
899 AsmOutput *asm_output = asm_expr->output_list.at(i);
900 if (i != 0) fprintf(irp->f, ", ");
901
902 fprintf(irp->f, "[%s] \"%s\" (",
903 buf_ptr(asm_output->asm_symbolic_name),
904 buf_ptr(asm_output->constraint));
905 if (asm_output->return_type) {
906 fprintf(irp->f, "-> ");
907 ir_print_other_instruction(irp, instruction->output_types[i]);
908 } else {
909 fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name));
910 }
911 fprintf(irp->f, ")");
912 }
913
914 fprintf(irp->f, " : ");
915 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
916 AsmInput *asm_input = asm_expr->input_list.at(i);
917
918 if (i != 0) fprintf(irp->f, ", ");
919 fprintf(irp->f, "[%s] \"%s\" (",
920 buf_ptr(asm_input->asm_symbolic_name),
921 buf_ptr(asm_input->constraint));
922 ir_print_other_instruction(irp, instruction->input_list[i]);
923 fprintf(irp->f, ")");
924 }
925 fprintf(irp->f, " : ");
926 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) {
927 Buf *reg_name = asm_expr->clobber_list.at(i);
928 if (i != 0) fprintf(irp->f, ", ");
929 fprintf(irp->f, "\"%s\"", buf_ptr(reg_name));
930 }
931 fprintf(irp->f, ")");
893932}
894933
895static void ir_print_asm(IrPrint *irp, IrInstructionAsm *instruction) {
934static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) {
896935 assert(instruction->base.source_node->type == NodeTypeAsmExpr);
897936 AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr;
898937 const char *volatile_kw = instruction->has_side_effects ? " volatile" : "";
......@@ -2121,11 +2160,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
21212160 case IrInstructionIdAnyFrameType:
21222161 ir_print_any_frame_type(irp, (IrInstructionAnyFrameType *)instruction);
21232162 break;
2124 case IrInstructionIdGlobalAsm:
2125 ir_print_global_asm(irp, (IrInstructionGlobalAsm *)instruction);
2163 case IrInstructionIdAsmSrc:
2164 ir_print_asm_src(irp, (IrInstructionAsmSrc *)instruction);
21262165 break;
2127 case IrInstructionIdAsm:
2128 ir_print_asm(irp, (IrInstructionAsm *)instruction);
2166 case IrInstructionIdAsmGen:
2167 ir_print_asm_gen(irp, (IrInstructionAsmGen *)instruction);
21292168 break;
21302169 case IrInstructionIdSizeOf:
21312170 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
src/parser.cpp+1-1
......@@ -1891,7 +1891,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) {
18911891
18921892 Token *volatile_token = eat_token_if(pc, TokenIdKeywordVolatile);
18931893 expect_token(pc, TokenIdLParen);
1894 Token *asm_template = expect_token(pc, TokenIdStringLiteral);
1894 AstNode *asm_template = ast_expect(pc, ast_parse_expr);
18951895 AstNode *res = ast_parse_asm_output(pc);
18961896 if (res == nullptr)
18971897 res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);