mirror of
https://github.com/ziglang/zig.git
synced 2026-02-16 14:28:57 +00:00
Merge pull request #11246 from jmc-88/cbe-asm
CBE: improve support for asm inputs
This commit is contained in:
commit
3c64c519e6
@ -6423,7 +6423,6 @@ fn identifier(
|
||||
|
||||
const astgen = gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
const gpa = astgen.gpa;
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
|
||||
const ident_token = main_tokens[ident];
|
||||
@ -6467,6 +6466,19 @@ fn identifier(
|
||||
}
|
||||
|
||||
// Local variables, including function parameters.
|
||||
return localVarRef(gz, scope, rl, ident, ident_token);
|
||||
}
|
||||
|
||||
fn localVarRef(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
ident: Ast.Node.Index,
|
||||
ident_token: Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
const name_str_index = try astgen.identAsString(ident_token);
|
||||
var s = scope;
|
||||
var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already
|
||||
@ -6808,43 +6820,13 @@ fn asmExpr(
|
||||
};
|
||||
} else {
|
||||
const ident_token = symbolic_name + 4;
|
||||
const str_index = try astgen.identAsString(ident_token);
|
||||
// TODO this needs extra code for local variables. Have a look at #215 and related
|
||||
// issues and decide how to handle outputs. Do we want this to be identifiers?
|
||||
// TODO have a look at #215 and related issues and decide how to
|
||||
// handle outputs. Do we want this to be identifiers?
|
||||
// Or maybe we want to force this to be expressions with a pointer type.
|
||||
// Until that is figured out this is only hooked up for referencing Decls.
|
||||
// TODO we have put this as an identifier lookup just so that we don't get
|
||||
// unused vars for outputs. We need to check if this is correct in the future ^^
|
||||
// so we just put in this simple lookup. This is a workaround.
|
||||
{
|
||||
var s = scope;
|
||||
while (true) switch (s.tag) {
|
||||
.local_val => {
|
||||
const local_val = s.cast(Scope.LocalVal).?;
|
||||
if (local_val.name == str_index) {
|
||||
local_val.used = true;
|
||||
break;
|
||||
}
|
||||
s = local_val.parent;
|
||||
},
|
||||
.local_ptr => {
|
||||
const local_ptr = s.cast(Scope.LocalPtr).?;
|
||||
if (local_ptr.name == str_index) {
|
||||
local_ptr.used = true;
|
||||
break;
|
||||
}
|
||||
s = local_ptr.parent;
|
||||
},
|
||||
.gen_zir => s = s.cast(GenZir).?.parent,
|
||||
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
|
||||
.namespace, .top => break,
|
||||
};
|
||||
}
|
||||
const operand = try gz.addStrTok(.decl_ref, str_index, ident_token);
|
||||
outputs[i] = .{
|
||||
.name = name,
|
||||
.constraint = constraint,
|
||||
.operand = operand,
|
||||
.operand = try localVarRef(gz, scope, rl, node, ident_token),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -6860,7 +6842,7 @@ fn asmExpr(
|
||||
const name = try astgen.identAsString(symbolic_name);
|
||||
const constraint_token = symbolic_name + 2;
|
||||
const constraint = (try astgen.strLitAsString(constraint_token)).index;
|
||||
const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs);
|
||||
const operand = try expr(gz, scope, .none, node_datas[input_node].lhs);
|
||||
inputs[i] = .{
|
||||
.name = name,
|
||||
.constraint = constraint,
|
||||
|
||||
15
src/Sema.zig
15
src/Sema.zig
@ -10253,6 +10253,11 @@ fn zirAsm(
|
||||
const inputs_len = @truncate(u5, extended.small >> 5);
|
||||
const clobbers_len = @truncate(u5, extended.small >> 10);
|
||||
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
|
||||
const is_global_assembly = sema.func == null;
|
||||
|
||||
if (block.is_comptime and !is_global_assembly) {
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
}
|
||||
|
||||
if (extra.data.asm_source == 0) {
|
||||
// This can move to become an AstGen error after inline assembly improvements land
|
||||
@ -10299,7 +10304,14 @@ fn zirAsm(
|
||||
const name = sema.code.nullTerminatedString(input.data.name);
|
||||
_ = name; // TODO: use the name
|
||||
|
||||
arg.* = sema.resolveInst(input.data.operand);
|
||||
const uncasted_arg = sema.resolveInst(input.data.operand);
|
||||
const uncasted_arg_ty = sema.typeOf(uncasted_arg);
|
||||
switch (uncasted_arg_ty.zigTypeTag()) {
|
||||
.ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),
|
||||
.ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src),
|
||||
else => arg.* = uncasted_arg,
|
||||
}
|
||||
|
||||
const constraint = sema.code.nullTerminatedString(input.data.constraint);
|
||||
needed_capacity += constraint.len / 4 + 1;
|
||||
inputs[arg_i] = constraint;
|
||||
@ -10317,7 +10329,6 @@ fn zirAsm(
|
||||
needed_capacity += (asm_source.len + 3) / 4;
|
||||
|
||||
const gpa = sema.gpa;
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);
|
||||
const asm_air = try block.addInst(.{
|
||||
.tag = .assembly,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user