Skip to content

Commit 52a2e68

Browse files
authored
[clang][RISCV] Fix crash on VLS calling convention (#145489)
This patch handle struct of fixed vector and struct of array of fixed vector correctly for VLS calling convention in EmitFunctionProlog, EmitFunctionEpilog and EmitCall. stack on: #147173
1 parent e16ced3 commit 52a2e68

File tree

11 files changed

+391
-54
lines changed

11 files changed

+391
-54
lines changed

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ class ABIArgInfo {
7777
/// Array elements in the type are assumed to be padding and skipped.
7878
CoerceAndExpand,
7979

80+
/// TargetSpecific - Some argument types are passed as target specific types
81+
/// such as RISC-V's tuple type, these need to be handled in the target
82+
/// hook.
83+
TargetSpecific,
84+
8085
/// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
8186
/// This is similar to indirect with byval, except it only applies to
8287
/// arguments stored in memory and forbids any implicit copies. When
@@ -120,7 +125,7 @@ class ABIArgInfo {
120125

121126
bool canHavePaddingType() const {
122127
return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
123-
isExpand();
128+
isExpand() || isTargetSpecific();
124129
}
125130
void setPaddingType(llvm::Type *T) {
126131
assert(canHavePaddingType());
@@ -291,6 +296,20 @@ class ABIArgInfo {
291296
return AI;
292297
}
293298

299+
static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
300+
unsigned Offset = 0,
301+
llvm::Type *Padding = nullptr,
302+
bool CanBeFlattened = true,
303+
unsigned Align = 0) {
304+
auto AI = ABIArgInfo(TargetSpecific);
305+
AI.setCoerceToType(T);
306+
AI.setPaddingType(Padding);
307+
AI.setDirectOffset(Offset);
308+
AI.setDirectAlign(Align);
309+
AI.setCanBeFlattened(CanBeFlattened);
310+
return AI;
311+
}
312+
294313
static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
295314
return eltType->isArrayTy() &&
296315
eltType->getArrayElementType()->isIntegerTy(8);
@@ -305,27 +324,33 @@ class ABIArgInfo {
305324
bool isIndirectAliased() const { return TheKind == IndirectAliased; }
306325
bool isExpand() const { return TheKind == Expand; }
307326
bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
327+
bool isTargetSpecific() const { return TheKind == TargetSpecific; }
308328

309329
bool canHaveCoerceToType() const {
310-
return isDirect() || isExtend() || isCoerceAndExpand();
330+
return isDirect() || isExtend() || isCoerceAndExpand() ||
331+
isTargetSpecific();
311332
}
312333

313334
// Direct/Extend accessors
314335
unsigned getDirectOffset() const {
315-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
336+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
337+
"Not a direct or extend or target specific kind");
316338
return DirectAttr.Offset;
317339
}
318340
void setDirectOffset(unsigned Offset) {
319-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
341+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
342+
"Not a direct or extend or target specific kind");
320343
DirectAttr.Offset = Offset;
321344
}
322345

323346
unsigned getDirectAlign() const {
324-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
347+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
348+
"Not a direct or extend or target specific kind");
325349
return DirectAttr.Align;
326350
}
327351
void setDirectAlign(unsigned Align) {
328-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
352+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
353+
"Not a direct or extend or target specific kind");
329354
DirectAttr.Align = Align;
330355
}
331356

@@ -394,12 +419,14 @@ class ABIArgInfo {
394419
}
395420

396421
bool getInReg() const {
397-
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
422+
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
423+
"Invalid kind!");
398424
return InReg;
399425
}
400426

401427
void setInReg(bool IR) {
402-
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
428+
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
429+
"Invalid kind!");
403430
InReg = IR;
404431
}
405432

@@ -481,12 +508,12 @@ class ABIArgInfo {
481508
}
482509

483510
bool getCanBeFlattened() const {
484-
assert(isDirect() && "Invalid kind!");
511+
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
485512
return CanBeFlattened;
486513
}
487514

488515
void setCanBeFlattened(bool Flatten) {
489-
assert(isDirect() && "Invalid kind!");
516+
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
490517
CanBeFlattened = Flatten;
491518
}
492519

