summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp109
1 files changed, 22 insertions, 87 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f0d8619faa3..d5ce4870f18 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1422,11 +1422,10 @@ static ConstantEmissionKind checkVarTypeForConstantEmission(QualType type) {
}
/// Try to emit a reference to the given value without producing it as
-/// an l-value. This is just an optimization, but it avoids us needing
-/// to emit global copies of variables if they're named without triggering
-/// a formal use in a context where we can't emit a direct reference to them,
-/// for instance if a block or lambda or a member of a local class uses a
-/// const int variable or constexpr variable from an enclosing function.
+/// an l-value. This is actually more than an optimization: we can't
+/// produce an l-value for variables that we never actually captured
+/// in a block or lambda, which means const int variables or constexpr
+/// literals or similar.
CodeGenFunction::ConstantEmission
CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
ValueDecl *value = refExpr->getDecl();
@@ -2451,97 +2450,33 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
return LValue::MakeGlobalReg(Address(Ptr, Alignment), VD->getType());
}
-/// Determine whether we can emit a reference to \p VD from the current
-/// context, despite not necessarily having seen an odr-use of the variable in
-/// this context.
-static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF,
- const DeclRefExpr *E,
- const VarDecl *VD,
- bool IsConstant) {
- // For a variable declared in an enclosing scope, do not emit a spurious
- // reference even if we have a capture, as that will emit an unwarranted
- // reference to our capture state, and will likely generate worse code than
- // emitting a local copy.
- if (E->refersToEnclosingVariableOrCapture())
- return false;
-
- // For a local declaration declared in this function, we can always reference
- // it even if we don't have an odr-use.
- if (VD->hasLocalStorage()) {
- return VD->getDeclContext() ==
- dyn_cast_or_null<DeclContext>(CGF.CurCodeDecl);
- }
-
- // For a global declaration, we can emit a reference to it if we know
- // for sure that we are able to emit a definition of it.
- VD = VD->getDefinition(CGF.getContext());
- if (!VD)
- return false;
-
- // Don't emit a spurious reference if it might be to a variable that only
- // exists on a different device / target.
- // FIXME: This is unnecessarily broad. Check whether this would actually be a
- // cross-target reference.
- if (CGF.getLangOpts().OpenMP || CGF.getLangOpts().CUDA ||
- CGF.getLangOpts().OpenCL) {
- return false;
- }
-
- // We can emit a spurious reference only if the linkage implies that we'll
- // be emitting a non-interposable symbol that will be retained until link
- // time.
- switch (CGF.CGM.getLLVMLinkageVarDefinition(VD, IsConstant)) {
- case llvm::GlobalValue::ExternalLinkage:
- case llvm::GlobalValue::LinkOnceODRLinkage:
- case llvm::GlobalValue::WeakODRLinkage:
- case llvm::GlobalValue::InternalLinkage:
- case llvm::GlobalValue::PrivateLinkage:
- return true;
- default:
- return false;
- }
-}
-
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
QualType T = E->getType();
- assert(E->isNonOdrUse() != NOUR_Unevaluated &&
- "should not emit an unevaluated operand");
-
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
// Global Named registers access via intrinsics only
if (VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
return EmitGlobalNamedRegister(VD, CGM);
- // If this DeclRefExpr does not constitute an odr-use of the variable,
- // we're not permitted to emit a reference to it in general, and it might
- // not be captured if capture would be necessary for a use. Emit the
- // constant value directly instead.
- if (E->isNonOdrUse() == NOUR_Constant &&
- (VD->getType()->isReferenceType() ||
- !canEmitSpuriousReferenceToVariable(*this, E, VD, true))) {
- VD->getAnyInitializer(VD);
- llvm::Constant *Val = ConstantEmitter(*this).emitAbstract(
- E->getLocation(), *VD->evaluateValue(), VD->getType());
- assert(Val && "failed to emit constant expression");
-
- Address Addr = Address::invalid();
- if (!VD->getType()->isReferenceType()) {
- // Spill the constant value to a global.
- Addr = CGM.createUnnamedGlobalFrom(*VD, Val,
- getContext().getDeclAlign(VD));
- } else {
- // Should we be using the alignment of the constant pointer we emitted?
- CharUnits Alignment =
- getNaturalTypeAlignment(E->getType(),
- /* BaseInfo= */ nullptr,
- /* TBAAInfo= */ nullptr,
- /* forPointeeType= */ true);
- Addr = Address(Val, Alignment);
- }
- return MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+ // A DeclRefExpr for a reference initialized by a constant expression can
+ // appear without being odr-used. Directly emit the constant initializer.
+ VD->getAnyInitializer(VD);
+ if (E->isNonOdrUse() == NOUR_Constant && VD->getType()->isReferenceType()) {
+ llvm::Constant *Val =
+ ConstantEmitter(*this).emitAbstract(E->getLocation(),
+ *VD->evaluateValue(),
+ VD->getType());
+ assert(Val && "failed to emit reference constant expression");
+ // FIXME: Eventually we will want to emit vector element references.
+
+ // Should we be using the alignment of the constant pointer we emitted?
+ CharUnits Alignment = getNaturalTypeAlignment(E->getType(),
+ /* BaseInfo= */ nullptr,
+ /* TBAAInfo= */ nullptr,
+ /* forPointeeType= */ true);
+ return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
}
// FIXME: Handle other kinds of non-odr-use DeclRefExprs.
@@ -2577,7 +2512,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// FIXME: We should be able to assert this for FunctionDecls as well!
// FIXME: We should be able to assert this for all DeclRefExprs, not just
// those with a valid source location.
- assert((ND->isUsed(false) || !isa<VarDecl>(ND) || E->isNonOdrUse() ||
+ assert((ND->isUsed(false) || !isa<VarDecl>(ND) ||
!E->getLocation().isValid()) &&
"Should not use decl without marking it used!");
OpenPOWER on IntegriCloud