Skip to content

Commit e51b061

Browse files
committed
[clang][RISCV] Fix crash on VLS calling convention
This patch handle struct of fixed vector and struct of array of fixed vector correctly for VLS calling convention in EmitFunctionProlog, EmitFunctionEpilog and EmitCall.
1 parent f2e244f commit e51b061

File tree

11 files changed

+394
-54
lines changed

11 files changed

+394
-54
lines changed

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ 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 RISCV's tuple type, these need to be handled in the target hook.
82+
TargetSpecific,
83+
8084
/// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
8185
/// This is similar to indirect with byval, except it only applies to
8286
/// arguments stored in memory and forbids any implicit copies. When
@@ -120,7 +124,7 @@ class ABIArgInfo {
120124

121125
bool canHavePaddingType() const {
122126
return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
123-
isExpand();
127+
isExpand() || isTargetSpecific();
124128
}
125129
void setPaddingType(llvm::Type *T) {
126130
assert(canHavePaddingType());
@@ -291,6 +295,20 @@ class ABIArgInfo {
291295
return AI;
292296
}
293297

298+
static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
299+
unsigned Offset = 0,
300+
llvm::Type *Padding = nullptr,
301+
bool CanBeFlattened = true,
302+
unsigned Align = 0) {
303+
auto AI = ABIArgInfo(TargetSpecific);
304+
AI.setCoerceToType(T);
305+
AI.setPaddingType(Padding);
306+
AI.setDirectOffset(Offset);
307+
AI.setDirectAlign(Align);
308+
AI.setCanBeFlattened(CanBeFlattened);
309+
return AI;
310+
}
311+
294312
static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
295313
return eltType->isArrayTy() &&
296314
eltType->getArrayElementType()->isIntegerTy(8);
@@ -305,27 +323,33 @@ class ABIArgInfo {
305323
bool isIndirectAliased() const { return TheKind == IndirectAliased; }
306324
bool isExpand() const { return TheKind == Expand; }
307325
bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
326+
bool isTargetSpecific() const { return TheKind == TargetSpecific; }
308327

309328
bool canHaveCoerceToType() const {
310-
return isDirect() || isExtend() || isCoerceAndExpand();
329+
return isDirect() || isExtend() || isCoerceAndExpand() ||
330+
isTargetSpecific();
311331
}
312332

313333
// Direct/Extend accessors
314334
unsigned getDirectOffset() const {
315-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
335+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
336+
"Not a direct or extend or target specific kind");
316337
return DirectAttr.Offset;
317338
}
318339
void setDirectOffset(unsigned Offset) {
319-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
340+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
341+
"Not a direct or extend or target specific kind");
320342
DirectAttr.Offset = Offset;
321343
}
322344

323345
unsigned getDirectAlign() const {
324-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
346+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
347+
"Not a direct or extend or target specific kind");
325348
return DirectAttr.Align;
326349
}
327350
void setDirectAlign(unsigned Align) {
328-
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
351+
assert((isDirect() || isExtend() || isTargetSpecific()) &&
352+
"Not a direct or extend or target specific kind");
329353
DirectAttr.Align = Align;
330354
}
331355

@@ -394,12 +418,14 @@ class ABIArgInfo {
394418
}
395419

396420
bool getInReg() const {
397-
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
421+
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
422+
"Invalid kind!");
398423
return InReg;
399424
}
400425

401426
void setInReg(bool IR) {
402-
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
427+
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
428+
"Invalid kind!");
403429
InReg = IR;
404430
}
405431

@@ -481,12 +507,12 @@ class ABIArgInfo {
481507
}
482508

483509
bool getCanBeFlattened() const {
484-
assert(isDirect() && "Invalid kind!");
510+
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
485511
return CanBeFlattened;
486512
}
487513

488514
void setCanBeFlattened(bool Flatten) {
489-
assert(isDirect() && "Invalid kind!");
515+
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
490516
CanBeFlattened = Flatten;
491517
}
492518

clang/lib/CodeGen/ABIInfo.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,15 @@ 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+
void ABIInfo::CreateCoercedStore(llvm::Value *Val, Address DstAddr,
252+
const ABIArgInfo &AI, bool DestIsVolatile,
253+
CodeGenFunction &CGF) const {
254+
return;
255+
}
247256
// Pin the vtable to this file.
248257
SwiftABIInfo::~SwiftABIInfo() = default;
249258

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);
@@ -3335,17 +3340,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
33353340
}
33363341
}
33373342

