CBE: improve support for asm inputs

This is not complete support for asm expressions, but allows a few more
test cases from test/behavior/asm.zig to pass. Since the non-register
inputs are named `input_${n}` they can cause name collisions: I'm
wrapping the asm expressions in their own block to prevent that.

Contextually, this change also makes test/behavior/asm.zig run for
stage2, but skips individual tests for most backends (I only verified
the C and LLVM backends successfully run one new test case) and the
entire test file for aarch64, where it's running into preexisting
shortcomings.
This commit is contained in:
Daniele Cocca 2022-03-20 21:04:28 +00:00 committed by Veikka Tuominen
parent ebafdb958c
commit 907dc1e13f
3 changed files with 51 additions and 10 deletions

View File

@ -3014,9 +3014,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
} else null;
const writer = f.object.writer();
const inputs_extra_begin = extra_i;
try writer.writeAll("{\n");
for (inputs) |input| {
const inputs_extra_begin = extra_i;
for (inputs) |input, i| {
const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
// for the string, we still use the next u32 for the null terminator.
@ -3032,7 +3033,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValue(writer, arg_c_value);
try writer.writeAll(";\n");
} else {
return f.fail("TODO non-explicit inline asm regs", .{});
try writer.writeAll("register ");
try f.renderType(writer, f.air.typeOf(input));
try writer.print(" input_{d} = ", .{i});
try f.writeCValue(writer, try f.resolveInst(input));
try writer.writeAll(";\n");
}
}
@ -3074,12 +3079,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
try writer.print("\"r\"({s}_constant)", .{reg});
} else {
// This is blocked by the earlier test
unreachable;
if (index > 0) {
try writer.writeAll(", ");
}
try writer.print("\"r\"(input_{d})", .{index});
}
}
}
try writer.writeAll(");\n");
try writer.writeAll("}\n");
if (f.liveness.isUnused(inst))
return CValue.none;

View File

@ -165,10 +165,7 @@ test {
}
if (builtin.os.tag != .wasi) {
if (builtin.zig_backend == .stage1) {
// TODO get these tests passing with stage2
_ = @import("behavior/asm.zig");
}
_ = @import("behavior/asm.zig");
}
if (builtin.zig_backend != .stage2_arm and

View File

@ -5,7 +5,10 @@ const expect = std.testing.expect;
const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux;
comptime {
if (is_x86_64_linux) {
if (builtin.zig_backend != .stage2_arm and
builtin.zig_backend != .stage2_aarch64 and
is_x86_64_linux)
{
asm (
\\.globl this_is_my_alias;
\\.type this_is_my_alias, @function;
@ -15,12 +18,26 @@ comptime {
}
test "module level assembly" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
if (is_x86_64_linux) {
try expect(this_is_my_alias() == 1234);
}
}
test "output constraint modifiers" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
// This is only testing compilation.
var a: u32 = 3;
asm volatile (""
@ -36,6 +53,13 @@ test "output constraint modifiers" {
}
test "alternative constraints" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
// Make sure we allow commas as a separator for alternative constraints.
var a: u32 = 3;
asm volatile (""
@ -46,6 +70,11 @@ test "alternative constraints" {
}
test "sized integer/float in asm input" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
asm volatile (""
:
: [_] "m" (@as(usize, 3)),
@ -89,6 +118,13 @@ test "sized integer/float in asm input" {
}
test "struct/array/union types as input values" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
asm volatile (""
:
: [_] "m" (@as([1]u32, undefined)),