Skip to content

[clang][RISCV] Fix crash on VLS calling convention #145489

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions clang/include/clang/CodeGen/CGFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ class ABIArgInfo {
/// Array elements in the type are assumed to be padding and skipped.
CoerceAndExpand,

/// TargetSpecific - Some argument types are passed as target specific types
/// such as RISC-V's tuple type, these need to be handled in the target
/// hook.
TargetSpecific,

/// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
/// This is similar to indirect with byval, except it only applies to
/// arguments stored in memory and forbids any implicit copies. When
Expand Down Expand Up @@ -120,7 +125,7 @@ class ABIArgInfo {

bool canHavePaddingType() const {
return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
isExpand();
isExpand() || isTargetSpecific();
}
void setPaddingType(llvm::Type *T) {
assert(canHavePaddingType());
Expand Down Expand Up @@ -291,6 +296,20 @@ class ABIArgInfo {
return AI;
}

static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
unsigned Offset = 0,
llvm::Type *Padding = nullptr,
bool CanBeFlattened = true,
unsigned Align = 0) {
auto AI = ABIArgInfo(TargetSpecific);
AI.setCoerceToType(T);
AI.setPaddingType(Padding);
AI.setDirectOffset(Offset);
AI.setDirectAlign(Align);
AI.setCanBeFlattened(CanBeFlattened);
return AI;
}

static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
return eltType->isArrayTy() &&
eltType->getArrayElementType()->isIntegerTy(8);
Expand All @@ -305,27 +324,33 @@ class ABIArgInfo {
bool isIndirectAliased() const { return TheKind == IndirectAliased; }
bool isExpand() const { return TheKind == Expand; }
bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
bool isTargetSpecific() const { return TheKind == TargetSpecific; }

bool canHaveCoerceToType() const {
return isDirect() || isExtend() || isCoerceAndExpand();
return isDirect() || isExtend() || isCoerceAndExpand() ||
isTargetSpecific();
}

// Direct/Extend accessors
unsigned getDirectOffset() const {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
assert((isDirect() || isExtend() || isTargetSpecific()) &&
"Not a direct or extend or target specific kind");
return DirectAttr.Offset;
}
void setDirectOffset(unsigned Offset) {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
assert((isDirect() || isExtend() || isTargetSpecific()) &&
"Not a direct or extend or target specific kind");
DirectAttr.Offset = Offset;
}

unsigned getDirectAlign() const {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
assert((isDirect() || isExtend() || isTargetSpecific()) &&
"Not a direct or extend or target specific kind");
return DirectAttr.Align;
}
void setDirectAlign(unsigned Align) {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
assert((isDirect() || isExtend() || isTargetSpecific()) &&
"Not a direct or extend or target specific kind");
DirectAttr.Align = Align;
}

Expand Down Expand Up @@ -394,12 +419,14 @@ class ABIArgInfo {
}

bool getInReg() const {
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
"Invalid kind!");
return InReg;
}

void setInReg(bool IR) {
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
"Invalid kind!");
InReg = IR;
}

Expand Down Expand Up @@ -481,12 +508,12 @@ class ABIArgInfo {
}

bool getCanBeFlattened() const {
assert(isDirect() && "Invalid kind!");
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
return CanBeFlattened;
}

void setCanBeFlattened(bool Flatten) {
assert(isDirect() && "Invalid kind!");
assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
CanBeFlattened = Flatten;
}

Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ ABIInfo::getOptimalVectorMemoryType(llvm::FixedVectorType *T,
return T;
}

llvm::Value *ABIInfo::createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
CodeGenFunction &CGF) const {
return nullptr;
}

void ABIInfo::createCoercedStore(llvm::Value *Val, Address DstAddr,
const ABIArgInfo &AI, bool DestIsVolatile,
CodeGenFunction &CGF) const {}
// Pin the vtable to this file.
SwiftABIInfo::~SwiftABIInfo() = default;

Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CodeGen/ABIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ class ABIInfo {
virtual llvm::FixedVectorType *
getOptimalVectorMemoryType(llvm::FixedVectorType *T,
const LangOptions &Opt) const;

virtual llvm::Value *createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
CodeGenFunction &CGF) const;
virtual void createCoercedStore(llvm::Value *Val, Address DstAddr,
const ABIArgInfo &AI, bool DestIsVolatile,
CodeGenFunction &CGF) const;
};

/// Target specific hooks for defining how a type should be passed or returned
Expand Down
71 changes: 60 additions & 11 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context,
IRArgs.PaddingArgIndex = IRArgNo++;

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

