Emit initializers for static-storage-duration temporaries as constants where

possible.

llvm-svn: 183967
This commit is contained in:
Richard Smith
2013-06-14 03:07:01 +00:00
parent 18db1f2f1a
commit a509f2fdfa
6 changed files with 117 additions and 28 deletions

View File

@@ -2615,15 +2615,16 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str,
}
llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
const MaterializeTemporaryExpr *E, const Expr *Inner) {
const MaterializeTemporaryExpr *E, const Expr *Init) {
assert((E->getStorageDuration() == SD_Static ||
E->getStorageDuration() == SD_Thread) && "not a global temporary");
const VarDecl *VD = cast<VarDecl>(E->getExtendingDecl());
// If we're not materializing a subobject of the temporary, keep the
// cv-qualifiers from the type of the MaterializeTemporaryExpr.
if (Inner == E->GetTemporaryExpr())
Inner = E;
QualType MaterializedType = Init->getType();
if (Init == E->GetTemporaryExpr())
MaterializedType = E->getType();
llvm::Constant *&Slot = MaterializedGlobalTemporaryMap[E];
if (Slot)
@@ -2637,34 +2638,44 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
Out.flush();
llvm::Constant *InitialValue = 0;
APValue *Value = 0;
if (E->getStorageDuration() == SD_Static) {
// We might have a constant initializer for this temporary.
// We might have a cached constant initializer for this temporary. Note
// that this might have a different value from the value computed by
// evaluating the initializer if the surrounding constant expression
// modifies the temporary.
Value = getContext().getMaterializedTemporaryValue(E, false);
if (Value && Value->isUninit())
Value = 0;
}
bool Constant;
// Try evaluating it now, it might have a constant initializer.
Expr::EvalResult EvalResult;
if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) &&
!EvalResult.hasSideEffects())
Value = &EvalResult.Val;
llvm::Constant *InitialValue = 0;
bool Constant = false;
llvm::Type *Type;
if (Value) {
// The temporary has a constant initializer, use it.
InitialValue = EmitConstantValue(*Value, Inner->getType(), 0);
Constant = isTypeConstant(Inner->getType(), /*ExcludeCtor*/Value);
InitialValue = EmitConstantValue(*Value, MaterializedType, 0);
Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
Type = InitialValue->getType();
} else {
// No constant initializer, the initialization will be provided when we
// No initializer, the initialization will be provided when we
// initialize the declaration which performed lifetime extension.
InitialValue = EmitNullConstant(Inner->getType());
Constant = false;
Type = getTypes().ConvertTypeForMem(MaterializedType);
}
// Create a global variable for this lifetime-extended temporary.
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(getModule(), InitialValue->getType(), Constant,
llvm::GlobalValue::PrivateLinkage, InitialValue,
Name.c_str());
new llvm::GlobalVariable(getModule(), Type, Constant,
llvm::GlobalValue::PrivateLinkage,
InitialValue, Name.c_str());
GV->setAlignment(
getContext().getTypeAlignInChars(Inner->getType()).getQuantity());
getContext().getTypeAlignInChars(MaterializedType).getQuantity());
if (VD->getTLSKind())
setTLSMode(GV, *VD);
Slot = GV;