Skip to content

Commit 13f02c3

Browse files
committed
stage2: fix some inline asm incompatibilities with stage1
1 parent ffa700e commit 13f02c3

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

src/Sema.zig

+5-1
Original file line numberDiff line numberDiff line change
@@ -11406,6 +11406,7 @@ fn zirAsm(
1140611406
// Indicate the output is the asm instruction return value.
1140711407
arg.* = .none;
1140811408
const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);
11409+
try sema.queueFullTypeResolution(out_ty);
1140911410
expr_ty = try sema.addType(out_ty);
1141011411
} else {
1141111412
arg.* = try sema.resolveInst(output.data.operand);
@@ -11430,7 +11431,10 @@ fn zirAsm(
1143011431
switch (uncasted_arg_ty.zigTypeTag()) {
1143111432
.ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),
1143211433
.ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src),
11433-
else => arg.* = uncasted_arg,
11434+
else => {
11435+
arg.* = uncasted_arg;
11436+
try sema.queueFullTypeResolution(uncasted_arg_ty);
11437+
},
1143411438
}
1143511439

1143611440
const constraint = sema.code.nullTerminatedString(input.data.constraint);

src/codegen/llvm.zig

+54-5
Original file line numberDiff line numberDiff line change
@@ -5421,6 +5421,8 @@ pub const FuncGen = struct {
54215421
const llvm_params_len = inputs.len + outputs.len - return_count;
54225422
const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);
54235423
const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);
5424+
const target = self.dg.module.getTarget();
5425+
54245426
var llvm_param_i: usize = 0;
54255427
var total_i: usize = 0;
54265428

@@ -5449,7 +5451,18 @@ pub const FuncGen = struct {
54495451
llvm_param_types[llvm_param_i] = output_inst.typeOf();
54505452
llvm_param_i += 1;
54515453
}
5452-
llvm_constraints.appendSliceAssumeCapacity(constraint[1..]);
5454+
5455+
// LLVM uses commas internally to separate different constraints,
5456+
// alternative constraints are achieved with pipes.
5457+
// We still allow the user to use commas in a way that is similar
5458+
// to GCC's inline assembly.
5459+
// http://llvm.org/docs/LangRef.html#constraint-codes
5460+
for (constraint[1..]) |byte| {
5461+
llvm_constraints.appendAssumeCapacity(switch (byte) {
5462+
',' => '|',
5463+
else => byte,
5464+
});
5465+
}
54535466

54545467
name_map.putAssumeCapacityNoClobber(name, {});
54555468
total_i += 1;
@@ -5464,15 +5477,43 @@ pub const FuncGen = struct {
54645477
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
54655478

54665479
const arg_llvm_value = try self.resolveInst(input);
5467-
5468-
llvm_param_values[llvm_param_i] = arg_llvm_value;
5469-
llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
5480+
const arg_ty = self.air.typeOf(input);
5481+
if (isByRef(arg_ty)) {
5482+
if (constraintAllowsMemory(constraint)) {
5483+
llvm_param_values[llvm_param_i] = arg_llvm_value;
5484+
llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
5485+
} else {
5486+
const alignment = arg_ty.abiAlignment(target);
5487+
const load_inst = self.builder.buildLoad(arg_llvm_value, "");
5488+
load_inst.setAlignment(alignment);
5489+
llvm_param_values[llvm_param_i] = load_inst;
5490+
llvm_param_types[llvm_param_i] = load_inst.typeOf();
5491+
}
5492+
} else {
5493+
if (constraintAllowsRegister(constraint)) {
5494+
llvm_param_values[llvm_param_i] = arg_llvm_value;
5495+
llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
5496+
} else {
5497+
const alignment = arg_ty.abiAlignment(target);
5498+
const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf());
5499+
arg_ptr.setAlignment(alignment);
5500+
const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr);
5501+
store_inst.setAlignment(alignment);
5502+
llvm_param_values[llvm_param_i] = arg_ptr;
5503+
llvm_param_types[llvm_param_i] = arg_ptr.typeOf();
5504+
}
5505+
}
54705506

54715507
try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1);
54725508
if (total_i != 0) {
54735509
llvm_constraints.appendAssumeCapacity(',');
54745510
}
5475-
llvm_constraints.appendSliceAssumeCapacity(constraint);
5511+
for (constraint) |byte| {
5512+
llvm_constraints.appendAssumeCapacity(switch (byte) {
5513+
',' => '|',
5514+
else => byte,
5515+
});
5516+
}
54765517

54775518
if (!std.mem.eql(u8, name, "_")) {
54785519
name_map.putAssumeCapacityNoClobber(name, {});
@@ -9307,3 +9348,11 @@ fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 {
93079348
fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {
93089349
return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));
93099350
}
9351+
9352+
fn constraintAllowsMemory(constraint: []const u8) bool {
9353+
return constraint[0] == 'm';
9354+
}
9355+
9356+
fn constraintAllowsRegister(constraint: []const u8) bool {
9357+
return constraint[0] != 'm';
9358+
}

test/behavior/asm.zig

-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ test "output constraint modifiers" {
3535
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3636
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3737
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
38-
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
3938

4039
// This is only testing compilation.
4140
var a: u32 = 3;
@@ -57,7 +56,6 @@ test "alternative constraints" {
5756
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5857
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5958
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60-
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
6159

6260
// Make sure we allow commas as a separator for alternative constraints.
6361
var a: u32 = 3;
@@ -122,7 +120,6 @@ test "struct/array/union types as input values" {
122120
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
123121
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
124122
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125-
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
126123

127124
asm volatile (""
128125
:

0 commit comments

Comments
 (0)