Skip to content

Commit c798df6

Browse files
committed
Replicate the inreg attribute from the declaration to the call site
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
1 parent ad00063 commit c798df6

File tree

2 files changed

+7
-1
lines changed

2 files changed

+7
-1
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,11 @@ llvm::CallBase *IRBuilder::CreateCallOrInvoke(
35623562
builder.addByValAttr(func->getParamByValType(argIndex));
35633563
attrs = attrs.addParamAttributes(func->getContext(), argIndex, builder);
35643564
}
3565+
if (func->hasParamAttribute(argIndex, llvm::Attribute::InReg)) {
3566+
llvm::AttrBuilder builder(func->getContext());
3567+
builder.addAttribute(llvm::Attribute::InReg);
3568+
attrs = attrs.addParamAttributes(func->getContext(), argIndex, builder);
3569+
}
35653570
}
35663571
}
35673572
call->setAttributes(attrs);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +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 noalias sret(%TSo19NonTrivialInWrapperV) %[[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

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

0 commit comments

Comments
 (0)