| ... | ... | @@ -5421,6 +5421,8 @@ pub const FuncGen = struct { |
| 5421 | 5421 | const llvm_params_len = inputs.len + outputs.len - return_count; |
| 5422 | 5422 | const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len); |
| 5423 | 5423 | const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len); |
| 5424 | const target = self.dg.module.getTarget(); |
| 5425 | |
| 5424 | 5426 | var llvm_param_i: usize = 0; |
| 5425 | 5427 | var total_i: usize = 0; |
| 5426 | 5428 | |
| ... | ... | @@ -5449,7 +5451,18 @@ pub const FuncGen = struct { |
| 5449 | 5451 | llvm_param_types[llvm_param_i] = output_inst.typeOf(); |
| 5450 | 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 | 5467 | name_map.putAssumeCapacityNoClobber(name, {}); |
| 5455 | 5468 | total_i += 1; |
| ... | ... | @@ -5464,15 +5477,43 @@ pub const FuncGen = struct { |
| 5464 | 5477 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 5465 | 5478 | |
| 5466 | 5479 | 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 | } |
| 5470 | 5506 | |
| 5471 | 5507 | try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); |
| 5472 | 5508 | if (total_i != 0) { |
| 5473 | 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 | 5518 | if (!std.mem.eql(u8, name, "_")) { |
| 5478 | 5519 | name_map.putAssumeCapacityNoClobber(name, {}); |
| ... | ... | @@ -9307,3 +9348,11 @@ fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 { |
| 9307 | 9348 | fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 { |
| 9308 | 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 | } |