case ABIArgInfo::TargetSpecific:
case ABIArgInfo::Extend:
case ABIArgInfo::Direct:
resultType = retAI.getCoerceToType();
Expand Down Expand Up @@ -1784,6 +1786,7 @@ llvm::FunctionType *CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
ArgTypes[FirstIRArg] = llvm::PointerType::get(
getLLVMContext(), ArgInfo.getIndirectAddrSpace());
break;
case ABIArgInfo::TargetSpecific:
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
// Fast-isel and the optimizer generally like scalar values better than
Expand Down Expand Up @@ -2697,6 +2700,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
else
RetAttrs.addAttribute(llvm::Attribute::NoExt);
[[fallthrough]];
case ABIArgInfo::TargetSpecific:
case ABIArgInfo::Direct:
if (RetAI.getInReg())
RetAttrs.addAttribute(llvm::Attribute::InReg);
Expand Down Expand Up @@ -2838,6 +2842,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
else
Attrs.addAttribute(llvm::Attribute::NoExt);
[[fallthrough]];
case ABIArgInfo::TargetSpecific:
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
Attrs.addAttribute(llvm::Attribute::Nest);
Expand Down Expand Up @@ -3335,17 +3340,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
}
}

// Struct of fixed-length vectors and struct of array of fixed-length
// vector in VLS calling convention are coerced to vector tuple
// type(represented as TargetExtType) and scalable vector type
// respectively, they're no longer handled as struct.
if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
(isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
ArgVals.push_back(ParamValue::forDirect(AI));
break;
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
Address Alloca =
Expand Down Expand Up @@ -3486,6 +3480,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
break;
}

case ABIArgInfo::TargetSpecific: {
auto *AI = Fn->getArg(FirstIRArg);
AI->setName(Arg->getName() + ".target_coerce");
Address Alloca =
CreateMemTemp(Ty, getContext().getDeclAlign(Arg), Arg->getName());
Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI);
CGM.getABIInfo().createCoercedStore(AI, Ptr, ArgI, false, *this);
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
llvm::Value *V =
EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc());
if (isPromoted) {
V = emitArgumentDemotion(*this, Arg, V);
}
ArgVals.push_back(ParamValue::forDirect(V));
} else {
ArgVals.push_back(ParamValue::forIndirect(Alloca));
}
break;
}
case ABIArgInfo::Ignore:
assert(NumIRArgs == 0);
// Initialize the local variable appropriately.
Expand Down Expand Up @@ -4114,6 +4127,11 @@ void CodeGenFunction::EmitFunctionEpilog(
}
break;
}
case ABIArgInfo::TargetSpecific: {
Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
RV = CGM.getABIInfo().createCoercedLoad(V, RetAI, *this);
break;
}
case ABIArgInfo::Expand:
case ABIArgInfo::IndirectAliased:
llvm_unreachable("Invalid ABI kind for return argument");
Expand Down Expand Up @@ -5691,6 +5709,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(IRArgPos == FirstIRArg + NumIRArgs);
break;
}

case ABIArgInfo::TargetSpecific: {
Address Src = Address::invalid();
if (!I->isAggregate()) {
Src = CreateMemTemp(I->Ty, "target_coerce");
I->copyInto(*this, Src);
} else {
Src = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
}

// If the value is offset in memory, apply the offset now.
Src = emitAddressAtOffset(*this, Src, ArgInfo);
llvm::Value *Load =
CGM.getABIInfo().createCoercedLoad(Src, ArgInfo, *this);
IRCallArgs[FirstIRArg] = Load;
break;
}
}
}

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

case ABIArgInfo::TargetSpecific: {
Address DestPtr = ReturnValue.getValue();
Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
bool DestIsVolatile = ReturnValue.isVolatile();
if (!DestPtr.isValid()) {
DestPtr = CreateMemTemp(RetTy, "target_coerce");
DestIsVolatile = false;
}
CGM.getABIInfo().createCoercedStore(CI, StorePtr, RetAI, DestIsVolatile,
*this);
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}

case ABIArgInfo::Expand:
case ABIArgInfo::IndirectAliased:
llvm_unreachable("Invalid ABI kind for return argument");
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ LLVM_DUMP_METHOD void ABIArgInfo::dump() const {
OS << "CoerceAndExpand Type=";
getCoerceAndExpandType()->print(OS);
break;
case TargetSpecific:
OS << "TargetSpecific Type=";
if (llvm::Type *Ty = getCoerceToType())
Ty->print(OS);
else
OS << "null";
break;
}
OS << ")\n";
}
Expand Down
Loading