3338-
// Struct of fixed-length vectors and struct of array of fixed-length
3339-
// vector in VLS calling convention are coerced to vector tuple
3340-
// type(represented as TargetExtType) and scalable vector type
3341-
// respectively, they're no longer handled as struct.
3342-
if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
3343-
(isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
3344-
isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
3345-
ArgVals.push_back(ParamValue::forDirect(AI));
3346-
break;
3347-
}
3348-
33493343
llvm::StructType *STy =
33503344
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
33513345
Address Alloca =
@@ -3486,6 +3480,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
34863480
break;
34873481
}
34883482

3483+
case ABIArgInfo::TargetSpecific: {
3484+
auto *AI = Fn->getArg(FirstIRArg);
3485+
AI->setName(Arg->getName() + ".target_coerce");
3486+
Address Alloca =
3487+
CreateMemTemp(Ty, getContext().getDeclAlign(Arg), Arg->getName());
3488+
Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI);
3489+
CGM.getABIInfo().CreateCoercedStore(AI, Ptr, ArgI, false, *this);
3490+
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
3491+
llvm::Value *V =
3492+
EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc());
3493+
if (isPromoted) {
3494+
V = emitArgumentDemotion(*this, Arg, V);
3495+
}
3496+
ArgVals.push_back(ParamValue::forDirect(V));
3497+
} else {
3498+
ArgVals.push_back(ParamValue::forIndirect(Alloca));
3499+
}
3500+
break;
3501+
}
34893502
case ABIArgInfo::Ignore:
34903503
assert(NumIRArgs == 0);
34913504
// Initialize the local variable appropriately.
@@ -4114,6 +4127,11 @@ void CodeGenFunction::EmitFunctionEpilog(
41144127
}
41154128
break;
41164129
}
4130+
case ABIArgInfo::TargetSpecific: {
4131+
Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
4132+
RV = CGM.getABIInfo().CreateCoercedLoad(V, RetAI, *this);
4133+
break;
4134+
}
41174135
case ABIArgInfo::Expand:
41184136
case ABIArgInfo::IndirectAliased:
41194137
llvm_unreachable("Invalid ABI kind for return argument");
@@ -5691,6 +5709,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
56915709
assert(IRArgPos == FirstIRArg + NumIRArgs);
56925710
break;
56935711
}
5712+
5713+
case ABIArgInfo::TargetSpecific: {
5714+
Address Src = Address::invalid();
5715+
if (!I->isAggregate()) {
5716+
Src = CreateMemTemp(I->Ty, "target_coerce");
5717+
I->copyInto(*this, Src);
5718+
} else {
5719+
Src = I->hasLValue() ? I->getKnownLValue().getAddress()
5720+
: I->getKnownRValue().getAggregateAddress();
5721+
}
5722+
5723+
// If the value is offset in memory, apply the offset now.
5724+
Src = emitAddressAtOffset(*this, Src, ArgInfo);
5725+
llvm::Value *Load =
5726+
CGM.getABIInfo().CreateCoercedLoad(Src, ArgInfo, *this);
5727+
IRCallArgs[FirstIRArg] = Load;
5728+
break;
5729+
}
56945730
}
56955731
}
56965732

@@ -6177,6 +6213,19 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
61776213
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
61786214
}
61796215

6216+
case ABIArgInfo::TargetSpecific: {
6217+
Address DestPtr = ReturnValue.getValue();
6218+
Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
6219+
bool DestIsVolatile = ReturnValue.isVolatile();
6220+
if (!DestPtr.isValid()) {
6221+
DestPtr = CreateMemTemp(RetTy, "target_coerce");
6222+
DestIsVolatile = false;
6223+
}
6224+
CGM.getABIInfo().CreateCoercedStore(CI, StorePtr, RetAI, DestIsVolatile,
6225+
*this);
6226+
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
6227+
}
6228+
61806229
case ABIArgInfo::Expand:
61816230
case ABIArgInfo::IndirectAliased:
61826231
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)