Skip to content

Commit b4ef4aa

Browse files
committed
Add the inreg attribute to sreg when present.
On Windows/AArch64, a different register is used between when an arugment is both inreg and sret (X0 or X1) and when it is just sret (X8) as the following comment indicates: https://github.com/llvm/llvm-project/blob/46fe36a4295f05d5d3731762e31fc4e6e99863e9/llvm/lib/Target/AArch64/AArch64CallingConvention.td#L42 ``` // In AAPCS, an SRet is passed in X8, not X0 like a normal pointer parameter. // However, on windows, in some circumstances, the SRet is passed in X0 or X1 // instead. The presence of the inreg attribute indicates that SRet is // passed in the alternative register (X0 or X1), not X8: // - X0 for non-instance methods. // - X1 for instance methods. // The "sret" attribute identifies indirect returns. // The "inreg" attribute identifies non-aggregate types. // The position of the "sret" attribute identifies instance/non-instance // methods. // "sret" on argument 0 means non-instance methods. // "sret" on argument 1 means instance methods. CCIfInReg<CCIfType<[i64], CCIfSRet<CCIfType<[i64], CCAssignToReg<[X0, X1]>>>>>, CCIfSRet<CCIfType<[i64], CCAssignToReg<[X8]>>>, ``` So missing/dropping inreg can cause a codegen bug. This is a partial fix for #74866 Cherrypick #76159
1 parent 48015ab commit b4ef4aa

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,16 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
341341
static void addIndirectResultAttributes(IRGenModule &IGM,
342342
llvm::AttributeList &attrs,
343343
unsigned paramIndex, bool allowSRet,
344-
llvm::Type *storageType) {
344+
llvm::Type *storageType,
345+
bool useInReg = false) {
345346
llvm::AttrBuilder b(IGM.getLLVMContext());
346347
b.addAttribute(llvm::Attribute::NoAlias);
347348
b.addAttribute(llvm::Attribute::NoCapture);
348349
if (allowSRet) {
349350
assert(storageType);
350351
b.addStructRetAttr(storageType);
352+
if (useInReg)
353+
b.addAttribute(llvm::Attribute::InReg);
351354
}
352355
attrs = attrs.addParamAttributes(IGM.getLLVMContext(), paramIndex, b);
353356
}
@@ -449,7 +452,7 @@ namespace {
449452

450453
private:
451454
const TypeInfo &expand(SILParameterInfo param);
452-
llvm::Type *addIndirectResult();
455+
llvm::Type *addIndirectResult(bool useInReg = false);
453456

454457
SILFunctionConventions getSILFuncConventions() const {
455458
return SILFunctionConventions(FnType, IGM.getSILModule());
@@ -503,13 +506,13 @@ namespace {
503506
} // end namespace irgen
504507
} // end namespace swift
505508

506-
llvm::Type *SignatureExpansion::addIndirectResult() {
509+
llvm::Type *SignatureExpansion::addIndirectResult(bool useInReg) {
507510
auto resultType = getSILFuncConventions().getSILResultType(
508511
IGM.getMaximalTypeExpansionContext());
509512
const TypeInfo &resultTI = IGM.getTypeInfo(resultType);
510513
auto storageTy = resultTI.getStorageType();
511514
addIndirectResultAttributes(IGM, Attrs, ParamIRTypes.size(), claimSRet(),
512-
storageTy);
515+
storageTy, useInReg);
513516
addPointerParameter(storageTy);
514517
return IGM.VoidTy;
515518
}
@@ -1526,9 +1529,9 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15261529
// returned indirect values.
15271530
emitArg(0);
15281531
firstParamToLowerNormally = 1;
1529-
addIndirectResult();
1532+
addIndirectResult(returnInfo.getInReg());
15301533
} else
1531-
addIndirectResult();
1534+
addIndirectResult(returnInfo.getInReg());
15321535
}
15331536

15341537
// Use a special IR type for passing block pointers.

test/Interop/Cxx/class/method/methods-this-and-indirect-return-irgen-msvc.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public func use() -> CInt {
1212

1313
// CHECK: %[[instance:.*]] = alloca %TSo10HasMethodsV
1414
// CHECK: %[[result:.*]] = alloca %TSo19NonTrivialInWrapperV
15-
// CHECK: call void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr %[[instance]], ptr sret(%struct.NonTrivialInWrapper) %[[result]], i32 42)
15+
// CHECK-x86_64: call void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr %[[instance]], ptr noalias sret(%TSo19NonTrivialInWrapperV) %[[result]], i32 42)
16+
// CHECK-aarch64: call void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr %[[instance]], ptr inreg noalias sret(%TSo19NonTrivialInWrapperV) %[[result]], i32 42)
1617

17-
// CHECK: define {{.*}} void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr {{.*}} %{{.*}}, ptr noalias sret(%struct.NonTrivialInWrapper) {{.*}} %{{.*}}, i32 noundef %{{.*}})
18+
// CHECK-x86_64: define {{.*}} void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr {{.*}} %{{.*}}, ptr noalias sret(%struct.NonTrivialInWrapper) {{.*}} %{{.*}}, i32 noundef %{{.*}})
19+
// CHECK-aarch64: define {{.*}} void @"?nonConstPassThroughAsWrapper@HasMethods@@QEAA?AUNonTrivialInWrapper@@H@Z"(ptr {{.*}} %{{.*}}, ptr inreg noalias sret(%struct.NonTrivialInWrapper) {{.*}} %{{.*}}, i32 noundef %{{.*}})

0 commit comments

Comments
 (0)