Skip to content

[clang][CodeGen] Return RValue from EmitVAArg #94635

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

Merged
merged 12 commits into from
Jun 17, 2024
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ bool ABIInfo::isOHOSFamily() const {
return getTarget().getTriple().isOHOSFamily();
}

Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
return Address::invalid();
RValue ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty, AggValueSlot Slot) const {
return RValue::getIgnored();
}

bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/CodeGen/ABIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class CGCXXABI;
class CGFunctionInfo;
class CodeGenFunction;
class CodeGenTypes;
class RValue;
class AggValueSlot;

// FIXME: All of this stuff should be part of the target interface
// somehow. It is currently here because it is not clear how to factor
Expand Down Expand Up @@ -75,18 +77,18 @@ class ABIInfo {
// the ABI information any lower than CodeGen. Of course, for
// VAArg handling it has to be at this level; there is no way to
// abstract this out.
virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF,
CodeGen::Address VAListAddr,
QualType Ty) const = 0;
virtual RValue EmitVAArg(CodeGen::CodeGenFunction &CGF,
CodeGen::Address VAListAddr, QualType Ty,
AggValueSlot Slot) const = 0;

bool isAndroid() const;
bool isOHOSFamily() const;

/// Emit the target dependent code to load a value of
/// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr.
virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
CodeGen::Address VAListAddr,
QualType Ty) const;
virtual RValue EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
CodeGen::Address VAListAddr, QualType Ty,
AggValueSlot Slot) const;

virtual bool isHomogeneousAggregateBaseType(QualType Ty) const;

Expand Down
23 changes: 13 additions & 10 deletions clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,12 @@ void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {
I.info = classifyArgumentType(I.type);
}

Address DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty));
RValue DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty, AggValueSlot Slot) const {
return CGF.EmitLoadOfAnyValue(
CGF.MakeAddrLValue(
EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)), Ty),
Slot);
}

ABIArgInfo CodeGen::coerceToIntArray(QualType Ty, ASTContext &Context,
Expand Down Expand Up @@ -199,12 +202,12 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
return Addr.withElementType(DirectTy);
}

Address CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType ValueTy, bool IsIndirect,
TypeInfoChars ValueInfo,
CharUnits SlotSizeAndAlign,
bool AllowHigherAlign,
bool ForceRightAdjust) {
RValue CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType ValueTy, bool IsIndirect,
TypeInfoChars ValueInfo,
CharUnits SlotSizeAndAlign,
bool AllowHigherAlign, AggValueSlot Slot,
bool ForceRightAdjust) {
// The size and alignment of the value that was passed directly.
CharUnits DirectSize, DirectAlign;
if (IsIndirect) {
Expand All @@ -230,7 +233,7 @@ Address CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align);
}

return Addr;
return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Addr, ValueTy), Slot);
}

Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/CodeGen/ABIInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class DefaultABIInfo : public ABIInfo {

void computeInfo(CGFunctionInfo &FI) const override;

Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
AggValueSlot Slot) const override;
};

// Helper for coercing an aggregate argument or return value into an integer
Expand Down Expand Up @@ -112,10 +112,11 @@ Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
/// \param ForceRightAdjust - Default is false. On big-endian platform and
/// if the argument is smaller than a slot, set this flag will force
/// right-adjust the argument in its slot irrespective of the type.
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType ValueTy, bool IsIndirect,
TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign,
bool AllowHigherAlign, bool ForceRightAdjust = false);
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType ValueTy, bool IsIndirect,
TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign,
bool AllowHigherAlign, AggValueSlot Slot,
bool ForceRightAdjust = false);

