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(...@@ -11406,6 +11406,7 @@ fn zirAsm(
11406 // Indicate the output is the asm instruction return value.11406 // Indicate the output is the asm instruction return value.
11407 arg.* = .none;11407 arg.* = .none;
11408 const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);11408 const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);
11409 try sema.queueFullTypeResolution(out_ty);
11409 expr_ty = try sema.addType(out_ty);11410 expr_ty = try sema.addType(out_ty);
11410 } else {11411 } else {
11411 arg.* = try sema.resolveInst(output.data.operand);11412 arg.* = try sema.resolveInst(output.data.operand);
...@@ -11430,7 +11431,10 @@ fn zirAsm(...@@ -11430,7 +11431,10 @@ fn zirAsm(
11430 switch (uncasted_arg_ty.zigTypeTag()) {11431 switch (uncasted_arg_ty.zigTypeTag()) {
11431 .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),11432 .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),
11432 .ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src),11433 .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 },
11434 }11438 }
1143511439
11436 const constraint = sema.code.nullTerminatedString(input.data.constraint);11440 const constraint = sema.code.nullTerminatedString(input.data.constraint);
src/codegen/llvm.zig+54-5
...@@ -5421,6 +5421,8 @@ pub const FuncGen = struct {...@@ -5421,6 +5421,8 @@ pub const FuncGen = struct {
5421 const llvm_params_len = inputs.len + outputs.len - return_count;5421 const llvm_params_len = inputs.len + outputs.len - return_count;
5422 const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);5422 const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);
5423 const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);5423 const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);
5424 const target = self.dg.module.getTarget();
5425
5424 var llvm_param_i: usize = 0;5426 var llvm_param_i: usize = 0;
5425 var total_i: usize = 0;5427 var total_i: usize = 0;
54265428
...@@ -5449,7 +5451,18 @@ pub const FuncGen = struct {...@@ -5449,7 +5451,18 @@ pub const FuncGen = struct {
5449 llvm_param_types[llvm_param_i] = output_inst.typeOf();5451 llvm_param_types[llvm_param_i] = output_inst.typeOf();
5450 llvm_param_i += 1;5452 llvm_param_i += 1;
5451 }5453 }
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
5454 name_map.putAssumeCapacityNoClobber(name, {});5467 name_map.putAssumeCapacityNoClobber(name, {});
5455 total_i += 1;5468 total_i += 1;
...@@ -5464,15 +5477,43 @@ pub const FuncGen = struct {...@@ -5464,15 +5477,43 @@ pub const FuncGen = struct {
5464 extra_i += (constraint.len + name.len + (2 + 3)) / 4;5477 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
54655478
5466 const arg_llvm_value = try self.resolveInst(input);5479 const arg_llvm_value = try self.resolveInst(input);
54675480 const arg_ty = self.air.typeOf(input);
5468 llvm_param_values[llvm_param_i] = arg_llvm_value;5481 if (isByRef(arg_ty)) {
5469 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();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
5471 try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1);5507 try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1);
5472 if (total_i != 0) {5508 if (total_i != 0) {
5473 llvm_constraints.appendAssumeCapacity(',');5509 llvm_constraints.appendAssumeCapacity(',');
5474 }5510 }
5475 llvm_constraints.appendSliceAssumeCapacity(constraint);5511 for (constraint) |byte| {
5512 llvm_constraints.appendAssumeCapacity(switch (byte) {
5513 ',' => '|',
5514 else => byte,
5515 });
5516 }
54765517
5477 if (!std.mem.eql(u8, name, "_")) {5518 if (!std.mem.eql(u8, name, "_")) {
5478 name_map.putAssumeCapacityNoClobber(name, {});5519 name_map.putAssumeCapacityNoClobber(name, {});
...@@ -9307,3 +9348,11 @@ fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 {...@@ -9307,3 +9348,11 @@ fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 {
9307fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {9348fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {
9308 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));9349 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));
9309}9350}
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" {...@@ -35,7 +35,6 @@ test "output constraint modifiers" {
35 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO35 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
38 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
3938
40 // This is only testing compilation.39 // This is only testing compilation.
41 var a: u32 = 3;40 var a: u32 = 3;
...@@ -57,7 +56,6 @@ test "alternative constraints" {...@@ -57,7 +56,6 @@ test "alternative constraints" {
57 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
6159
62 // Make sure we allow commas as a separator for alternative constraints.60 // Make sure we allow commas as a separator for alternative constraints.
63 var a: u32 = 3;61 var a: u32 = 3;
...@@ -122,7 +120,6 @@ test "struct/array/union types as input values" {...@@ -122,7 +120,6 @@ test "struct/array/union types as input values" {
122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO120 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO121 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
126123
127 asm volatile (""124 asm volatile (""
128 :125 :