clang/lib/CodeGen/ABIInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,14 @@ ABIInfo::getOptimalVectorMemoryType(llvm::FixedVectorType *T,
244244
return T;
245245
}
246246

247+
llvm::Value *ABIInfo::createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
248+
CodeGenFunction &CGF) const {
249+
return nullptr;
250+
}
251+
252+
void ABIInfo::createCoercedStore(llvm::Value *Val, Address DstAddr,
253+
const ABIArgInfo &AI, bool DestIsVolatile,
254+
CodeGenFunction &CGF) const {}
247255
// Pin the vtable to this file.
248256
SwiftABIInfo::~SwiftABIInfo() = default;
249257

clang/lib/CodeGen/ABIInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ class ABIInfo {
132132
virtual llvm::FixedVectorType *
133133
getOptimalVectorMemoryType(llvm::FixedVectorType *T,
134134
const LangOptions &Opt) const;
135+
136+
virtual llvm::Value *createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
137+
CodeGenFunction &CGF) const;
138+
virtual void createCoercedStore(llvm::Value *Val, Address DstAddr,
139+
const ABIArgInfo &AI, bool DestIsVolatile,
140+
CodeGenFunction &CGF) const;
135141
};
136142

137143
/// Target specific hooks for defining how a type should be passed or returned

clang/lib/CodeGen/CGCall.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,7 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context,
16021602
IRArgs.PaddingArgIndex = IRArgNo++;
16031603

16041604
switch (AI.getKind()) {
1605+
case ABIArgInfo::TargetSpecific:
16051606
case ABIArgInfo::Extend:
16061607
case ABIArgInfo::Direct: {
16071608
// FIXME: handle sseregparm someday...
@@ -1712,6 +1713,7 @@ llvm::FunctionType *CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
17121713
case ABIArgInfo::IndirectAliased:
17131714
llvm_unreachable("Invalid ABI kind for return argument");
17141715

1716+
case ABIArgInfo::TargetSpecific:
17151717
case ABIArgInfo::Extend:
17161718
case ABIArgInfo::Direct:
17171719
resultType = retAI.getCoerceToType();
@@ -1784,6 +1786,7 @@ llvm::FunctionType *CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
17841786
ArgTypes[FirstIRArg] = llvm::PointerType::get(
17851787
getLLVMContext(), ArgInfo.getIndirectAddrSpace());
17861788
break;
1789+
case ABIArgInfo::TargetSpecific:
17871790
case ABIArgInfo::Extend:
17881791
case ABIArgInfo::Direct: {
17891792
// Fast-isel and the optimizer generally like scalar values better than
@@ -2697,6 +2700,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
26972700
else
26982701
RetAttrs.addAttribute(llvm::Attribute::NoExt);
26992702
[[fallthrough]];
2703+
case ABIArgInfo::TargetSpecific:
27002704
case ABIArgInfo::Direct:
27012705
if (RetAI.getInReg())
27022706
RetAttrs.addAttribute(llvm::Attribute::InReg);
@@ -2838,6 +2842,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
28382842
else
28392843
Attrs.addAttribute(llvm::Attribute::NoExt);
28402844
[[fallthrough]];
2845+
case ABIArgInfo::TargetSpecific:
28412846
case ABIArgInfo::Direct:
28422847
if (ArgNo == 0 && FI.isChainCall())
28432848
Attrs.addAttribute(llvm::Attribute::Nest);
@@ -3357,17 +3362,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
33573362
}
33583363
}
33593364

3360-
// Struct of fixed-length vectors and struct of array of fixed-length
3361-
// vector in VLS calling convention are coerced to vector tuple
3362-
// type(represented as TargetExtType) and scalable vector type
3363-
// respectively, they're no longer handled as struct.
3364-
if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
3365-
(isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
3366-
isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
3367-
ArgVals.push_back(ParamValue::forDirect(AI));
3368-
break;
3369-
}
3370-
33713365
llvm::StructType *STy =
33723366
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
33733367
Address Alloca =
@@ -3508,6 +3502,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
35083502
break;
35093503
}
35103504

