Commit dd62a6d2e8

Andrew Kelley <andrew@ziglang.org>
2021-12-01 03:41:14
AstGen: allow non-string-literal inline assembly for stage1
The end-game for inline assembly is that the syntax is more integrated with zig, and it will not allow string concatenation for the assembler code, for the same reasons that Zig does not have a preprocessor. However, inline assembly in zig right now is lacking for a variety of use cases (take a look at the open issues having to do with inline assembly for example), and being able to use comptime expressions to concatenate text is a workaround that real-world users are exploiting to get by in the short term. This commit keeps "assembly code must use string literal syntax" as a compile error when using stage2, but allows it through when using stage1. I expect to revert this commit after making enough improvements to inline assembly that our real world users' needs are satisfied.
1 parent f2608df
Changed files (1)
src/AstGen.zig
@@ -6421,7 +6421,53 @@ fn asmExpr(
     const asm_source = switch (node_tags[full.ast.template]) {
         .string_literal => try astgen.strLitAsString(main_tokens[full.ast.template]),
         .multiline_string_literal => try astgen.strLitNodeAsString(full.ast.template),
-        else => return astgen.failNode(full.ast.template, "assembly code must use string literal syntax", .{}),
+        else => {
+            // stage1 allows this, and until we do another design iteration on inline assembly
+            // in stage2 to improve support for the various needed use cases, we allow inline
+            // assembly templates to be an expression. Once stage2 addresses the real world needs
+            // of people using inline assembly (primarily OS developers) then we can re-institute
+            // the rule into AstGen that assembly code must use string literal syntax.
+            //return astgen.failNode(full.ast.template, "assembly code must use string literal syntax", .{}),
+
+            // This code emits ZIR for
+            // `@compileError("assembly code must use string literal syntax")`
+            // which allows it to make it to stage1 but gives the error for stage2.
+            const string_bytes = &astgen.string_bytes;
+            const str_index = @intCast(u32, string_bytes.items.len);
+            try string_bytes.appendSlice(astgen.gpa, "assembly code must use string literal syntax");
+            const key = string_bytes.items[str_index..];
+            const gop = try astgen.string_table.getOrPutContextAdapted(astgen.gpa, @as([]const u8, key), StringIndexAdapter{
+                .bytes = string_bytes,
+            }, StringIndexContext{
+                .bytes = string_bytes,
+            });
+            const str = if (gop.found_existing) str: {
+                string_bytes.shrinkRetainingCapacity(str_index);
+                break :str IndexSlice{
+                    .index = gop.key_ptr.*,
+                    .len = @intCast(u32, key.len),
+                };
+            } else str: {
+                gop.key_ptr.* = str_index;
+                // Still need a null byte because we are using the same table
+                // to lookup null terminated strings, so if we get a match, it has to
+                // be null terminated for that to work.
+                try string_bytes.append(astgen.gpa, 0);
+                break :str IndexSlice{
+                    .index = str_index,
+                    .len = @intCast(u32, key.len),
+                };
+            };
+            const msg = try gz.add(.{
+                .tag = .str,
+                .data = .{ .str = .{
+                    .start = str.index,
+                    .len = str.len,
+                } },
+            });
+            const result = try gz.addUnNode(.compile_error, msg, node);
+            return rvalue(gz, rl, result, node);
+        },
     };
 
     // See https://github.com/ziglang/zig/issues/215 and related issues discussing