diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 85 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 64 | ||||
-rw-r--r-- | lib/CodeGen/CGValue.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 137 |
7 files changed, 251 insertions, 55 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9ad3ae8352..d7371141f3 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -672,6 +672,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitStringLiteralLValue(cast<StringLiteral>(E)); case Expr::ObjCEncodeExprClass: return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E)); + case Expr::PseudoObjectExprClass: + return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E)); case Expr::BlockDeclRefExprClass: return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E)); @@ -2768,3 +2770,86 @@ void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, unsigned AccuracyN, cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy, Node); } + +namespace { + struct LValueOrRValue { + LValue LV; + RValue RV; + }; +} + +static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF, + const PseudoObjectExpr *E, + bool forLValue, + AggValueSlot slot) { + llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; + + // Find the result expression, if any. + const Expr *resultExpr = E->getResultExpr(); + LValueOrRValue result; + + for (PseudoObjectExpr::const_semantics_iterator + i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { + const Expr *semantic = *i; + + // If this semantic expression is an opaque value, bind it + // to the result of its source expression. + if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { + + // If this is the result expression, we may need to evaluate + // directly into the slot. + typedef CodeGenFunction::OpaqueValueMappingData OVMA; + OVMA opaqueData; + if (ov == resultExpr && ov->isRValue() && !forLValue && + CodeGenFunction::hasAggregateLLVMType(ov->getType()) && + !ov->getType()->isAnyComplexType()) { + CGF.EmitAggExpr(ov->getSourceExpr(), slot); + + LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType()); + opaqueData = OVMA::bind(CGF, ov, LV); + result.RV = slot.asRValue(); + + // Otherwise, emit as normal. + } else { + opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); + + // If this is the result, also evaluate the result now. + if (ov == resultExpr) { + if (forLValue) + result.LV = CGF.EmitLValue(ov); + else + result.RV = CGF.EmitAnyExpr(ov, slot); + } + } + + opaques.push_back(opaqueData); + + // Otherwise, if the expression is the result, evaluate it + // and remember the result. + } else if (semantic == resultExpr) { + if (forLValue) + result.LV = CGF.EmitLValue(semantic); + else + result.RV = CGF.EmitAnyExpr(semantic, slot); + + // Otherwise, evaluate the expression in an ignored context. + } else { + CGF.EmitIgnoredExpr(semantic); + } + } + + // Unbind all the opaques now. + for (unsigned i = 0, e = opaques.size(); i != e; ++i) + opaques[i].unbind(CGF); + + return result; +} + +RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E, + AggValueSlot slot) { + return emitPseudoObjectExpr(*this, E, false, slot).RV; +} + +LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) { + return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV; +} diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0fa143391d..ffbc2e0732 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -148,6 +148,15 @@ public: void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); + void VisitPseudoObjectExpr(PseudoObjectExpr *E) { + if (E->isGLValue()) { + LValue LV = CGF.EmitPseudoObjectLValue(E); + return EmitFinalDestCopy(E, LV); + } + + CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType())); + } + void VisitVAArgExpr(VAArgExpr *E); void EmitInitializationToLValue(Expr *E, LValue Address); diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index b6c416bc35..c09278c14e 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -137,6 +137,10 @@ public: return CGF.getOpaqueRValueMapping(E).getComplexVal(); } + ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) { + return CGF.EmitPseudoObjectRValue(E).getComplexVal(); + } + // FIXME: CompoundLiteralExpr ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 50c5057f3e..83ca159aa5 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -197,6 +197,10 @@ public: return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength()); } + Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) { + return CGF.EmitPseudoObjectRValue(E).getScalarVal(); + } + Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) { if (E->isGLValue()) return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E)); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 0cd98ee319..f164103723 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -2231,6 +2231,59 @@ static bool shouldEmitSeparateBlockRetain(const Expr *e) { return true; } +/// Try to emit a PseudoObjectExpr at +1. +/// +/// This massively duplicates emitPseudoObjectRValue. +static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF, + const PseudoObjectExpr *E) { + llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; + + // Find the result expression. + const Expr *resultExpr = E->getResultExpr(); + assert(resultExpr); + TryEmitResult result; + + for (PseudoObjectExpr::const_semantics_iterator + i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { + const Expr *semantic = *i; + + // If this semantic expression is an opaque value, bind it + // to the result of its source expression. + if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { + typedef CodeGenFunction::OpaqueValueMappingData OVMA; + OVMA opaqueData; + + // If this semantic is the result of the pseudo-object + // expression, try to evaluate the source as +1. + if (ov == resultExpr) { + assert(!OVMA::shouldBindAsLValue(ov)); + result = tryEmitARCRetainScalarExpr(CGF, ov->getSourceExpr()); + opaqueData = OVMA::bind(CGF, ov, RValue::get(result.getPointer())); + + // Otherwise, just bind it. + } else { + opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); + } + opaques.push_back(opaqueData); + + // Otherwise, if the expression is the result, evaluate it + // and remember the result. + } else if (semantic == resultExpr) { + result = tryEmitARCRetainScalarExpr(CGF, semantic); + + // Otherwise, evaluate the expression in an ignored context. + } else { + CGF.EmitIgnoredExpr(semantic); + } + } + + // Unbind all the opaques now. + for (unsigned i = 0, e = opaques.size(); i != e; ++i) + opaques[i].unbind(CGF); + + return result; +} + static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { // Look through cleanups. @@ -2356,6 +2409,17 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { llvm::Value *result = emitARCRetainCall(CGF, e); if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); return TryEmitResult(result, true); + + // Look through pseudo-object expressions. + } else if (const PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { + TryEmitResult result + = tryEmitARCRetainPseudoObject(CGF, pseudo); + if (resultType) { + llvm::Value *value = result.getPointer(); + value = CGF.Builder.CreateBitCast(value, resultType); + result.setPointer(value); + } + return result; } // Conservatively halt the search at any other expression kind. diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 489e600b3d..bc94e8ebc9 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -27,6 +27,7 @@ namespace clang { class ObjCPropertyRefExpr; namespace CodeGen { + class AggValueSlot; class CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an @@ -452,7 +453,7 @@ public: RValue asRValue() const { return RValue::getAggregate(getAddr(), isVolatile()); } - + void setZeroed(bool V = true) { ZeroedFlag = V; } IsZeroed_t isZeroed() const { return IsZeroed_t(ZeroedFlag); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4940e21c8b..0b31ce43a9 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -950,20 +950,86 @@ public: public: PeepholeProtection() : Inst(0) {} - }; + }; - /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr. - class OpaqueValueMapping { - CodeGenFunction &CGF; + /// A non-RAII class containing all the information about a bound + /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for + /// this which makes individual mappings very simple; using this + /// class directly is useful when you have a variable number of + /// opaque values or don't want the RAII functionality for some + /// reason. + class OpaqueValueMappingData { const OpaqueValueExpr *OpaqueValue; bool BoundLValue; CodeGenFunction::PeepholeProtection Protection; + OpaqueValueMappingData(const OpaqueValueExpr *ov, + bool boundLValue) + : OpaqueValue(ov), BoundLValue(boundLValue) {} public: + OpaqueValueMappingData() : OpaqueValue(0) {} + static bool shouldBindAsLValue(const Expr *expr) { return expr->isGLValue() || expr->getType()->isRecordType(); } + static OpaqueValueMappingData bind(CodeGenFunction &CGF, + const OpaqueValueExpr *ov, + const Expr *e) { + if (shouldBindAsLValue(ov)) + return bind(CGF, ov, CGF.EmitLValue(e)); + return bind(CGF, ov, CGF.EmitAnyExpr(e)); + } + + static OpaqueValueMappingData bind(CodeGenFunction &CGF, + const OpaqueValueExpr *ov, + const LValue &lv) { + assert(shouldBindAsLValue(ov)); + CGF.OpaqueLValues.insert(std::make_pair(ov, lv)); + return OpaqueValueMappingData(ov, true); + } + + static OpaqueValueMappingData bind(CodeGenFunction &CGF, + const OpaqueValueExpr *ov, + const RValue &rv) { + assert(!shouldBindAsLValue(ov)); + CGF.OpaqueRValues.insert(std::make_pair(ov, rv)); + + OpaqueValueMappingData data(ov, false); + + // Work around an extremely aggressive peephole optimization in + // EmitScalarConversion which assumes that all other uses of a + // value are extant. + data.Protection = CGF.protectFromPeepholes(rv); + + return data; + } + + bool isValid() const { return OpaqueValue != 0; } + void clear() { OpaqueValue = 0; } + + void unbind(CodeGenFunction &CGF) { + assert(OpaqueValue && "no data to unbind!"); + + if (BoundLValue) { + CGF.OpaqueLValues.erase(OpaqueValue); + } else { + CGF.OpaqueRValues.erase(OpaqueValue); + CGF.unprotectFromPeepholes(Protection); + } + } + }; + + /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr. + class OpaqueValueMapping { + CodeGenFunction &CGF; + OpaqueValueMappingData Data; + + public: + static bool shouldBindAsLValue(const Expr *expr) { + return OpaqueValueMappingData::shouldBindAsLValue(expr); + } + /// 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 @@ -971,75 +1037,34 @@ public: /// OpaqueValueMapping(CodeGenFunction &CGF, const AbstractConditionalOperator *op) : CGF(CGF) { - if (isa<ConditionalOperator>(op)) { - OpaqueValue = 0; - BoundLValue = false; + if (isa<ConditionalOperator>(op)) + // Leave Data empty. return; - } const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op); - init(e->getOpaqueValue(), e->getCommon()); + Data = OpaqueValueMappingData::bind(CGF, e->getOpaqueValue(), + e->getCommon()); } OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *opaqueValue, LValue lvalue) - : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) { - assert(opaqueValue && "no opaque value expression!"); - assert(shouldBindAsLValue(opaqueValue)); - initLValue(lvalue); + : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, 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); + : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) { } void pop() { - assert(OpaqueValue && "mapping already popped!"); - popImpl(); - OpaqueValue = 0; + Data.unbind(CGF); + Data.clear(); } ~OpaqueValueMapping() { - 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)); + if (Data.isValid()) Data.unbind(CGF); } }; @@ -2015,6 +2040,10 @@ public: LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e); + RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e, + AggValueSlot slot = AggValueSlot::ignored()); + LValue EmitPseudoObjectLValue(const PseudoObjectExpr *e); + llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); LValue EmitLValueForAnonRecordField(llvm::Value* Base, |