3505+
case ABIArgInfo::TargetSpecific: {
3506+
auto *AI = Fn->getArg(FirstIRArg);
3507+
AI->setName(Arg->getName() + ".target_coerce");
3508+
Address Alloca =
3509+
CreateMemTemp(Ty, getContext().getDeclAlign(Arg), Arg->getName());
3510+
Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI);
3511+
CGM.getABIInfo().createCoercedStore(AI, Ptr, ArgI, false, *this);
3512+
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
3513+
llvm::Value *V =
3514+
EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc());
3515+
if (isPromoted) {
3516+
V = emitArgumentDemotion(*this, Arg, V);
3517+
}
3518+
ArgVals.push_back(ParamValue::forDirect(V));
3519+
} else {
3520+
ArgVals.push_back(ParamValue::forIndirect(Alloca));
3521+
}
3522+
break;
3523+
}
35113524
case ABIArgInfo::Ignore:
35123525
assert(NumIRArgs == 0);
35133526
// Initialize the local variable appropriately.
@@ -4136,6 +4149,11 @@ void CodeGenFunction::EmitFunctionEpilog(
41364149
}
41374150
break;
41384151
}
4152+
case ABIArgInfo::TargetSpecific: {
4153+
Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
4154+
RV = CGM.getABIInfo().createCoercedLoad(V, RetAI, *this);
4155+
break;
4156+
}
41394157
case ABIArgInfo::Expand:
41404158
case ABIArgInfo::IndirectAliased:
41414159
llvm_unreachable("Invalid ABI kind for return argument");
@@ -5704,6 +5722,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
57045722
assert(IRArgPos == FirstIRArg + NumIRArgs);
57055723
break;
57065724
}
5725+
5726+
case ABIArgInfo::TargetSpecific: {
5727+
Address Src = Address::invalid();
5728+
if (!I->isAggregate()) {
5729+
Src = CreateMemTemp(I->Ty, "target_coerce");
5730+
I->copyInto(*this, Src);
5731+
} else {
5732+
Src = I->hasLValue() ? I->getKnownLValue().getAddress()
5733+
: I->getKnownRValue().getAggregateAddress();
5734+
}
5735+
5736+
// If the value is offset in memory, apply the offset now.
5737+
Src = emitAddressAtOffset(*this, Src, ArgInfo);
5738+
llvm::Value *Load =
5739+
CGM.getABIInfo().createCoercedLoad(Src, ArgInfo, *this);
5740+
IRCallArgs[FirstIRArg] = Load;
5741+
break;
5742+
}
57075743
}
57085744
}
57095745

@@ -6189,6 +6225,19 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
61896225
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
61906226
}
61916227

6228+
case ABIArgInfo::TargetSpecific: {
6229+
Address DestPtr = ReturnValue.getValue();
6230+
Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
6231+
bool DestIsVolatile = ReturnValue.isVolatile();
6232+
if (!DestPtr.isValid()) {
6233+
DestPtr = CreateMemTemp(RetTy, "target_coerce");
6234+
DestIsVolatile = false;
6235+
}
6236+
CGM.getABIInfo().createCoercedStore(CI, StorePtr, RetAI, DestIsVolatile,
6237+
*this);
6238+
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
6239+
}
6240+
61926241
case ABIArgInfo::Expand:
61936242
case ABIArgInfo::IndirectAliased:
61946243
llvm_unreachable("Invalid ABI kind for return argument");

clang/lib/CodeGen/TargetInfo.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ LLVM_DUMP_METHOD void ABIArgInfo::dump() const {
6363
OS << "CoerceAndExpand Type=";
6464
getCoerceAndExpandType()->print(OS);
6565
break;
66+
case TargetSpecific:
67+
OS << "TargetSpecific Type=";
68+
if (llvm::Type *Ty = getCoerceToType())
69+
Ty->print(OS);
70+
else
71+
OS << "null";
72+
break;
6673
}
6774
OS << ")\n";
6875
}

0 commit comments

Comments
 (0)