summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGException.cpp3
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp81
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp19
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp31
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp85
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp27
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h133
7 files changed, 237 insertions, 142 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 7f3bbb78986..0e717e26ab3 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1052,7 +1052,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
// The copy expression is defined in terms of an OpaqueValueExpr.
// Find it and map it to the adjusted expression.
CodeGenFunction::OpaqueValueMapping
- opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), adjustedExn);
+ opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+ CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
// Call the copy ctor in a terminate scope.
CGF.EHStack.pushTerminate();
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 56a9107a82c..27316526b16 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -581,6 +581,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E));
case Expr::ConditionalOperatorClass:
return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
+ case Expr::BinaryConditionalOperatorClass:
+ return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
case Expr::ChooseExprClass:
return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
case Expr::OpaqueValueExprClass:
@@ -1675,68 +1677,64 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
return Result;
}
-LValue
-CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator *E) {
- if (!E->isGLValue()) {
+LValue CodeGenFunction::
+EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
+ if (!expr->isGLValue()) {
// ?: here should be an aggregate.
- assert((hasAggregateLLVMType(E->getType()) &&
- !E->getType()->isAnyComplexType()) &&
+ assert((hasAggregateLLVMType(expr->getType()) &&
+ !expr->getType()->isAnyComplexType()) &&
"Unexpected conditional operator!");
- return EmitAggExprToLValue(E);
+ return EmitAggExprToLValue(expr);
}
- if (int Cond = ConstantFoldsToSimpleInteger(E->getCond())) {
- Expr *Live = Cond == 1 ? E->getLHS() : E->getRHS();
- if (Live)
- return EmitLValue(Live);
+ const Expr *condExpr = expr->getCond();
+
+ if (int condValue = ConstantFoldsToSimpleInteger(condExpr)) {
+ const Expr *live = expr->getTrueExpr(), *dead = expr->getFalseExpr();
+ if (condValue == -1) std::swap(live, dead);
+
+ if (!ContainsLabel(dead))
+ return EmitLValue(live);
}
- llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
- llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
- llvm::BasicBlock *ContBlock = createBasicBlock("cond.end");
+ OpaqueValueMapping binding(*this, expr);
+
+ llvm::BasicBlock *lhsBlock = createBasicBlock("cond.true");
+ llvm::BasicBlock *rhsBlock = createBasicBlock("cond.false");
+ llvm::BasicBlock *contBlock = createBasicBlock("cond.end");
ConditionalEvaluation eval(*this);
-
- if (E->getLHS())
- EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- else {
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentianlly not doing direct assignment to ConditionalSaveExprs[save]
- LValue SaveVal = EmitLValue(save);
- ConditionalSaveLValueExprs[save] = SaveVal;
- EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- }
+ EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock);
// Any temporaries created here are conditional.
- EmitBlock(LHSBlock);
+ EmitBlock(lhsBlock);
eval.begin(*this);
- LValue LHS = EmitLValue(E->getTrueExpr());
+ LValue lhs = EmitLValue(expr->getTrueExpr());
eval.end(*this);
- if (!LHS.isSimple())
- return EmitUnsupportedLValue(E, "conditional operator");
+ if (!lhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
- LHSBlock = Builder.GetInsertBlock();
- Builder.CreateBr(ContBlock);
+ lhsBlock = Builder.GetInsertBlock();
+ Builder.CreateBr(contBlock);
// Any temporaries created here are conditional.
- EmitBlock(RHSBlock);
+ EmitBlock(rhsBlock);
eval.begin(*this);
- LValue RHS = EmitLValue(E->getRHS());
+ LValue rhs = EmitLValue(expr->getFalseExpr());
eval.end(*this);
- if (!RHS.isSimple())
- return EmitUnsupportedLValue(E, "conditional operator");
- RHSBlock = Builder.GetInsertBlock();
+ if (!rhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
+ rhsBlock = Builder.GetInsertBlock();
- EmitBlock(ContBlock);
+ EmitBlock(contBlock);
- llvm::PHINode *phi = Builder.CreatePHI(LHS.getAddress()->getType(),
+ llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(),
"cond-lvalue");
phi->reserveOperandSpace(2);
- phi->addIncoming(LHS.getAddress(), LHSBlock);
- phi->addIncoming(RHS.getAddress(), RHSBlock);
- return MakeAddrLValue(phi, E->getType());
+ phi->addIncoming(lhs.getAddress(), lhsBlock);
+ phi->addIncoming(rhs.getAddress(), rhsBlock);
+ return MakeAddrLValue(phi, expr->getType());
}
/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
@@ -1892,8 +1890,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue(
LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
assert(e->isGLValue() || e->getType()->isRecordType());
- llvm::Value *value = getOpaqueValueMapping(e);
- return MakeAddrLValue(value, e->getType());
+ return getOpaqueLValueMapping(e);
}
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 0b3a617be15..f992dc7c9cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -116,7 +116,7 @@ public:
}
void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
- void VisitConditionalOperator(const ConditionalOperator *CO);
+ void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
void VisitChooseExpr(const ChooseExpr *CE);
void VisitInitListExpr(InitListExpr *E);
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
@@ -245,7 +245,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
//===----------------------------------------------------------------------===//
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
- EmitFinalDestCopy(e, CGF.EmitOpaqueValueLValue(e));
+ EmitFinalDestCopy(e, CGF.getOpaqueLValueMapping(e));
}
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
@@ -419,16 +419,15 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
}
-void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
- if (!E->getLHS()) {
- CGF.ErrorUnsupported(E, "conditional operator with missing LHS");
- return;
- }
-
+void AggExprEmitter::
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
CodeGenFunction::ConditionalEvaluation eval(CGF);
CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
@@ -437,7 +436,7 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
- Visit(E->getLHS());
+ Visit(E->getTrueExpr());
eval.end(CGF);
assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!");
@@ -451,7 +450,7 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
- Visit(E->getRHS());
+ Visit(E->getFalseExpr());
eval.end(CGF);
CGF.EmitBlock(ContBlock);
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 15901eb99a8..8b4ead8b111 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -130,12 +130,9 @@ public:
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- if (E->isGLValue()) return EmitLoadOfLValue(E);
-
- // Otherwise, the mapping is... what, exactly? Probably a
- // first-class aggregate, but it's really just not worthwhile.
- CGF.ErrorUnsupported(E, "complex opaque r-value");
- return ComplexPairTy();
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
+ return CGF.getOpaqueRValueMapping(E).getComplexVal();
}
// FIXME: CompoundLiteralExpr
@@ -260,7 +257,8 @@ public:
ComplexPairTy VisitBinComma (const BinaryOperator *E);
- ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO);
+ ComplexPairTy
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
ComplexPairTy VisitInitListExpr(InitListExpr *E);
@@ -647,25 +645,18 @@ ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
}
ComplexPairTy ComplexExprEmitter::
-VisitConditionalOperator(const ConditionalOperator *E) {
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
- CodeGenFunction::ConditionalEvaluation eval(CGF);
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- if (E->getLHS())
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- else {
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentionally not doing direct assignment to ConditionalSaveExprs[save] !!
- ComplexPairTy SaveVal = Visit(save);
- CGF.ConditionalSaveComplexExprs[save] = SaveVal;
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- }
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
@@ -676,7 +667,7 @@ VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
- ComplexPairTy RHS = Visit(E->getRHS());
+ ComplexPairTy RHS = Visit(E->getFalseExpr());
RHSBlock = Builder.GetInsertBlock();
CGF.EmitBlock(ContBlock);
eval.end(CGF);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 99f3f0d3231..34e247d7c3f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -201,10 +201,11 @@ public:
}
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- if (E->isGLValue()) return EmitLoadOfLValue(E);
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getType());
// Otherwise, assume the mapping is the scalar directly.
- return CGF.getOpaqueValueMapping(E);
+ return CGF.getOpaqueRValueMapping(E).getScalarVal();
}
// l-values.
@@ -496,7 +497,7 @@ public:
// Other Operators.
Value *VisitBlockExpr(const BlockExpr *BE);
- Value *VisitConditionalOperator(const ConditionalOperator *CO);
+ Value *VisitAbstractConditionalOperator(const AbstractConditionalOperator *);
Value *VisitChooseExpr(ChooseExpr *CE);
Value *VisitVAArgExpr(VAArgExpr *VE);
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
@@ -2401,32 +2402,38 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
Value *ScalarExprEmitter::
-VisitConditionalOperator(const ConditionalOperator *E) {
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
TestAndClearIgnoreResultAssign();
+
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
+ Expr *condExpr = E->getCond();
+ Expr *lhsExpr = E->getTrueExpr();
+ Expr *rhsExpr = E->getFalseExpr();
+
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm.
- if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getCond())){
- Expr *Live = E->getLHS(), *Dead = E->getRHS();
- if (Cond == -1)
- std::swap(Live, Dead);
+ if (int Cond = CGF.ConstantFoldsToSimpleInteger(condExpr)){
+ Expr *live = lhsExpr, *dead = rhsExpr;
+ if (Cond == -1) std::swap(live, dead);
// If the dead side doesn't have labels we need, and if the Live side isn't
// the gnu missing ?: extension (which we could handle, but don't bother
// to), just emit the Live part.
- if ((!Dead || !CGF.ContainsLabel(Dead)) && // No labels in dead part
- Live) // Live part isn't missing.
- return Visit(Live);
+ if (!CGF.ContainsLabel(dead))
+ return Visit(live);
}
// OpenCL: If the condition is a vector, we can treat this condition like
// the select function.
if (CGF.getContext().getLangOptions().OpenCL
- && E->getCond()->getType()->isVectorType()) {
- llvm::Value *CondV = CGF.EmitScalarExpr(E->getCond());
- llvm::Value *LHS = Visit(E->getLHS());
- llvm::Value *RHS = Visit(E->getRHS());
+ && condExpr->getType()->isVectorType()) {
+ llvm::Value *CondV = CGF.EmitScalarExpr(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
- const llvm::Type *condType = ConvertType(E->getCond()->getType());
+ const llvm::Type *condType = ConvertType(condExpr->getType());
const llvm::VectorType *vecTy = cast<llvm::VectorType>(condType);
unsigned numElem = vecTy->getNumElements();
@@ -2467,12 +2474,11 @@ VisitConditionalOperator(const ConditionalOperator *E) {
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
- if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS(),
- CGF) &&
- isCheapEnoughToEvaluateUnconditionally(E->getRHS(), CGF)) {
- llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
- llvm::Value *LHS = Visit(E->getLHS());
- llvm::Value *RHS = Visit(E->getRHS());
+ if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) {
+ llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
return Builder.CreateSelect(CondV, LHS, RHS, "cond");
}
@@ -2481,40 +2487,11 @@ VisitConditionalOperator(const ConditionalOperator *E) {
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
CodeGenFunction::ConditionalEvaluation eval(CGF);
-
- // If we don't have the GNU missing condition extension, emit a branch on bool
- // the normal way.
- if (E->getLHS()) {
- // Otherwise, just use EmitBranchOnBoolExpr to get small and simple code for
- // the branch on bool.
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- } else {
- // Otherwise, for the ?: extension, evaluate the conditional and then
- // convert it to bool the hard way. We do this explicitly because we need
- // the unconverted value for the missing middle value of the ?:.
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentianlly not doing direct assignment to ConditionalSaveExprs[save] !!
- Value *SaveVal = CGF.EmitScalarExpr(save);
- CGF.ConditionalSaveExprs[save] = SaveVal;
- Value *CondVal = Visit(E->getCond());
- // In some cases, EmitScalarConversion will delete the "CondVal" expression
- // if there are no extra uses (an optimization). Inhibit this by making an
- // extra dead use, because we're going to add a use of CondVal later. We
- // don't use the builder for this, because we don't want it to get optimized
- // away. This leaves dead code, but the ?: extension isn't common.
- new llvm::BitCastInst(CondVal, CondVal->getType(), "dummy?:holder",
- Builder.GetInsertBlock());
-
- Value *CondBoolVal =
- CGF.EmitScalarConversion(CondVal, E->getCond()->getType(),
- CGF.getContext().BoolTy);
- Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
- }
+ CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock);
CGF.EmitBlock(LHSBlock);
eval.begin(CGF);
- Value *LHS = Visit(E->getTrueExpr());
+ Value *LHS = Visit(lhsExpr);
eval.end(CGF);
LHSBlock = Builder.GetInsertBlock();
@@ -2522,7 +2499,7 @@ VisitConditionalOperator(const ConditionalOperator *E) {
CGF.EmitBlock(RHSBlock);
eval.begin(CGF);
- Value *RHS = Visit(E->getRHS());
+ Value *RHS = Visit(rhsExpr);
eval.end(CGF);
RHSBlock = Builder.GetInsertBlock();
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b316fa86f1e..96716ad9ccf 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -762,3 +762,30 @@ void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
if (CGDebugInfo *Dbg = getDebugInfo())
Dbg->EmitGlobalVariable(E->getDecl(), Init);
}
+
+CodeGenFunction::PeepholeProtection
+CodeGenFunction::protectFromPeepholes(RValue rvalue) {
+ // At the moment, the only aggressive peephole we do in IR gen
+ // is trunc(zext) folding, but if we add more, we can easily
+ // extend this protection.
+
+ if (!rvalue.isScalar()) return PeepholeProtection();
+ llvm::Value *value = rvalue.getScalarVal();
+ if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();
+
+ // Just make an extra bitcast.
+ assert(HaveInsertPoint());
+ llvm::Instruction *inst = new llvm::BitCastInst(value, value->getType(), "",
+ Builder.GetInsertBlock());
+
+ PeepholeProtection protection;
+ protection.Inst = inst;
+ return protection;
+}
+
+void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
+ if (!protection.Inst) return;
+
+ // In theory, we could try to duplicate the peepholes now, but whatever.
+ protection.Inst->eraseFromParent();
+}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index adbc223afc6..d35a400f7de 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -840,28 +840,105 @@ public:
}
};
+ /// An object which temporarily prevents a value from being
+ /// destroyed by aggressive peephole optimizations that assume that
+ /// all uses of a value have been realized in the IR.
+ class PeepholeProtection {
+ llvm::Instruction *Inst;
+ friend class CodeGenFunction;
+
+ public:
+ PeepholeProtection() : Inst(0) {}
+ };
+
/// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
class OpaqueValueMapping {
CodeGenFunction &CGF;
const OpaqueValueExpr *OpaqueValue;
+ bool BoundLValue;
+ CodeGenFunction::PeepholeProtection Protection;
public:
+ static bool shouldBindAsLValue(const Expr *expr) {
+ return expr->isGLValue() || expr->getType()->isRecordType();
+ }
+
+ /// Build the opaque value mapping for the given conditional
+ /// operator if it's the GNU ?: extension. This is a common
+ /// enough pattern that the convenience operator is really
+ /// helpful.
+ ///
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const AbstractConditionalOperator *op) : CGF(CGF) {
+ if (isa<ConditionalOperator>(op)) {
+ OpaqueValue = 0;
+ BoundLValue = false;
+ return;
+ }
+
+ const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op);
+ init(e->getOpaqueValue(), e->getCommon());
+ }
+
OpaqueValueMapping(CodeGenFunction &CGF,
const OpaqueValueExpr *opaqueValue,
- llvm::Value *value)
- : CGF(CGF), OpaqueValue(opaqueValue) {
+ LValue lvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) {
assert(opaqueValue && "no opaque value expression!");
- CGF.OpaqueValues.insert(std::make_pair(opaqueValue, value));
+ assert(shouldBindAsLValue(opaqueValue));
+ initLValue(lvalue);
+ }
+
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const OpaqueValueExpr *opaqueValue,
+ RValue rvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(false) {
+ assert(opaqueValue && "no opaque value expression!");
+ assert(!shouldBindAsLValue(opaqueValue));
+ initRValue(rvalue);
}
void pop() {
assert(OpaqueValue && "mapping already popped!");
- CGF.OpaqueValues.erase(OpaqueValue);
+ popImpl();
OpaqueValue = 0;
}
~OpaqueValueMapping() {
- if (OpaqueValue) CGF.OpaqueValues.erase(OpaqueValue);
+ if (OpaqueValue) popImpl();
+ }
+
+ private:
+ void popImpl() {
+ if (BoundLValue)
+ CGF.OpaqueLValues.erase(OpaqueValue);
+ else {
+ CGF.OpaqueRValues.erase(OpaqueValue);
+ CGF.unprotectFromPeepholes(Protection);
+ }
+ }
+
+ void init(const OpaqueValueExpr *ov, const Expr *e) {
+ OpaqueValue = ov;
+ BoundLValue = shouldBindAsLValue(ov);
+ assert(BoundLValue == shouldBindAsLValue(e)
+ && "inconsistent expression value kinds!");
+ if (BoundLValue)
+ initLValue(CGF.EmitLValue(e));
+ else
+ initRValue(CGF.EmitAnyExpr(e));
+ }
+
+ void initLValue(const LValue &lv) {
+ CGF.OpaqueLValues.insert(std::make_pair(OpaqueValue, lv));
+ }
+
+ void initRValue(const RValue &rv) {
+ // Work around an extremely aggressive peephole optimization in
+ // EmitScalarConversion which assumes that all other uses of a
+ // value are extant.
+ Protection = CGF.protectFromPeepholes(rv);
+ CGF.OpaqueRValues.insert(std::make_pair(OpaqueValue, rv));
}
};
@@ -909,9 +986,10 @@ private:
/// statement range in current switch instruction.
llvm::BasicBlock *CaseRangeBlock;
- /// OpaqueValues - Keeps track of the current set of opaque value
+ /// OpaqueLValues - Keeps track of the current set of opaque value
/// expressions.
- llvm::DenseMap<const OpaqueValueExpr *, llvm::Value*> OpaqueValues;
+ llvm::DenseMap<const OpaqueValueExpr *, LValue> OpaqueLValues;
+ llvm::DenseMap<const OpaqueValueExpr *, RValue> OpaqueRValues;
// VLASizeMap - This keeps track of the associated size for each VLA type.
// We track this by the size expression rather than the type itself because
@@ -1308,13 +1386,25 @@ public:
return Res;
}
- /// getOpaqueValueMapping - Given an opaque value expression (which
- /// must be mapped), return its mapping. Whether this is an address
- /// or a value depends on the expression's type and value kind.
- llvm::Value *getOpaqueValueMapping(const OpaqueValueExpr *e) {
- llvm::DenseMap<const OpaqueValueExpr*,llvm::Value*>::iterator
- it = OpaqueValues.find(e);
- assert(it != OpaqueValues.end() && "no mapping for opaque value!");
+ /// getOpaqueLValueMapping - Given an opaque value expression (which
+ /// must be mapped to an l-value), return its mapping.
+ const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+ assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
+ return it->second;
+ }
+
+ /// getOpaqueRValueMapping - Given an opaque value expression (which
+ /// must be mapped to an r-value), return its mapping.
+ const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
+ assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
+ assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
return it->second;
}
@@ -1477,6 +1567,18 @@ public:
/// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
void EmitParmDecl(const VarDecl &D, llvm::Value *Arg);
+ /// protectFromPeepholes - Protect a value that we're intending to
+ /// store to the side, but which will probably be used later, from
+ /// aggressive peepholing optimizations that might delete it.
+ ///
+ /// Pass the result to unprotectFromPeepholes to declare that
+ /// protection is no longer required.
+ ///
+ /// There's no particular reason why this shouldn't apply to
+ /// l-values, it's just that no existing peepholes work on pointers.
+ PeepholeProtection protectFromPeepholes(RValue rvalue);
+ void unprotectFromPeepholes(PeepholeProtection protection);
+
//===--------------------------------------------------------------------===//
// Statement Emission
//===--------------------------------------------------------------------===//
@@ -1646,7 +1748,7 @@ public:
LValue EmitMemberExpr(const MemberExpr *E);
LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
- LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
+ LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
@@ -1687,6 +1789,7 @@ public:
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
+
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
OpenPOWER on IntegriCloud