Address emitMergePHI(CodeGenFunction &CGF, Address Addr1,
llvm::BasicBlock *Block1, Address Addr2,
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5989,12 +5989,12 @@ CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const {

/* VarArg handling */

Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) {
VAListAddr = VE->isMicrosoftABI()
? EmitMSVAListRef(VE->getSubExpr())
: EmitVAListRef(VE->getSubExpr());
RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
AggValueSlot Slot) {
VAListAddr = VE->isMicrosoftABI() ? EmitMSVAListRef(VE->getSubExpr())
: EmitVAListRef(VE->getSubExpr());
QualType Ty = VE->getType();
if (VE->isMicrosoftABI())
return CGM.getTypes().getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty);
return CGM.getTypes().getABIInfo().EmitVAArg(*this, VAListAddr, Ty);
return CGM.getTypes().getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot);
return CGM.getTypes().getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot);
}
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2161,6 +2161,21 @@ static RValue EmitLoadOfMatrixLValue(LValue LV, SourceLocation Loc,
return RValue::get(CGF.EmitLoadOfScalar(LV, Loc));
}

RValue CodeGenFunction::EmitLoadOfAnyValue(LValue LV, AggValueSlot Slot,
SourceLocation Loc) {
QualType Ty = LV.getType();
switch (getEvaluationKind(Ty)) {
case TEK_Scalar:
return EmitLoadOfLValue(LV, Loc);
case TEK_Complex:
return RValue::getComplex(EmitLoadOfComplex(LV, Loc));
case TEK_Aggregate:
EmitAggFinalDestCopy(Ty, Slot, LV, EVK_NonRValue);
return Slot.asRValue();
}
llvm_unreachable("bad evaluation kind");
}

/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
/// method emits the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
Expand Down
30 changes: 16 additions & 14 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,11 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
/// then loads the result into DestPtr.
void EmitAggLoadOfLValue(const Expr *E);

enum ExprValueKind {
EVK_RValue,
EVK_NonRValue
};

