diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 4230dbdf293..176152a8369 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -963,6 +963,49 @@ static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init, return llvm::isBytewiseValue(Init); } +static Address createUnnamedGlobalFrom(CodeGenModule &CGM, const VarDecl &D, + CGBuilderTy &Builder, + llvm::Constant *Constant, + CharUnits Align) { + auto FunctionName = [&](const DeclContext *DC) -> std::string { + if (const auto *FD = dyn_cast<FunctionDecl>(DC)) { + if (const auto *CC = dyn_cast<CXXConstructorDecl>(FD)) + return CC->getNameAsString(); + if (const auto *CD = dyn_cast<CXXDestructorDecl>(FD)) + return CD->getNameAsString(); + return CGM.getMangledName(FD); + } else if (const auto *OM = dyn_cast<ObjCMethodDecl>(DC)) { + return OM->getNameAsString(); + } else if (const auto *OM = dyn_cast<BlockDecl>(DC)) { + return "<block>"; + } else if (const auto *OM = dyn_cast<CapturedDecl>(DC)) { + return "<captured>"; + } else { + llvm::llvm_unreachable_internal("expected a function or method"); + } + }; + + auto *Ty = Constant->getType(); + bool isConstant = true; + llvm::GlobalVariable *InsertBefore = nullptr; + unsigned AS = CGM.getContext().getTargetAddressSpace( + CGM.getStringLiteralAddressSpace()); + llvm::GlobalVariable *GV = new llvm::GlobalVariable( + CGM.getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage, + Constant, + "__const." + FunctionName(D.getParentFunctionOrMethod()) + "." + + D.getName(), + InsertBefore, llvm::GlobalValue::NotThreadLocal, AS); + GV->setAlignment(Align.getQuantity()); + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + + Address SrcPtr = Address(GV, Align); + llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(), AS); + if (SrcPtr.getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP); + return SrcPtr; +} + static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, Address Loc, bool isVolatile, CGBuilderTy &Builder, @@ -1002,25 +1045,10 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, return; } - // Otherwise, create a temporary global with the initializer then memcpy from - // the global to the alloca. - std::string Name = getStaticDeclName(CGM, D); - unsigned AS = CGM.getContext().getTargetAddressSpace( - CGM.getStringLiteralAddressSpace()); - llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(), AS); - - llvm::GlobalVariable *GV = new llvm::GlobalVariable( - CGM.getModule(), constant->getType(), true, - llvm::GlobalValue::PrivateLinkage, constant, Name, nullptr, - llvm::GlobalValue::NotThreadLocal, AS); - GV->setAlignment(Loc.getAlignment().getQuantity()); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - Address SrcPtr = Address(GV, Loc.getAlignment()); - if (SrcPtr.getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP); - - Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile); + Builder.CreateMemCpy( + Loc, + createUnnamedGlobalFrom(CGM, D, Builder, constant, Loc.getAlignment()), + SizeVal, isVolatile); } /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a |