| ... | @@ -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; |
| 5426 | | 5428 | |
| ... | @@ -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 | } |
| 5453 | | 5466 | |
| 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; |
| 5465 | | 5478 | |
| 5466 | const arg_llvm_value = try self.resolveInst(input); | 5479 | const arg_llvm_value = try self.resolveInst(input); |
| 5467 | | 5480 | 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 | } |
| 5470 | | 5506 | |
| 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 | } |
| 5476 | | 5517 | |
| 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 { |
| 9307 | fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 { | 9348 | fn 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 | |
| | 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 | } |