diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 81 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 19 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 85 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 27 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 133 |
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 //===--------------------------------------------------------------------===// |