diff options
author | John McCall <rjmccall@apple.com> | 2011-02-17 10:25:35 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-17 10:25:35 +0000 |
commit | 56ca35d396d8692c384c785f9aeebcf22563fe1e (patch) | |
tree | cd52281e952ff00244a59c5d47e34459c22fd7c0 /lib/CodeGen/CodeGenFunction.h | |
parent | 05c699e97aea64ee8cea1faaca900a39f977350c (diff) |
Change the representation of GNU ?: expressions to use a different expression
class and to bind the shared value using OpaqueValueExpr. This fixes an
unnoticed problem with deserialization of these expressions where the
deserialized form would lose the vital pointer-equality trait; or rather,
it fixes it because this patch also does the right thing for deserializing
OVEs.
Change OVEs to not be a "temporary object" in the sense that copy elision is
permitted.
This new representation is not totally unawkward to work with, but I think
that's really part and parcel with the semantics we're modelling here. In
particular, it's much easier to fix things like the copy elision bug and to
make the CFG look right.
I've tried to update the analyzer to deal with this in at least some
obvious cases, and I think we get a much better CFG out, but the printing
of OpaqueValueExprs probably needs some work.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125744 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 133 |
1 files changed, 118 insertions, 15 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index adbc223afc..d35a400f7d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/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 //===--------------------------------------------------------------------===// |