aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-03-31 00:04:04 +0300
committerGitHub <noreply@github.com>2022-03-31 00:04:04 +0300
commit3c64c519e65861868e05c47de2d8605a579edf06 (patch)
tree9e06748f9c048b4f54982db9163f6e46e8eb9746 /src
parentd227f76afbacb619152ffd943cf3018e62e00adc (diff)
parent907dc1e13f657f349dbdecf739b2f1a13ad7011a (diff)
downloadzig-3c64c519e65861868e05c47de2d8605a579edf06.tar.gz
zig-3c64c519e65861868e05c47de2d8605a579edf06.zip
Merge pull request #11246 from jmc-88/cbe-asm
CBE: improve support for asm inputs
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig52
-rw-r--r--src/Sema.zig15
-rw-r--r--src/codegen/c.zig18
3 files changed, 43 insertions, 42 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 1e4865bd97..b6ca1fe848 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -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,
diff --git a/src/Sema.zig b/src/Sema.zig
index 9fc54f805b..112939c995 100644
--- a/src/Sema.zig
+++ b/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,
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 19556fe8c4..4085305941 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -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;