Commit e1216077f0

Jacob Young <jacobly0@users.noreply.github.com>
2022-12-03 04:20:12
cbe: add support for constraint modifiers specified after a colon
This translates `%[name:mod]` to `%mod[name]` for C.
1 parent fdedd62
Changed files (2)
src
codegen
test
behavior
src/codegen/c.zig
@@ -4175,11 +4175,46 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
             extra_i += clobber.len / 4 + 1;
         }
     }
-    const asm_source = std.mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
+    {
+        const asm_source = std.mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
+
+        var stack = std.heap.stackFallback(256, f.object.dg.gpa);
+        const allocator = stack.get();
+        const fixed_asm_source = try allocator.alloc(u8, asm_source.len);
+        defer allocator.free(fixed_asm_source);
+
+        var src_i: usize = 0;
+        var dst_i: usize = 0;
+        while (src_i < asm_source.len) : (src_i += 1) {
+            fixed_asm_source[dst_i] = asm_source[src_i];
+            dst_i += 1;
+            if (asm_source[src_i] != '%' or src_i + 1 >= asm_source.len) continue;
+            src_i += 1;
+            if (asm_source[src_i] != '[') {
+                // This handles %%
+                fixed_asm_source[dst_i] = asm_source[src_i];
+                dst_i += 1;
+                continue;
+            }
+            const len = std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..], ']') orelse
+                return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source});
+            if (std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..][0..len], ':')) |colon| {
+                const modifier = asm_source[src_i + 1 + colon + 1 .. src_i + 1 + len];
+                std.mem.copy(u8, fixed_asm_source[dst_i..], modifier);
+                dst_i += modifier.len;
+
+                const name = asm_source[src_i .. src_i + 1 + colon];
+                std.mem.copy(u8, fixed_asm_source[dst_i..], name);
+                dst_i += name.len;
+
+                src_i += len;
+            }
+        }
 
-    try writer.writeAll("__asm");
-    if (is_volatile) try writer.writeAll(" volatile");
-    try writer.print("({s}", .{fmtStringLiteral(asm_source)});
+        try writer.writeAll("__asm");
+        if (is_volatile) try writer.writeAll(" volatile");
+        try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i])});
+    }
 
     extra_i = constraints_extra_begin;
     var locals_index = locals_begin;
test/behavior/asm.zig
@@ -140,7 +140,6 @@ export fn derp() i32 {
 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]"