From bc3324365090f3c9077df147b52fbc0c3c19b753 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Thu, 10 Nov 2022 14:02:05 -0700 Subject: [PATCH] stage2: Support modifiers in inline asm These are supported using %[ident:mod] syntax. This allows requesting, e.g., the "w" (32-bit) vs. "x" (64-bit) views of AArch64 registers. See https://llvm.org/docs/LangRef.html#asm-template-argument-modifiers --- src/codegen/llvm.zig | 23 ++++++++++++++++++++--- test/behavior/asm.zig | 13 +++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 024d6742cb..b6834ad192 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -6290,11 +6290,12 @@ pub const FuncGen = struct { var rendered_template = std.ArrayList(u8).init(self.gpa); defer rendered_template.deinit(); - const State = enum { start, percent, input }; + const State = enum { start, percent, input, modifier }; var state: State = .start; var name_start: usize = undefined; + var modifier_start: usize = undefined; for (asm_source) |byte, i| { switch (state) { .start => switch (byte) { @@ -6309,6 +6310,7 @@ pub const FuncGen = struct { }, '[' => { try rendered_template.append('$'); + try rendered_template.append('{'); name_start = i + 1; state = .input; }, @@ -6319,15 +6321,30 @@ pub const FuncGen = struct { }, }, .input => switch (byte) { - ']' => { + ']', ':' => { const name = asm_source[name_start..i]; - state = .start; const index = name_map.get(name) orelse { // we should validate the assembly in Sema; by now it is too late return self.todo("unknown input or output name: '{s}'", .{name}); }; try rendered_template.writer().print("{d}", .{index}); + if (byte == ':') { + try rendered_template.append(':'); + modifier_start = i + 1; + state = .modifier; + } else { + try rendered_template.append('}'); + state = .start; + } + }, + else => {}, + }, + .modifier => switch (byte) { + ']' => { + try rendered_template.appendSlice(asm_source[modifier_start..i]); + try rendered_template.append('}'); + state = .start; }, else => {}, }, diff --git a/test/behavior/asm.zig b/test/behavior/asm.zig index fd1601bf06..106690d820 100644 --- a/test/behavior/asm.zig +++ b/test/behavior/asm.zig @@ -136,3 +136,16 @@ extern fn this_is_my_alias() i32; export fn derp() i32 { return 1234; } + +test "asm modifiers (AArch64)" { + if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + + var x: u32 = 15; + const double = asm ("add %[ret:w], %[in:w], %[in:w]" + : [ret] "=r" (-> u32), + : [in] "r" (x), + ); + try expect(double == 2 * x); +}