authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-01 16:24:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-01 16:24:44-07:00
log1912ec0323af9a9077a8706157beb8207f6e3eb9
tree7e94761acb4c3b773ee0d9ae0d0206f7417b3204
parent0714832c21169493a0a857237fbface612e3d5e0

AstGen: use null string to communicate non-string-literal asm

dd62a6d2e8de522187fd096354e7156cca1821c5 short-circuited the logic of `asmExpr` by emitting ZIR for `@compileError("...")`. This caused false positive "unreachable code" errors for stage1 when there was an expression in the asm template. This commit makes such cases instead go through logic of `asmExpr` like normal, however the asm template is set to 0. This is then picked up in Sema (part of stage2, not stage1) and reported as "assembly code must use string literal syntax".

2 files changed, 11 insertions(+), 40 deletions(-)

src/AstGen.zig+5-40
......@@ -6422,52 +6422,17 @@ fn asmExpr(
64226422 const asm_source = switch (node_tags[full.ast.template]) {
64236423 .string_literal => try astgen.strLitAsString(main_tokens[full.ast.template]),
64246424 .multiline_string_literal => try astgen.strLitNodeAsString(full.ast.template),
6425 else => {
6425 else => blk: {
64266426 // stage1 allows this, and until we do another design iteration on inline assembly
64276427 // in stage2 to improve support for the various needed use cases, we allow inline
64286428 // assembly templates to be an expression. Once stage2 addresses the real world needs
64296429 // of people using inline assembly (primarily OS developers) then we can re-institute
64306430 // the rule into AstGen that assembly code must use string literal syntax.
64316431 //return astgen.failNode(full.ast.template, "assembly code must use string literal syntax", .{}),
6432
6433 // This code emits ZIR for
6434 // `@compileError("assembly code must use string literal syntax")`
6435 // which allows it to make it to stage1 but gives the error for stage2.
6436 const string_bytes = &astgen.string_bytes;
6437 const str_index = @intCast(u32, string_bytes.items.len);
6438 try string_bytes.appendSlice(astgen.gpa, "assembly code must use string literal syntax");
6439 const key = string_bytes.items[str_index..];
6440 const gop = try astgen.string_table.getOrPutContextAdapted(astgen.gpa, @as([]const u8, key), StringIndexAdapter{
6441 .bytes = string_bytes,
6442 }, StringIndexContext{
6443 .bytes = string_bytes,
6444 });
6445 const str = if (gop.found_existing) str: {
6446 string_bytes.shrinkRetainingCapacity(str_index);
6447 break :str IndexSlice{
6448 .index = gop.key_ptr.*,
6449 .len = @intCast(u32, key.len),
6450 };
6451 } else str: {
6452 gop.key_ptr.* = str_index;
6453 // Still need a null byte because we are using the same table
6454 // to lookup null terminated strings, so if we get a match, it has to
6455 // be null terminated for that to work.
6456 try string_bytes.append(astgen.gpa, 0);
6457 break :str IndexSlice{
6458 .index = str_index,
6459 .len = @intCast(u32, key.len),
6460 };
6461 };
6462 const msg = try gz.add(.{
6463 .tag = .str,
6464 .data = .{ .str = .{
6465 .start = str.index,
6466 .len = str.len,
6467 } },
6468 });
6469 const result = try gz.addUnNode(.compile_error, msg, node);
6470 return rvalue(gz, rl, result, node);
6432 // We still need to trigger all the expr() calls here to avoid errors for unused things.
6433 // So we pass 0 as the asm source and stage2 Sema will notice this and
6434 // report the error.
6435 break :blk IndexSlice{ .index = 0, .len = 0 };
64716436 },
64726437 };
64736438
src/Sema.zig+6
......@@ -8226,6 +8226,12 @@ fn zirAsm(
82268226 const inputs_len = @truncate(u5, extended.small >> 5);
82278227 const clobbers_len = @truncate(u5, extended.small >> 10);
82288228
8229 if (extra.data.asm_source == 0) {
8230 // This can move to become an AstGen error after inline assembly improvements land
8231 // and stage1 code matches stage2 code.
8232 return sema.fail(block, src, "assembly code must use string literal syntax", .{});
8233 }
8234
82298235 if (outputs_len > 1) {
82308236 return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{});
82318237 }