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(...@@ -6422,52 +6422,17 @@ fn asmExpr(
6422 const asm_source = switch (node_tags[full.ast.template]) {6422 const asm_source = switch (node_tags[full.ast.template]) {
6423 .string_literal => try astgen.strLitAsString(main_tokens[full.ast.template]),6423 .string_literal => try astgen.strLitAsString(main_tokens[full.ast.template]),
6424 .multiline_string_literal => try astgen.strLitNodeAsString(full.ast.template),6424 .multiline_string_literal => try astgen.strLitNodeAsString(full.ast.template),
6425 else => {6425 else => blk: {
6426 // stage1 allows this, and until we do another design iteration on inline assembly6426 // stage1 allows this, and until we do another design iteration on inline assembly
6427 // in stage2 to improve support for the various needed use cases, we allow inline6427 // in stage2 to improve support for the various needed use cases, we allow inline
6428 // assembly templates to be an expression. Once stage2 addresses the real world needs6428 // assembly templates to be an expression. Once stage2 addresses the real world needs
6429 // of people using inline assembly (primarily OS developers) then we can re-institute6429 // of people using inline assembly (primarily OS developers) then we can re-institute
6430 // the rule into AstGen that assembly code must use string literal syntax.6430 // the rule into AstGen that assembly code must use string literal syntax.
6431 //return astgen.failNode(full.ast.template, "assembly code must use string literal syntax", .{}),6431 //return astgen.failNode(full.ast.template, "assembly code must use string literal syntax", .{}),
64326432 // We still need to trigger all the expr() calls here to avoid errors for unused things.
6433 // This code emits ZIR for6433 // So we pass 0 as the asm source and stage2 Sema will notice this and
6434 // `@compileError("assembly code must use string literal syntax")`6434 // report the error.
6435 // which allows it to make it to stage1 but gives the error for stage2.6435 break :blk IndexSlice{ .index = 0, .len = 0 };
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);
6471 },6436 },
6472 };6437 };
64736438
src/Sema.zig+6
...@@ -8226,6 +8226,12 @@ fn zirAsm(...@@ -8226,6 +8226,12 @@ fn zirAsm(
8226 const inputs_len = @truncate(u5, extended.small >> 5);8226 const inputs_len = @truncate(u5, extended.small >> 5);
8227 const clobbers_len = @truncate(u5, extended.small >> 10);8227 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
8229 if (outputs_len > 1) {8235 if (outputs_len > 1) {
8230 return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{});8236 return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{});
8231 }8237 }