authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-12 14:34:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-12 14:46:05-07:00
log13f02c30e62564b85c2fbaa98e632d44f854cf53
treec04e6204e5d6dbc03d5c5b9846b63eb3bea765b1
parentffa700ee58cd29dafe2bbdfe78a4bd4f7bab0674

stage2: fix some inline asm incompatibilities with stage1


3 files changed, 59 insertions(+), 9 deletions(-)

src/Sema.zig+5-1
......@@ -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
......@@ -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 {
93079348fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {
93089349 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));
93099350}
9351
9352fn constraintAllowsMemory(constraint: []const u8) bool {
9353 return constraint[0] == 'm';
9354}
9355
9356fn constraintAllowsRegister(constraint: []const u8) bool {
9357 return constraint[0] != 'm';
9358}
test/behavior/asm.zig-3
......@@ -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 :