Change hasAggregateLLVMType, which conflates complex and
aggregate types in a profoundly wrong way that has to be
worked around in every call site, to getEvaluationKind,
which classifies and distinguishes between all of these
cases.
Also, normalize the API for loading and storing complexes.
I'm working on a larger patch and wanted to pull these
changes out, but it would have be annoying to detangle
them from each other.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176656 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index f55a8e5..8a69e8a 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1496,9 +1496,7 @@
ErrorUnsupported(E, "builtin function");
// Unknown builtin, for now just dump it out and return undef.
- if (hasAggregateLLVMType(E->getType()))
- return RValue::getAggregate(CreateMemTemp(E->getType()));
- return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
+ return GetUndefRValue(E->getType());
}
Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 6aabd64..b6ec67d 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1278,7 +1278,7 @@
case ABIArgInfo::Indirect: {
llvm::Value *V = AI;
- if (hasAggregateLLVMType(Ty)) {
+ if (!hasScalarEvaluationKind(Ty)) {
// Aggregates and complex variables are accessed by reference. All we
// need to do is realign the value, if requested
if (ArgI.getIndirectRealign()) {
@@ -1411,7 +1411,7 @@
// Match to what EmitParmDecl is expecting for this type.
- if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty);
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
@@ -1440,7 +1440,7 @@
case ABIArgInfo::Ignore:
// Initialize the local variable appropriately.
- if (hasAggregateLLVMType(Ty))
+ if (!hasScalarEvaluationKind(Ty))
EmitParmDecl(*Arg, CreateMemTemp(Ty), ArgNo);
else
EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())),
@@ -1664,15 +1664,23 @@
switch (RetAI.getKind()) {
case ABIArgInfo::Indirect: {
- unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
- if (RetTy->isAnyComplexType()) {
- ComplexPairTy RT = LoadComplexFromAddr(ReturnValue, false);
- StoreComplexToAddr(RT, CurFn->arg_begin(), false);
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ switch (getEvaluationKind(RetTy)) {
+ case TEK_Complex: {
+ ComplexPairTy RT =
+ EmitLoadOfComplex(MakeNaturalAlignAddrLValue(ReturnValue, RetTy));
+ EmitStoreOfComplex(RT,
+ MakeNaturalAlignAddrLValue(CurFn->arg_begin(), RetTy),
+ /*isInit*/ true);
+ break;
+ }
+ case TEK_Aggregate:
// Do nothing; aggregrates get evaluated directly into the destination.
- } else {
- EmitStoreOfScalar(Builder.CreateLoad(ReturnValue), CurFn->arg_begin(),
- false, Alignment, RetTy);
+ break;
+ case TEK_Scalar:
+ EmitStoreOfScalar(Builder.CreateLoad(ReturnValue),
+ MakeNaturalAlignAddrLValue(CurFn->arg_begin(), RetTy),
+ /*isInit*/ true);
+ break;
}
break;
}
@@ -1749,10 +1757,10 @@
// For the most part, we just need to load the alloca, except:
// 1) aggregate r-values are actually pointers to temporaries, and
- // 2) references to aggregates are pointers directly to the aggregate.
- // I don't know why references to non-aggregates are different here.
+ // 2) references to non-scalars are pointers directly to the aggregate.
+ // I don't know why references to scalars are different here.
if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
- if (hasAggregateLLVMType(ref->getPointeeType()))
+ if (!hasScalarEvaluationKind(ref->getPointeeType()))
return args.add(RValue::getAggregate(local), type);
// Locals which are references to scalars are represented
@@ -1760,17 +1768,7 @@
return args.add(RValue::get(Builder.CreateLoad(local)), type);
}
- if (type->isAnyComplexType()) {
- ComplexPairTy complex = LoadComplexFromAddr(local, /*volatile*/ false);
- return args.add(RValue::getComplex(complex), type);
- }
-
- if (hasAggregateLLVMType(type))
- return args.add(RValue::getAggregate(local), type);
-
- unsigned alignment = getContext().getDeclAlign(param).getQuantity();
- llvm::Value *value = EmitLoadOfScalar(local, false, alignment, type);
- return args.add(RValue::get(value), type);
+ args.add(convertTempToRValue(local, type), type);
}
static bool isProvablyNull(llvm::Value *addr) {
@@ -1935,7 +1933,7 @@
type);
}
- if (hasAggregateLLVMType(type) && !E->getType()->isAnyComplexType() &&
+ if (hasAggregateEvaluationKind(type) &&
isa<ImplicitCastExpr>(E) &&
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) {
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
@@ -2079,15 +2077,7 @@
llvm::Value *Addr = RV.getAggregateAddr();
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
- LValue LV = MakeAddrLValue(EltAddr, EltTy);
- RValue EltRV;
- if (EltTy->isAnyComplexType())
- // FIXME: Volatile?
- EltRV = RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
- else if (CodeGenFunction::hasAggregateLLVMType(EltTy))
- EltRV = LV.asAggregateRValue();
- else
- EltRV = EmitLoadOfLValue(LV);
+ RValue EltRV = convertTempToRValue(EltAddr, EltTy);
ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy);
}
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -2180,8 +2170,7 @@
const ABIArgInfo &ArgInfo = info_it->info;
RValue RV = I->RV;
- unsigned TypeAlign =
- getContext().getTypeAlignInChars(I->Ty).getQuantity();
+ CharUnits TypeAlign = getContext().getTypeAlignInChars(I->Ty);
// Insert a padding argument to ensure proper alignment.
if (llvm::Type *PaddingType = ArgInfo.getPaddingType()) {
@@ -2197,12 +2186,14 @@
if (ArgInfo.getIndirectAlign() > AI->getAlignment())
AI->setAlignment(ArgInfo.getIndirectAlign());
Args.push_back(AI);
+
+ LValue argLV =
+ MakeAddrLValue(Args.back(), I->Ty, TypeAlign);
if (RV.isScalar())
- EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false,
- TypeAlign, I->Ty);
+ EmitStoreOfScalar(RV.getScalarVal(), argLV, /*init*/ true);
else
- StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
+ EmitStoreOfComplex(RV.getComplexVal(), argLV, /*init*/ true);
// Validate argument match.
checkArgMatches(AI, IRArgNo, IRFuncTy);
@@ -2217,7 +2208,7 @@
unsigned Align = ArgInfo.getIndirectAlign();
const llvm::DataLayout *TD = &CGM.getDataLayout();
if ((!ArgInfo.getIndirectByVal() && I->NeedsCopy) ||
- (ArgInfo.getIndirectByVal() && TypeAlign < Align &&
+ (ArgInfo.getIndirectByVal() && TypeAlign.getQuantity() < Align &&
llvm::getOrEnforceKnownAlignment(Addr, Align, TD) < Align)) {
// Create an aligned temporary, and copy to it.
llvm::AllocaInst *AI = CreateMemTemp(I->Ty);
@@ -2266,12 +2257,14 @@
// FIXME: Avoid the conversion through memory if possible.
llvm::Value *SrcPtr;
- if (RV.isScalar()) {
+ if (RV.isScalar() || RV.isComplex()) {
SrcPtr = CreateMemTemp(I->Ty, "coerce");
- EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, TypeAlign, I->Ty);
- } else if (RV.isComplex()) {
- SrcPtr = CreateMemTemp(I->Ty, "coerce");
- StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false);
+ LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign);
+ if (RV.isScalar()) {
+ EmitStoreOfScalar(RV.getScalarVal(), SrcLV, /*init*/ true);
+ } else {
+ EmitStoreOfComplex(RV.getComplexVal(), SrcLV, /*init*/ true);
+ }
} else
SrcPtr = RV.getAggregateAddr();
@@ -2424,14 +2417,8 @@
emitWritebacks(*this, CallArgs);
switch (RetAI.getKind()) {
- case ABIArgInfo::Indirect: {
- unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
- if (RetTy->isAnyComplexType())
- return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
- if (CodeGenFunction::hasAggregateLLVMType(RetTy))
- return RValue::getAggregate(Args[0]);
- return RValue::get(EmitLoadOfScalar(Args[0], false, Alignment, RetTy));
- }
+ case ABIArgInfo::Indirect:
+ return convertTempToRValue(Args[0], RetTy);
case ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to
@@ -2442,12 +2429,13 @@
case ABIArgInfo::Direct: {
llvm::Type *RetIRTy = ConvertType(RetTy);
if (RetAI.getCoerceToType() == RetIRTy && RetAI.getDirectOffset() == 0) {
- if (RetTy->isAnyComplexType()) {
+ switch (getEvaluationKind(RetTy)) {
+ case TEK_Complex: {
llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
return RValue::getComplex(std::make_pair(Real, Imag));
}
- if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ case TEK_Aggregate: {
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
@@ -2458,13 +2446,16 @@
BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false);
return RValue::getAggregate(DestPtr);
}
-
- // If the argument doesn't match, perform a bitcast to coerce it. This
- // can happen due to trivial type mismatches.
- llvm::Value *V = CI;
- if (V->getType() != RetIRTy)
- V = Builder.CreateBitCast(V, RetIRTy);
- return RValue::get(V);
+ case TEK_Scalar: {
+ // If the argument doesn't match, perform a bitcast to coerce it. This
+ // can happen due to trivial type mismatches.
+ llvm::Value *V = CI;
+ if (V->getType() != RetIRTy)
+ V = Builder.CreateBitCast(V, RetIRTy);
+ return RValue::get(V);
+ }
+ }
+ llvm_unreachable("bad evaluation kind");
}
llvm::Value *DestPtr = ReturnValue.getValue();
@@ -2485,12 +2476,7 @@
}
CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
- unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
- if (RetTy->isAnyComplexType())
- return RValue::getComplex(LoadComplexFromAddr(DestPtr, false));
- if (CodeGenFunction::hasAggregateLLVMType(RetTy))
- return RValue::getAggregate(DestPtr);
- return RValue::get(EmitLoadOfScalar(DestPtr, false, Alignment, RetTy));
+ return convertTempToRValue(DestPtr, RetTy);
}
case ABIArgInfo::Expand:
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 4319e43..287d164 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -451,12 +451,14 @@
LV.setAlignment(std::min(Align, LV.getAlignment()));
}
- if (!CGF.hasAggregateLLVMType(T)) {
+ switch (CGF.getEvaluationKind(T)) {
+ case TEK_Scalar:
CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
- } else if (T->isAnyComplexType()) {
- CGF.EmitComplexExprIntoAddr(Init, LV.getAddress(),
- LV.isVolatileQualified());
- } else {
+ break;
+ case TEK_Complex:
+ CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
+ break;
+ case TEK_Aggregate: {
AggValueSlot Slot =
AggValueSlot::forLValue(LV,
AggValueSlot::IsDestructed,
@@ -464,6 +466,8 @@
AggValueSlot::IsNotAliased);
CGF.EmitAggExpr(Init, Slot);
+ break;
+ }
}
}
@@ -600,16 +604,19 @@
LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes) {
QualType FieldType = Field->getType();
- if (!hasAggregateLLVMType(FieldType)) {
+ switch (getEvaluationKind(FieldType)) {
+ case TEK_Scalar:
if (LHS.isSimple()) {
EmitExprAsInit(Init, Field, LHS, false);
} else {
RValue RHS = RValue::get(EmitScalarExpr(Init));
EmitStoreThroughLValue(RHS, LHS);
}
- } else if (FieldType->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, LHS.getAddress(), LHS.isVolatileQualified());
- } else {
+ break;
+ case TEK_Complex:
+ EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
+ break;
+ case TEK_Aggregate: {
llvm::Value *ArrayIndexVar = 0;
if (ArrayIndexes.size()) {
llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
@@ -638,6 +645,7 @@
EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType,
ArrayIndexes, 0);
}
+ }
// Ensure that we destroy this object if an exception is thrown
// later in the constructor.
@@ -2173,7 +2181,7 @@
ReturnValueSlot returnSlot;
if (!resultType->isVoidType() &&
calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- hasAggregateLLVMType(calleeFnInfo.getReturnType()))
+ !hasScalarEvaluationKind(calleeFnInfo.getReturnType()))
returnSlot = ReturnValueSlot(ReturnValue, resultType.isVolatileQualified());
// We don't need to separately arrange the call arguments because
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index f9ea7e0..861d31f 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -52,7 +52,8 @@
llvm::StructType::get(V.first->getType(), V.second->getType(),
(void*) 0);
llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
- CGF.StoreComplexToAddr(V, addr, /*volatile*/ false);
+ CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0));
+ CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1));
return saved_type(addr, ComplexAddress);
}
@@ -79,8 +80,13 @@
return RValue::getAggregate(Value);
case AggregateAddress:
return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
- case ComplexAddress:
- return RValue::getComplex(CGF.LoadComplexFromAddr(Value, false));
+ case ComplexAddress: {
+ llvm::Value *real =
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 0));
+ llvm::Value *imag =
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 1));
+ return RValue::getComplex(real, imag);
+ }
}
llvm_unreachable("bad saved r-value kind");
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 9c52314..bb5d638 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1115,21 +1115,29 @@
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
EmitStoreThroughLValue(rvalue, lvalue, true);
- } else if (!hasAggregateLLVMType(type)) {
+ return;
+ }
+ switch (getEvaluationKind(type)) {
+ case TEK_Scalar:
EmitScalarInit(init, D, lvalue, capturedByInit);
- } else if (type->isAnyComplexType()) {
+ return;
+ case TEK_Complex: {
ComplexPairTy complex = EmitComplexExpr(init);
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
- StoreComplexToAddr(complex, lvalue.getAddress(), lvalue.isVolatile());
- } else {
+ EmitStoreOfComplex(complex, lvalue, /*init*/ true);
+ return;
+ }
+ case TEK_Aggregate:
// TODO: how can we delay here if D is captured by its initializer?
EmitAggExpr(init, AggValueSlot::forLValue(lvalue,
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
MaybeEmitStdInitializerListCleanup(lvalue.getAddress(), init);
+ return;
}
+ llvm_unreachable("bad evaluation kind");
}
/// Enter a destroy cleanup for the given local variable.
@@ -1521,7 +1529,7 @@
llvm::Value *DeclPtr;
// If this is an aggregate or variable sized value, reuse the input pointer.
if (!Ty->isConstantSizeType() ||
- CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ !CodeGenFunction::hasScalarEvaluationKind(Ty)) {
DeclPtr = Arg;
} else {
// Otherwise, create a temporary to hold the value.
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 9b6c5d7..0448d31 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -34,7 +34,8 @@
LValue lv = CGF.MakeAddrLValue(DeclPtr, type, alignment);
const Expr *Init = D.getInit();
- if (!CGF.hasAggregateLLVMType(type)) {
+ switch (CGF.getEvaluationKind(type)) {
+ case TEK_Scalar: {
CodeGenModule &CGM = CGF.CGM;
if (lv.isObjCStrong())
CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
@@ -44,13 +45,18 @@
DeclPtr);
else
CGF.EmitScalarInit(Init, &D, lv, false);
- } else if (type->isAnyComplexType()) {
- CGF.EmitComplexExprIntoAddr(Init, DeclPtr, lv.isVolatile());
- } else {
+ return;
+ }
+ case TEK_Complex:
+ CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);
+ return;
+ case TEK_Aggregate:
CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
+ return;
}
+ llvm_unreachable("bad evaluation kind");
}
/// Emit code to cause the destruction of the given variable with
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 9794ca4..36642bc 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -1002,10 +1002,9 @@
return;
}
- // Non-aggregates (plus complexes).
- bool IsComplex = false;
- if (!CGF.hasAggregateLLVMType(CatchType) ||
- (IsComplex = CatchType->isAnyComplexType())) {
+ // Scalars and complexes.
+ TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);
+ if (TEK != TEK_Aggregate) {
llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
// If the catch type is a pointer type, __cxa_begin_catch returns
@@ -1037,17 +1036,23 @@
llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
- if (IsComplex) {
- CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false),
- ParamAddr, /*volatile*/ false);
- } else {
- unsigned Alignment =
- CGF.getContext().getDeclAlign(&CatchParam).getQuantity();
- llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar");
- CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment,
- CatchType);
+ LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);
+ LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,
+ CGF.getContext().getDeclAlign(&CatchParam));
+ switch (TEK) {
+ case TEK_Complex:
+ CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV), destLV,
+ /*init*/ true);
+ return;
+ case TEK_Scalar: {
+ llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV);
+ CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
+ return;
}
- return;
+ case TEK_Aggregate:
+ llvm_unreachable("evaluation kind filtered out!");
+ }
+ llvm_unreachable("bad evaluation kind");
}
assert(isa<RecordType>(CatchType) && "unexpected catch type!");
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 9b3638a..21cb08d 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -114,15 +114,18 @@
RValue CodeGenFunction::EmitAnyExpr(const Expr *E,
AggValueSlot aggSlot,
bool ignoreResult) {
- if (!hasAggregateLLVMType(E->getType()))
+ switch (getEvaluationKind(E->getType())) {
+ case TEK_Scalar:
return RValue::get(EmitScalarExpr(E, ignoreResult));
- else if (E->getType()->isAnyComplexType())
+ case TEK_Complex:
return RValue::getComplex(EmitComplexExpr(E, ignoreResult, ignoreResult));
-
- if (!ignoreResult && aggSlot.isIgnored())
- aggSlot = CreateAggTemp(E->getType(), "agg-temp");
- EmitAggExpr(E, aggSlot);
- return aggSlot.asRValue();
+ case TEK_Aggregate:
+ if (!ignoreResult && aggSlot.isIgnored())
+ aggSlot = CreateAggTemp(E->getType(), "agg-temp");
+ EmitAggExpr(E, aggSlot);
+ return aggSlot.asRValue();
+ }
+ llvm_unreachable("bad evaluation kind");
}
/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
@@ -130,8 +133,7 @@
RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
AggValueSlot AggSlot = AggValueSlot::ignored();
- if (hasAggregateLLVMType(E->getType()) &&
- !E->getType()->isAnyComplexType())
+ if (hasAggregateEvaluationKind(E->getType()))
AggSlot = CreateAggTemp(E->getType(), "agg.tmp");
return EmitAnyExpr(E, AggSlot);
}
@@ -143,19 +145,30 @@
Qualifiers Quals,
bool IsInit) {
// FIXME: This function should take an LValue as an argument.
- if (E->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(E, Location, Quals.hasVolatile());
- } else if (hasAggregateLLVMType(E->getType())) {
+ switch (getEvaluationKind(E->getType())) {
+ case TEK_Complex:
+ EmitComplexExprIntoLValue(E,
+ MakeNaturalAlignAddrLValue(Location, E->getType()),
+ /*isInit*/ false);
+ return;
+
+ case TEK_Aggregate: {
CharUnits Alignment = getContext().getTypeAlignInChars(E->getType());
EmitAggExpr(E, AggValueSlot::forAddr(Location, Alignment, Quals,
AggValueSlot::IsDestructed_t(IsInit),
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsAliased_t(!IsInit)));
- } else {
+ return;
+ }
+
+ case TEK_Scalar: {
RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false));
LValue LV = MakeAddrLValue(Location, E->getType());
EmitStoreThroughLValue(RV, LV);
+ return;
}
+ }
+ llvm_unreachable("bad evaluation kind");
}
static llvm::Value *
@@ -288,8 +301,7 @@
// Create a reference temporary if necessary.
AggValueSlot AggSlot = AggValueSlot::ignored();
- if (CGF.hasAggregateLLVMType(E->getType()) &&
- !E->getType()->isAnyComplexType()) {
+ if (CGF.hasAggregateEvaluationKind(E->getType())) {
ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
InitializedDecl);
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(E->getType());
@@ -370,14 +382,12 @@
InitializedDecl);
- unsigned Alignment =
- CGF.getContext().getTypeAlignInChars(E->getType()).getQuantity();
+ LValue tempLV = CGF.MakeNaturalAlignAddrLValue(ReferenceTemporary,
+ E->getType());
if (RV.isScalar())
- CGF.EmitStoreOfScalar(RV.getScalarVal(), ReferenceTemporary,
- /*Volatile=*/false, Alignment, E->getType());
+ CGF.EmitStoreOfScalar(RV.getScalarVal(), tempLV, /*init*/ true);
else
- CGF.StoreComplexToAddr(RV.getComplexVal(), ReferenceTemporary,
- /*Volatile=*/false);
+ CGF.EmitStoreOfComplex(RV.getComplexVal(), tempLV, /*init*/ true);
return ReferenceTemporary;
}
@@ -713,8 +723,7 @@
CodeGenFunction::ComplexPairTy CodeGenFunction::
EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre) {
- ComplexPairTy InVal = LoadComplexFromAddr(LV.getAddress(),
- LV.isVolatileQualified());
+ ComplexPairTy InVal = EmitLoadOfComplex(LV);
llvm::Value *NextVal;
if (isa<llvm::IntegerType>(InVal.first->getType())) {
@@ -737,7 +746,7 @@
ComplexPairTy IncVal(NextVal, InVal.second);
// Store the updated result through the lvalue.
- StoreComplexToAddr(IncVal, LV.getAddress(), LV.isVolatileQualified());
+ EmitStoreOfComplex(IncVal, LV, /*init*/ false);
// If this is a postinc, return the value read from memory, otherwise use the
// updated value.
@@ -752,9 +761,11 @@
RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
if (Ty->isVoidType())
return RValue::get(0);
-
- if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
- llvm::Type *EltTy = ConvertType(CTy->getElementType());
+
+ switch (getEvaluationKind(Ty)) {
+ case TEK_Complex: {
+ llvm::Type *EltTy =
+ ConvertType(Ty->castAs<ComplexType>()->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return RValue::getComplex(std::make_pair(U, U));
}
@@ -762,12 +773,15 @@
// If this is a use of an undefined aggregate type, the aggregate must have an
// identifiable address. Just because the contents of the value are undefined
// doesn't mean that the address can't be taken and compared.
- if (hasAggregateLLVMType(Ty)) {
+ case TEK_Aggregate: {
llvm::Value *DestPtr = CreateMemTemp(Ty, "undef.agg.tmp");
return RValue::getAggregate(DestPtr);
}
-
- return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
+
+ case TEK_Scalar:
+ return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
+ }
+ llvm_unreachable("bad evaluation kind");
}
RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E,
@@ -1093,7 +1107,6 @@
llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
llvm::MDNode *TBAAInfo) {
-
// For better performance, handle vector loads differently.
if (Ty->isVectorType()) {
llvm::Value *V;
@@ -1237,7 +1250,7 @@
}
Value = EmitToMemory(Value, Ty);
-
+
llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
if (Alignment)
Store->setAlignment(Alignment);
@@ -1248,7 +1261,7 @@
}
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
- bool isInit) {
+ bool isInit) {
EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getAlignment().getQuantity(), lvalue.getType(),
lvalue.getTBAAInfo(), isInit);
@@ -2579,8 +2592,7 @@
EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
if (!expr->isGLValue()) {
// ?: here should be an aggregate.
- assert((hasAggregateLLVMType(expr->getType()) &&
- !expr->getType()->isAnyComplexType()) &&
+ assert(hasAggregateEvaluationKind(expr->getType()) &&
"Unexpected conditional operator!");
return EmitAggExprToLValue(expr);
}
@@ -2808,14 +2820,15 @@
const FieldDecl *FD) {
QualType FT = FD->getType();
LValue FieldLV = EmitLValueForField(LV, FD);
- if (FT->isAnyComplexType())
- return RValue::getComplex(
- LoadComplexFromAddr(FieldLV.getAddress(),
- FieldLV.isVolatileQualified()));
- else if (CodeGenFunction::hasAggregateLLVMType(FT))
+ switch (getEvaluationKind(FT)) {
+ case TEK_Complex:
+ return RValue::getComplex(EmitLoadOfComplex(FieldLV));
+ case TEK_Aggregate:
return FieldLV.asAggregateRValue();
-
- return EmitLoadOfLValue(FieldLV);
+ case TEK_Scalar:
+ return EmitLoadOfLValue(FieldLV);
+ }
+ llvm_unreachable("bad evaluation kind");
}
//===--------------------------------------------------------------------===//
@@ -2922,8 +2935,9 @@
// Note that in all of these cases, __block variables need the RHS
// evaluated first just in case the variable gets moved by the RHS.
-
- if (!hasAggregateLLVMType(E->getType())) {
+
+ switch (getEvaluationKind(E->getType())) {
+ case TEK_Scalar: {
switch (E->getLHS()->getType().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
return EmitARCStoreStrong(E, /*ignored*/ false).first;
@@ -2944,10 +2958,13 @@
return LV;
}
- if (E->getType()->isAnyComplexType())
+ case TEK_Complex:
return EmitComplexAssignmentLValue(E);
- return EmitAggExprToLValue(E);
+ case TEK_Aggregate:
+ return EmitAggExprToLValue(E);
+ }
+ llvm_unreachable("bad evaluation kind");
}
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
@@ -3271,13 +3288,20 @@
return DeclPtr;
}
-static RValue ConvertTempToRValue(CodeGenFunction &CGF, QualType Ty,
- llvm::Value *Dest) {
- if (Ty->isAnyComplexType())
- return RValue::getComplex(CGF.LoadComplexFromAddr(Dest, false));
- if (CGF.hasAggregateLLVMType(Ty))
- return RValue::getAggregate(Dest);
- return RValue::get(CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(Dest, Ty)));
+/// Given the address of a temporary variable, produce an r-value of
+/// its type.
+RValue CodeGenFunction::convertTempToRValue(llvm::Value *addr,
+ QualType type) {
+ LValue lvalue = MakeNaturalAlignAddrLValue(addr, type);
+ switch (getEvaluationKind(type)) {
+ case TEK_Complex:
+ return RValue::getComplex(EmitLoadOfComplex(lvalue));
+ case TEK_Aggregate:
+ return lvalue.asAggregateRValue();
+ case TEK_Scalar:
+ return RValue::get(EmitLoadOfScalar(lvalue));
+ }
+ llvm_unreachable("bad evaluation kind");
}
RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
@@ -3299,23 +3323,24 @@
if (E->getOp() == AtomicExpr::AO__c11_atomic_init) {
assert(!Dest && "Init does not return a value");
- if (!hasAggregateLLVMType(E->getVal1()->getType())) {
- QualType PointeeType
- = E->getPtr()->getType()->getAs<PointerType>()->getPointeeType();
- EmitScalarInit(EmitScalarExpr(E->getVal1()),
- LValue::MakeAddr(Ptr, PointeeType, alignChars,
- getContext()));
- } else if (E->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(E->getVal1(), Ptr, E->isVolatile());
- } else {
- AggValueSlot Slot = AggValueSlot::forAddr(Ptr, alignChars,
- AtomicTy.getQualifiers(),
+ LValue LV = MakeAddrLValue(Ptr, AtomicTy, alignChars);
+ switch (getEvaluationKind(E->getVal1()->getType())) {
+ case TEK_Scalar:
+ EmitScalarInit(EmitScalarExpr(E->getVal1()), LV);
+ return RValue::get(0);
+ case TEK_Complex:
+ EmitComplexExprIntoLValue(E->getVal1(), LV, /*isInit*/ true);
+ return RValue::get(0);
+ case TEK_Aggregate: {
+ AggValueSlot Slot = AggValueSlot::forLValue(LV,
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
EmitAggExpr(E->getVal1(), Slot);
+ return RValue::get(0);
}
- return RValue::get(0);
+ }
+ llvm_unreachable("bad evaluation kind");
}
Order = EmitScalarExpr(E->getOrder());
@@ -3485,7 +3510,7 @@
return Res;
if (E->getType()->isVoidType())
return RValue::get(0);
- return ConvertTempToRValue(*this, E->getType(), Dest);
+ return convertTempToRValue(Dest, E->getType());
}
bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
@@ -3540,7 +3565,7 @@
}
if (E->getType()->isVoidType())
return RValue::get(0);
- return ConvertTempToRValue(*this, E->getType(), OrigDest);
+ return convertTempToRValue(OrigDest, E->getType());
}
// Long case, when Order isn't obviously constant.
@@ -3602,7 +3627,7 @@
Builder.SetInsertPoint(ContBB);
if (E->getType()->isVoidType())
return RValue::get(0);
- return ConvertTempToRValue(*this, E->getType(), OrigDest);
+ return convertTempToRValue(OrigDest, E->getType());
}
void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, float Accuracy) {
@@ -3646,8 +3671,7 @@
typedef CodeGenFunction::OpaqueValueMappingData OVMA;
OVMA opaqueData;
if (ov == resultExpr && ov->isRValue() && !forLValue &&
- CodeGenFunction::hasAggregateLLVMType(ov->getType()) &&
- !ov->getType()->isAnyComplexType()) {
+ CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) {
CGF.EmitAggExpr(ov->getSourceExpr(), slot);
LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType());
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index f9f2733..f8921db 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -935,24 +935,34 @@
// FIXME: Are initializers affected by volatile?
if (Dest.isZeroed() && isSimpleZero(E, CGF)) {
// Storing "i32 0" to a zero'd memory location is a noop.
+ return;
} else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) {
- EmitNullInitializationToLValue(LV);
+ return EmitNullInitializationToLValue(LV);
} else if (type->isReferenceType()) {
RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
- CGF.EmitStoreThroughLValue(RV, LV);
- } else if (type->isAnyComplexType()) {
- CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
- } else if (CGF.hasAggregateLLVMType(type)) {
+ return CGF.EmitStoreThroughLValue(RV, LV);
+ }
+
+ switch (CGF.getEvaluationKind(type)) {
+ case TEK_Complex:
+ CGF.EmitComplexExprIntoLValue(E, LV, /*isInit*/ true);
+ return;
+ case TEK_Aggregate:
CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV,
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased,
Dest.isZeroed()));
- } else if (LV.isSimple()) {
- CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false);
- } else {
- CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV);
+ return;
+ case TEK_Scalar:
+ if (LV.isSimple()) {
+ CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false);
+ } else {
+ CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV);
+ }
+ return;
}
+ llvm_unreachable("bad evaluation kind");
}
void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) {
@@ -963,7 +973,7 @@
if (Dest.isZeroed() && CGF.getTypes().isZeroInitializable(type))
return;
- if (!CGF.hasAggregateLLVMType(type)) {
+ if (CGF.hasScalarEvaluationKind(type)) {
// For non-aggregates, we can store the appropriate null constant.
llvm::Value *null = CGF.CGM.EmitNullConstant(type);
// Note that the following is not equivalent to
@@ -1254,7 +1264,7 @@
/// the value of the aggregate expression is not needed. If VolatileDest is
/// true, DestPtr cannot be 0.
void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
- assert(E && hasAggregateLLVMType(E->getType()) &&
+ assert(E && hasAggregateEvaluationKind(E->getType()) &&
"Invalid aggregate expression to emit");
assert((Slot.getAddr() != 0 || Slot.isIgnored()) &&
"slot has bits but no address");
@@ -1266,7 +1276,7 @@
}
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
- assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!");
+ assert(hasAggregateEvaluationKind(E->getType()) && "Invalid argument!");
llvm::Value *Temp = CreateMemTemp(E->getType());
LValue LV = MakeAddrLValue(Temp, E->getType());
EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed,
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 7ad497b..13ae8bb 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -820,14 +820,18 @@
QualType AllocType, llvm::Value *NewPtr) {
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
- if (!CGF.hasAggregateLLVMType(AllocType))
+ switch (CGF.getEvaluationKind(AllocType)) {
+ case TEK_Scalar:
CGF.EmitScalarInit(Init, 0, CGF.MakeAddrLValue(NewPtr, AllocType,
Alignment),
false);
- else if (AllocType->isAnyComplexType())
- CGF.EmitComplexExprIntoAddr(Init, NewPtr,
- AllocType.isVolatileQualified());
- else {
+ return;
+ case TEK_Complex:
+ CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType,
+ Alignment),
+ /*isInit*/ true);
+ return;
+ case TEK_Aggregate: {
AggValueSlot Slot
= AggValueSlot::forAddr(NewPtr, Alignment, AllocType.getQualifiers(),
AggValueSlot::IsDestructed,
@@ -836,7 +840,10 @@
CGF.EmitAggExpr(Init, Slot);
CGF.MaybeEmitStdInitializerListCleanup(NewPtr, Init);
+ return;
}
+ }
+ llvm_unreachable("bad evaluation kind");
}
void
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 0a53d4f..840463b 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -27,6 +27,16 @@
typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
+/// Return the complex type that we are meant to emit.
+static const ComplexType *getComplexType(QualType type) {
+ type = type.getCanonicalType();
+ if (const ComplexType *comp = dyn_cast<ComplexType>(type)) {
+ return comp;
+ } else {
+ return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
+ }
+}
+
namespace {
class ComplexExprEmitter
: public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
@@ -63,25 +73,11 @@
return EmitLoadOfLValue(CGF.EmitLValue(E));
}
- ComplexPairTy EmitLoadOfLValue(LValue LV) {
- assert(LV.isSimple() && "complex l-value must be simple");
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
- }
-
- /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load
- /// the real and imaginary pieces.
- ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile);
-
- /// EmitStoreThroughLValue - Given an l-value of complex type, store
- /// a complex number into it.
- void EmitStoreThroughLValue(ComplexPairTy Val, LValue LV) {
- assert(LV.isSimple() && "complex l-value must be simple");
- return EmitStoreOfComplex(Val, LV.getAddress(), LV.isVolatileQualified());
- }
+ ComplexPairTy EmitLoadOfLValue(LValue LV);
/// EmitStoreOfComplex - Store the specified real/imag parts into the
/// specified value pointer.
- void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol);
+ void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit);
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
@@ -194,13 +190,13 @@
}
ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
assert(E->getType()->isAnyComplexType() && "Expected complex type!");
- QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem));
return ComplexPairTy(Null, Null);
}
ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
assert(E->getType()->isAnyComplexType() && "Expected complex type!");
- QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
llvm::Constant *Null =
llvm::Constant::getNullValue(CGF.ConvertType(Elem));
return ComplexPairTy(Null, Null);
@@ -286,10 +282,13 @@
// Utilities
//===----------------------------------------------------------------------===//
-/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
+/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
/// load the real and imaginary pieces, returning them as Real/Imag.
-ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
- bool isVolatile) {
+ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue) {
+ assert(lvalue.isSimple() && "non-simple complex l-value?");
+ llvm::Value *SrcPtr = lvalue.getAddress();
+ bool isVolatile = lvalue.isVolatileQualified();
+
llvm::Value *Real=0, *Imag=0;
if (!IgnoreReal || isVolatile) {
@@ -308,13 +307,16 @@
/// EmitStoreOfComplex - Store the specified real/imag parts into the
/// specified value pointer.
-void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr,
- bool isVolatile) {
+void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val,
+ LValue lvalue,
+ bool isInit) {
+ llvm::Value *Ptr = lvalue.getAddress();
llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
- Builder.CreateStore(Val.first, RealPtr, isVolatile);
- Builder.CreateStore(Val.second, ImagPtr, isVolatile);
+ // TODO: alignment
+ Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+ Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
}
@@ -326,7 +328,7 @@
ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
CGF.ErrorUnsupported(E, "complex expression");
llvm::Type *EltTy =
- CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
+ CGF.ConvertType(getComplexType(E->getType())->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return ComplexPairTy(U, U);
}
@@ -355,8 +357,8 @@
QualType SrcType,
QualType DestType) {
// Get the src/dest element type.
- SrcType = SrcType->getAs<ComplexType>()->getElementType();
- DestType = DestType->getAs<ComplexType>()->getElementType();
+ SrcType = SrcType->castAs<ComplexType>()->getElementType();
+ DestType = DestType->castAs<ComplexType>()->getElementType();
// C99 6.3.1.6: When a value of complex type is converted to another
// complex type, both the real and imaginary parts follow the conversion
@@ -381,11 +383,12 @@
return Visit(Op);
case CK_LValueBitCast: {
- llvm::Value *V = CGF.EmitLValue(Op).getAddress();
+ LValue origLV = CGF.EmitLValue(Op);
+ llvm::Value *V = origLV.getAddress();
V = Builder.CreateBitCast(V,
CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
- // FIXME: Are the qualifiers correct here?
- return EmitLoadOfComplex(V, DestTy.isVolatileQualified());
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy,
+ origLV.getAlignment()));
}
case CK_BitCast:
@@ -436,7 +439,7 @@
llvm::Value *Elt = CGF.EmitScalarExpr(Op);
// Convert the input element to the element type of the complex.
- DestTy = DestTy->getAs<ComplexType>()->getElementType();
+ DestTy = DestTy->castAs<ComplexType>()->getElementType();
Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
// Return (realval, 0).
@@ -569,7 +572,7 @@
llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
- if (Op.Ty->getAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
+ if (Op.Ty->castAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
DSTr = Builder.CreateUDiv(Tmp3, Tmp6);
DSTi = Builder.CreateUDiv(Tmp9, Tmp6);
} else {
@@ -629,7 +632,7 @@
Val = Result;
// Store the result value into the LHS lvalue.
- EmitStoreThroughLValue(Result, LHS);
+ EmitStoreOfComplex(Result, LHS, /*isInit*/ false);
return LHS;
}
@@ -649,7 +652,7 @@
if (!LV.isVolatileQualified())
return Val;
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+ return EmitLoadOfLValue(LV);
}
LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
@@ -667,7 +670,7 @@
LValue LHS = CGF.EmitLValue(E->getLHS());
// Store the result value into the LHS lvalue.
- EmitStoreThroughLValue(Val, LHS);
+ EmitStoreOfComplex(Val, LHS, /*isInit*/ false);
return LHS;
}
@@ -684,7 +687,7 @@
if (!LV.isVolatileQualified())
return Val;
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+ return EmitLoadOfLValue(LV);
}
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -755,7 +758,7 @@
// Empty init list intializes to null
assert(E->getNumInits() == 0 && "Unexpected number of inits");
- QualType Ty = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType Ty = E->getType()->castAs<ComplexType>()->getElementType();
llvm::Type* LTy = CGF.ConvertType(Ty);
llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
return ComplexPairTy(zeroConstant, zeroConstant);
@@ -768,13 +771,13 @@
if (!ArgPtr) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
llvm::Type *EltTy =
- CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
+ CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return ComplexPairTy(U, U);
}
- // FIXME Volatility.
- return EmitLoadOfComplex(ArgPtr, false);
+ return EmitLoadOfLValue(
+ CGF.MakeNaturalAlignAddrLValue(ArgPtr, E->getType()));
}
//===----------------------------------------------------------------------===//
@@ -785,36 +788,31 @@
/// complex type, ignoring the result.
ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
bool IgnoreImag) {
- assert(E && E->getType()->isAnyComplexType() &&
+ assert(E && getComplexType(E->getType()) &&
"Invalid complex expression to emit");
return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
.Visit(const_cast<Expr*>(E));
}
-/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
-/// of complex type, storing into the specified Value*.
-void CodeGenFunction::EmitComplexExprIntoAddr(const Expr *E,
- llvm::Value *DestAddr,
- bool DestIsVolatile) {
- assert(E && E->getType()->isAnyComplexType() &&
+void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
+ bool isInit) {
+ assert(E && getComplexType(E->getType()) &&
"Invalid complex expression to emit");
ComplexExprEmitter Emitter(*this);
ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
- Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
+ Emitter.EmitStoreOfComplex(Val, dest, isInit);
}
-/// StoreComplexToAddr - Store a complex number into the specified address.
-void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
- llvm::Value *DestAddr,
- bool DestIsVolatile) {
- ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
+/// EmitStoreOfComplex - Store a complex number into the specified l-value.
+void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest,
+ bool isInit) {
+ ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit);
}
-/// LoadComplexFromAddr - Load a complex number from the specified address.
-ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr,
- bool SrcIsVolatile) {
- return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile);
+/// EmitLoadOfComplex - Load a complex number from the specified address.
+ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src) {
+ return ComplexExprEmitter(*this).EmitLoadOfLValue(src);
}
LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 7df4818..56b150a 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -775,7 +775,7 @@
EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
QualType SrcTy, QualType DstTy) {
// Get the source element type.
- SrcTy = SrcTy->getAs<ComplexType>()->getElementType();
+ SrcTy = SrcTy->castAs<ComplexType>()->getElementType();
// Handle conversions to bool first, they are special: comparisons against 0.
if (DstTy->isBooleanType()) {
@@ -3160,7 +3160,7 @@
/// EmitScalarExpr - Emit the computation of the specified expression of scalar
/// type, ignoring the result.
Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
- assert(E && !hasAggregateLLVMType(E->getType()) &&
+ assert(E && hasScalarEvaluationKind(E->getType()) &&
"Invalid scalar expression to emit");
if (isa<CXXDefaultArgExpr>(E))
@@ -3176,7 +3176,7 @@
/// specified destination type, both of which are LLVM scalar types.
Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy,
QualType DstTy) {
- assert(!hasAggregateLLVMType(SrcTy) && !hasAggregateLLVMType(DstTy) &&
+ assert(hasScalarEvaluationKind(SrcTy) && hasScalarEvaluationKind(DstTy) &&
"Invalid scalar expression to emit");
return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy);
}
@@ -3187,7 +3187,7 @@
Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src,
QualType SrcTy,
QualType DstTy) {
- assert(SrcTy->isAnyComplexType() && !hasAggregateLLVMType(DstTy) &&
+ assert(SrcTy->isAnyComplexType() && hasScalarEvaluationKind(DstTy) &&
"Invalid complex -> scalar conversion");
return ScalarExprEmitter(*this).EmitComplexToScalarConversion(Src, SrcTy,
DstTy);
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 235b0da..ad7d629 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -895,16 +895,21 @@
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0);
QualType ivarType = ivar->getType();
- if (ivarType->isAnyComplexType()) {
- ComplexPairTy pair = LoadComplexFromAddr(LV.getAddress(),
- LV.isVolatileQualified());
- StoreComplexToAddr(pair, ReturnValue, LV.isVolatileQualified());
- } else if (hasAggregateLLVMType(ivarType)) {
+ switch (getEvaluationKind(ivarType)) {
+ case TEK_Complex: {
+ ComplexPairTy pair = EmitLoadOfComplex(LV);
+ EmitStoreOfComplex(pair,
+ MakeNaturalAlignAddrLValue(ReturnValue, ivarType),
+ /*init*/ true);
+ return;
+ }
+ case TEK_Aggregate:
// The return value slot is guaranteed to not be aliased, but
// that's not necessarily the same as "on the stack", so
// we still potentially need objc_memmove_collectable.
EmitAggregateCopy(ReturnValue, LV.getAddress(), ivarType);
- } else {
+ return;
+ case TEK_Scalar: {
llvm::Value *value;
if (propType->isReferenceType()) {
value = LV.getAddress();
@@ -926,8 +931,10 @@
}
EmitReturnOfRValue(RValue::get(value), propType);
+ return;
}
- return;
+ }
+ llvm_unreachable("bad evaluation kind");
}
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 842eaf1..9e7ddfb 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -741,7 +741,9 @@
} else if (RV.isAggregate()) {
EmitAggregateCopy(ReturnValue, RV.getAggregateAddr(), Ty);
} else {
- StoreComplexToAddr(RV.getComplexVal(), ReturnValue, false);
+ EmitStoreOfComplex(RV.getComplexVal(),
+ MakeNaturalAlignAddrLValue(ReturnValue, Ty),
+ /*init*/ true);
}
EmitBranchThroughCleanup(ReturnBlock);
}
@@ -788,16 +790,26 @@
// rather than the value.
RValue Result = EmitReferenceBindingToExpr(RV, /*InitializedDecl=*/0);
Builder.CreateStore(Result.getScalarVal(), ReturnValue);
- } else if (!hasAggregateLLVMType(RV->getType())) {
- Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
- } else if (RV->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(RV, ReturnValue, false);
} else {
- CharUnits Alignment = getContext().getTypeAlignInChars(RV->getType());
- EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Alignment, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ switch (getEvaluationKind(RV->getType())) {
+ case TEK_Scalar:
+ Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
+ break;
+ case TEK_Complex:
+ EmitComplexExprIntoLValue(RV,
+ MakeNaturalAlignAddrLValue(ReturnValue, RV->getType()),
+ /*isInit*/ true);
+ break;
+ case TEK_Aggregate: {
+ CharUnits Alignment = getContext().getTypeAlignInChars(RV->getType());
+ EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Alignment,
+ Qualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased));
+ break;
+ }
+ }
}
cleanupScope.ForceCleanup();
@@ -1355,7 +1367,7 @@
std::string &ConstraintStr) {
llvm::Value *Arg;
if (Info.allowsRegister() || !Info.allowsMemory()) {
- if (!CodeGenFunction::hasAggregateLLVMType(InputType)) {
+ if (CodeGenFunction::hasScalarEvaluationKind(InputType)) {
Arg = EmitLoadOfLValue(InputValue).getScalarVal();
} else {
llvm::Type *Ty = ConvertType(InputType);
@@ -1384,7 +1396,7 @@
const Expr *InputExpr,
std::string &ConstraintStr) {
if (Info.allowsRegister() || !Info.allowsMemory())
- if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType()))
+ if (CodeGenFunction::hasScalarEvaluationKind(InputExpr->getType()))
return EmitScalarExpr(InputExpr);
InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
@@ -1479,7 +1491,7 @@
// If this is a register output, then make the inline asm return it
// by-value. If this is a memory result, return the value by-reference.
- if (!Info.allowsMemory() && !hasAggregateLLVMType(OutExpr->getType())) {
+ if (!Info.allowsMemory() && hasScalarEvaluationKind(OutExpr->getType())) {
Constraints += "=" + OutputConstraint;
ResultRegQualTys.push_back(OutExpr->getType());
ResultRegDests.push_back(Dest);
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index b7ddc97..069cd5f 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -361,7 +361,7 @@
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- hasAggregateLLVMType(CurFnInfo->getReturnType()))
+ !hasScalarEvaluationKind(CurFnInfo->getReturnType()))
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
// Now emit our call.
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 01dee1f..0bbd373 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -18,11 +18,11 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
-#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Value.h"
namespace llvm {
class Constant;
- class Value;
+ class MDNode;
}
namespace clang {
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 973ee88..5e8bce9 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -77,45 +77,53 @@
return CGM.getTypes().ConvertType(T);
}
-bool CodeGenFunction::hasAggregateLLVMType(QualType type) {
- switch (type.getCanonicalType()->getTypeClass()) {
+TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
+ type = type.getCanonicalType();
+ while (true) {
+ switch (type->getTypeClass()) {
#define TYPE(name, parent)
#define ABSTRACT_TYPE(name, parent)
#define NON_CANONICAL_TYPE(name, parent) case Type::name:
#define DEPENDENT_TYPE(name, parent) case Type::name:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
#include "clang/AST/TypeNodes.def"
- llvm_unreachable("non-canonical or dependent type in IR-generation");
+ llvm_unreachable("non-canonical or dependent type in IR-generation");
- case Type::Builtin:
- case Type::Pointer:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- case Type::Enum:
- case Type::ObjCObjectPointer:
- return false;
+ // Various scalar types.
+ case Type::Builtin:
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Enum:
+ case Type::ObjCObjectPointer:
+ return TEK_Scalar;
- // Complexes, arrays, records, and Objective-C objects.
- case Type::Complex:
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::Record:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- return true;
+ // Complexes.
+ case Type::Complex:
+ return TEK_Complex;
- // In IRGen, atomic types are just the underlying type
- case Type::Atomic:
- return hasAggregateLLVMType(type->getAs<AtomicType>()->getValueType());
+ // Arrays, records, and Objective-C objects.
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::Record:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ return TEK_Aggregate;
+
+ // We operate on atomic values according to their underlying type.
+ case Type::Atomic:
+ type = cast<AtomicType>(type)->getValueType();
+ continue;
+ }
+ llvm_unreachable("unknown type kind!");
}
- llvm_unreachable("unknown type kind!");
}
void CodeGenFunction::EmitReturnBlock() {
@@ -422,7 +430,7 @@
// Void type; nothing to return.
ReturnValue = 0;
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- hasAggregateLLVMType(CurFnInfo->getReturnType())) {
+ !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Indirect aggregate return; emit returned value directly into sret slot.
// This reduces code size, and affects correctness in C++.
ReturnValue = CurFn->arg_begin();
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index cd738f0..4e6c72e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -78,6 +78,17 @@
class BlockFlags;
class BlockFieldFlags;
+/// The kind of evaluation to perform on values of a particular
+/// type. Basically, is the code in CGExprScalar, CGExprComplex, or
+/// CGExprAgg?
+///
+/// TODO: should vectors maybe be split out into their own thing?
+enum TypeEvaluationKind {
+ TEK_Scalar,
+ TEK_Complex,
+ TEK_Aggregate
+};
+
/// A branch fixup. These are required when emitting a goto to a
/// label which hasn't been emitted yet. The goto is optimistically
/// emitted as a branch to the basic block for the label, and (if it
@@ -1515,7 +1526,15 @@
/// hasAggregateLLVMType - Return true if the specified AST type will map into
/// an aggregate LLVM type or is void.
- static bool hasAggregateLLVMType(QualType T);
+ static TypeEvaluationKind getEvaluationKind(QualType T);
+
+ static bool hasScalarEvaluationKind(QualType T) {
+ return getEvaluationKind(T) == TEK_Scalar;
+ }
+
+ static bool hasAggregateEvaluationKind(QualType T) {
+ return getEvaluationKind(T) == TEK_Aggregate;
+ }
/// createBasicBlock - Create an LLVM basic block.
llvm::BasicBlock *createBasicBlock(const Twine &name = "",
@@ -2128,6 +2147,8 @@
/// that the address will be used to access the object.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK);
+ RValue convertTempToRValue(llvm::Value *addr, QualType type);
+
/// EmitToMemory - Change a scalar value from its value
/// representation to its in-memory representation.
llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty);
@@ -2504,16 +2525,15 @@
bool IgnoreReal = false,
bool IgnoreImag = false);
- /// EmitComplexExprIntoAddr - Emit the computation of the specified expression
- /// of complex type, storing into the specified Value*.
- void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
- bool DestIsVolatile);
+ /// EmitComplexExprIntoLValue - Emit the given expression of complex
+ /// type and place its result into the specified l-value.
+ void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit);
- /// StoreComplexToAddr - Store a complex number into the specified address.
- void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
- bool DestIsVolatile);
- /// LoadComplexFromAddr - Load a complex number from the specified address.
- ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
+ /// EmitStoreOfComplex - Store a complex number into the specified l-value.
+ void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit);
+
+ /// EmitLoadOfComplex - Load a complex number from the specified l-value.
+ ComplexPairTy EmitLoadOfComplex(LValue src);
/// CreateStaticVarDecl - Create a zero-initialized LLVM global for
/// a static local variable.
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 77f4fb4..81267ca 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -37,7 +37,7 @@
}
static bool isAggregateTypeForABI(QualType T) {
- return CodeGenFunction::hasAggregateLLVMType(T) ||
+ return !CodeGenFunction::hasScalarEvaluationKind(T) ||
T->isMemberFunctionPointerType();
}