/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
/// SrcIsRValue is true if source comes from an RValue.
void EmitFinalDestCopy(QualType type, const LValue &src,
ExprValueKind SrcValueKind = EVK_NonRValue);
CodeGenFunction::ExprValueKind SrcValueKind =
CodeGenFunction::EVK_NonRValue);
void EmitFinalDestCopy(QualType type, RValue src);
void EmitCopy(QualType type, const AggValueSlot &dest,
const AggValueSlot &src);
Expand Down Expand Up @@ -348,12 +344,13 @@ void AggExprEmitter::withReturnValueSlot(
void AggExprEmitter::EmitFinalDestCopy(QualType type, RValue src) {
assert(src.isAggregate() && "value must be aggregate value!");
LValue srcLV = CGF.MakeAddrLValue(src.getAggregateAddress(), type);
EmitFinalDestCopy(type, srcLV, EVK_RValue);
EmitFinalDestCopy(type, srcLV, CodeGenFunction::EVK_RValue);
}

/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src,
ExprValueKind SrcValueKind) {
void AggExprEmitter::EmitFinalDestCopy(
QualType type, const LValue &src,
CodeGenFunction::ExprValueKind SrcValueKind) {
// If Dest is ignored, then we're evaluating an aggregate expression
// in a context that doesn't care about the result. Note that loads
// from volatile l-values force the existence of a non-ignored
Expand All @@ -365,7 +362,7 @@ void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src,
LValue DstLV = CGF.MakeAddrLValue(
Dest.getAddress(), Dest.isVolatile() ? type.withVolatile() : type);

if (SrcValueKind == EVK_RValue) {
if (SrcValueKind == CodeGenFunction::EVK_RValue) {
if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
if (Dest.isPotentiallyAliased())
CGF.callCStructMoveAssignmentOperator(DstLV, src);
Expand Down Expand Up @@ -1317,15 +1314,13 @@ void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {

void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
Address ArgValue = Address::invalid();
Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
CGF.EmitVAArg(VE, ArgValue, Dest);

// If EmitVAArg fails, emit an error.
if (!ArgPtr.isValid()) {
if (!ArgValue.isValid()) {
CGF.ErrorUnsupported(VE, "aggregate va_arg expression");
return;
}

EmitFinalDestCopy(VE->getType(), CGF.MakeAddrLValue(ArgPtr, VE->getType()));
}

void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
Expand Down Expand Up @@ -2027,6 +2022,13 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
return LV;
}

void CodeGenFunction::EmitAggFinalDestCopy(QualType Type, AggValueSlot Dest,
const LValue &Src,
ExprValueKind SrcKind) {
return AggExprEmitter(*this, Dest, Dest.isIgnored())
.EmitFinalDestCopy(Type, Src, SrcKind);
}

AggValueSlot::Overlap_t
CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) {
if (!FD->hasAttr<NoUniqueAddressAttr>() || !FD->getType()->isRecordType())
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,18 +1448,17 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {

ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
Address ArgValue = Address::invalid();
Address ArgPtr = CGF.EmitVAArg(E, ArgValue);
RValue RV = CGF.EmitVAArg(E, ArgValue);

if (!ArgPtr.isValid()) {
if (!ArgValue.isValid()) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
llvm::Type *EltTy =
CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return ComplexPairTy(U, U);
}

return EmitLoadOfLValue(CGF.MakeAddrLValue(ArgPtr, E->getType()),
E->getExprLoc());
return RV.getComplexVal();
}

//===----------------------------------------------------------------------===//
Expand Down
23 changes: 2 additions & 21 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5357,28 +5357,9 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
CGF.EmitVariablyModifiedType(Ty);

Address ArgValue = Address::invalid();
Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
RValue ArgPtr = CGF.EmitVAArg(VE, ArgValue);

llvm::Type *ArgTy = ConvertType(VE->getType());

// If EmitVAArg fails, emit an error.
if (!ArgPtr.isValid()) {
CGF.ErrorUnsupported(VE, "va_arg expression");
return llvm::UndefValue::get(ArgTy);
}

// FIXME Volatility.
llvm::Value *Val = Builder.CreateLoad(ArgPtr);

// If EmitVAArg promoted the type, we must truncate it.
if (ArgTy != Val->getType()) {
if (ArgTy->isPointerTy() && !Val->getType()->isPointerTy())
Val = Builder.CreateIntToPtr(Val, ArgTy);
else
Val = Builder.CreateTrunc(Val, ArgTy);
}

return Val;
return ArgPtr.getScalarVal();
}

Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) {
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3014,7 +3014,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// \returns A pointer to the argument.
// FIXME: We should be able to get rid of this method and use the va_arg
// instruction in LLVM instead once it works well enough.
Address EmitVAArg(VAArgExpr *VE, Address &VAListAddr);
RValue EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
AggValueSlot Slot = AggValueSlot::ignored());

/// emitArrayLength - Compute the length of an array, even if it's a
/// VLA, and drill down to the base element type.
Expand Down Expand Up @@ -4215,6 +4216,11 @@ class CodeGenFunction : public CodeGenTypeCache {
RValue EmitLoadOfBitfieldLValue(LValue LV, SourceLocation Loc);
RValue EmitLoadOfGlobalRegLValue(LValue LV);

/// Like EmitLoadOfLValue but also handles complex and aggregate types.
RValue EmitLoadOfAnyValue(LValue V,
AggValueSlot Slot = AggValueSlot::ignored(),
SourceLocation Loc = {});

/// EmitStoreThroughLValue - Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
Expand Down Expand Up @@ -4775,6 +4781,13 @@ class CodeGenFunction : public CodeGenTypeCache {
/// aggregate type into a temporary LValue.
LValue EmitAggExprToLValue(const Expr *E);

enum ExprValueKind { EVK_RValue, EVK_NonRValue };

/// EmitAggFinalDestCopy - Emit copy of the specified aggregate into
/// destination address.
void EmitAggFinalDestCopy(QualType Type, AggValueSlot Dest, const LValue &Src,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels strange to be adding this API now... but I guess it's fine? The alternative would be to use EmitAggregateCopy directly. It only really makes a difference for structs containing pointers to ObjC types, which can't be passed by va_arg anyway, but I guess it's better for EmitLoadOfAnyValue to be fully general in case we add other uses in the future.

ExprValueKind SrcKind);

/// Build all the stores needed to initialize an aggregate at Dest with the
/// value Val.
void EmitAggregateStore(llvm::Value *Val, Address Dest, bool DestIsVolatile);
Expand Down
Loading