diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-03-06 09:23:02 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-03-06 09:23:02 +0000 |
commit | dd5132ce2569a1ef901c92772eb8581aa1705f25 (patch) | |
tree | 7e0a88c3c6cb70271946aaa95a231b3da55d9f91 /lib/CodeGen | |
parent | 79ade4e028932fcb9dab15e2fb2305ca15ab0f14 (diff) | |
download | src-dd5132ce2569a1ef901c92772eb8581aa1705f25.tar.gz src-dd5132ce2569a1ef901c92772eb8581aa1705f25.zip |
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 17 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 48 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 60 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 66 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.h | 17 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 81 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.h | 17 |
15 files changed, 326 insertions, 28 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 7076067e4381..c10a401d8abf 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -154,7 +154,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { { // C = BuildBlockStructInitlist(); - unsigned int flags = BLOCK_HAS_OBJC_TYPE; + unsigned int flags = BLOCK_HAS_SIGNATURE; // We run this first so that we set BlockHasCopyDispose from the entire // block literal. @@ -184,6 +184,18 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Elts[0] = C; // __flags + { + QualType BPT = BE->getType(); + const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>(); + QualType ResultType = ftype->getResultType(); + + CallArgList Args; + CodeGenTypes &Types = CGM.getTypes(); + const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, + CC_Default, false); + if (CGM.ReturnTypeUsesSret(FnInfo)) + flags |= BLOCK_USE_STRET; + } const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( CGM.getTypes().ConvertType(CGM.getContext().IntTy)); C = llvm::ConstantInt::get(IntTy, flags); @@ -200,6 +212,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); + Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL); C = llvm::ConstantStruct::get(VMContext, Elts, false); @@ -604,7 +617,7 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { // Flags LiteralFields[1] = - llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); + llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); // Reserved LiteralFields[2] = llvm::Constant::getNullValue(IntTy); diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 39f26f8b1363..e91319f6ddab 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -54,10 +54,12 @@ public: BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CXX_OBJ = (1 << 26), BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_OBJC_TYPE = (1 << 30) + BLOCK_USE_STRET = (1 << 29), + BLOCK_HAS_SIGNATURE = (1 << 30) }; }; + class BlockModule : public BlockBase { ASTContext &Context; llvm::Module &TheModule; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 0f5e90fb15aa..706e4411fc79 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -387,6 +387,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); return RValue::get(Result); } + case Builtin::BI__builtin_dwarf_sp_column: { + const llvm::IntegerType *Ty + = cast<llvm::IntegerType>(ConvertType(E->getType())); + int Column = getTargetHooks().getDwarfEHStackPointer(CGM); + if (Column == -1) { + CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); + return RValue::get(llvm::UndefValue::get(Ty)); + } + return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); + } + case Builtin::BI__builtin_init_dwarf_reg_size_table: { + Value *Address = EmitScalarExpr(E->getArg(0)); + if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) + CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); + return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); + } case Builtin::BI__builtin_eh_return: { Value *Int = EmitScalarExpr(E->getArg(0)); Value *Ptr = EmitScalarExpr(E->getArg(1)); @@ -666,6 +682,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1); return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); } + + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: { + LLVMContext &C = CGM.getLLVMContext(); + + Value *Arg = EmitScalarExpr(E->getArg(0)); + const llvm::Type *ArgTy = Arg->getType(); + if (ArgTy->isPPC_FP128Ty()) + break; // FIXME: I'm not sure what the right implementation is here. + int ArgWidth = ArgTy->getPrimitiveSizeInBits(); + const llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth); + Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy); + Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy); + Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp); + return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType()))); + } } // If this is an alias for a libm function (e.g. __builtin_sin) turn it into @@ -735,6 +768,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (Target.getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + return EmitARMBuiltinExpr(BuiltinID, E); case llvm::Triple::x86: case llvm::Triple::x86_64: return EmitX86BuiltinExpr(BuiltinID, E); @@ -746,6 +782,18 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, } } +Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + default: return 0; + + case ARM::BI__builtin_thread_pointer: { + Value *AtomF = CGM.getIntrinsic(Intrinsic::arm_thread_pointer, 0, 0); + return Builder.CreateCall(AtomF); + } + } +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4889fc08f488..7752cf79a28d 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -142,6 +142,12 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, return true; } + llvm::GlobalValue::LinkageTypes TargetLinkage + = getFunctionLinkage(cast<FunctionDecl>(TargetDecl.getDecl())); + + if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) + return true; + // Derive the type for the alias. const llvm::PointerType *AliasType = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 030d2c9c9f84..dc9ecd64f4e4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1062,6 +1062,16 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const NamedDecl *ND = E->getDecl(); + if (ND->hasAttr<WeakRefAttr>()) { + const ValueDecl* VD = cast<ValueDecl>(ND); + llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD); + + Qualifiers Quals = MakeQualifiers(E->getType()); + LValue LV = LValue::MakeAddr(Aliasee, Quals); + + return LV; + } + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { // Check if this is a global variable. diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3df552d75bb6..f0d82a8f0dc6 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -761,7 +761,9 @@ public: return C; } case Expr::DeclRefExprClass: { - NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); + ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); + if (Decl->hasAttr<WeakRefAttr>()) + return CGM.GetWeakRefReference(Decl); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) return CGM.GetAddrOfFunction(FD); if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index db0998b4dedc..7e26971414b4 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1888,6 +1888,8 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { V = CreateTempAlloca(ClassPtrTy, "resval"); llvm::Value *Src = EmitScalarExpr(BaseExpr); Builder.CreateStore(Src, V); + LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); + V = ScalarExprEmitter(*this).EmitLoadOfLValue(LV, E->getType()); } else { if (E->isArrow()) diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 008a480b9c12..a889e55a9e80 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -915,18 +915,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), S.getOutputName(i)); - assert(Target.validateOutputConstraint(Info) && - "Failed to parse output constraint"); + bool IsValid = Target.validateOutputConstraint(Info); (void)IsValid; + assert(IsValid && "Failed to parse output constraint"); OutputConstraintInfos.push_back(Info); } for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), S.getInputName(i)); - assert(Target.validateInputConstraint(OutputConstraintInfos.data(), - S.getNumOutputs(), - Info) && - "Failed to parse input constraint"); + bool IsValid = Target.validateInputConstraint(OutputConstraintInfos.data(), + S.getNumOutputs(), Info); + assert(IsValid && "Failed to parse input constraint"); (void)IsValid; InputConstraintInfos.push_back(Info); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d582c0def346..88d641330009 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1122,6 +1122,7 @@ public: /// is unhandled by the current target. llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 91c7322c6767..d6a56dad0ba5 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -33,6 +33,7 @@ #include "llvm/Module.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" +#include "llvm/ADT/Triple.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -89,6 +90,10 @@ void CodeGenModule::Release() { EmitLLVMUsed(); } +bool CodeGenModule::isTargetDarwin() const { + return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin; +} + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type, @@ -619,9 +624,41 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { return false; } +llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { + const AliasAttr *AA = VD->getAttr<AliasAttr>(); + assert(AA && "No alias?"); + + const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType()); + + // Unique the name through the identifier table. + const char *AliaseeName = + getContext().Idents.get(AA->getAliasee()).getNameStart(); + + // See if there is already something with the target's name in the module. + llvm::GlobalValue *Entry = GlobalDeclMap[AliaseeName]; + + llvm::Constant *Aliasee; + if (isa<llvm::FunctionType>(DeclTy)) + Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl()); + else + Aliasee = GetOrCreateLLVMGlobal(AliaseeName, + llvm::PointerType::getUnqual(DeclTy), 0); + if (!Entry) { + llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee); + F->setLinkage(llvm::Function::ExternalWeakLinkage); + WeakRefReferences.insert(F); + } + + return Aliasee; +} + void CodeGenModule::EmitGlobal(GlobalDecl GD) { const ValueDecl *Global = cast<ValueDecl>(GD.getDecl()); + // Weak references don't produce any output by themselves. + if (Global->hasAttr<WeakRefAttr>()) + return; + // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr<AliasAttr>()) @@ -708,6 +745,14 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl()); + if (FD && !FD->hasAttr<WeakAttr>()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType()->getElementType() == Ty) return Entry; @@ -753,17 +798,17 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // synthesized. else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { if (CD->isImplicit()) { - assert (CD->isUsed()); + assert(CD->isUsed() && "Sema doesn't consider constructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { if (DD->isImplicit()) { - assert (DD->isUsed()); + assert(DD->isUsed() && "Sema doesn't consider destructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { if (MD->isCopyAssignment() && MD->isImplicit()) { - assert (MD->isUsed()); + assert(MD->isUsed() && "Sema doesn't consider CopyAssignment as used."); DeferredDeclsToEmit.push_back(D); } } @@ -817,6 +862,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + if (D && !D->hasAttr<WeakAttr>()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType() == Ty) return Entry; @@ -1203,7 +1255,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); - + getMangleContext().mangleInitDiscriminator(); // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ac8332647b77..c86f8b45bcdd 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -29,6 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ValueHandle.h" #include <list> @@ -117,6 +118,11 @@ class CodeGenModule : public BlockModule { /// pointer lookups instead of full string lookups. llvm::DenseMap<const char*, llvm::GlobalValue*> GlobalDeclMap; + // WeakRefReferences - A set of references that have only been seen via + // a weakref so far. This is used to remove the weak of the reference if we ever + // see a direct reference or a definition. + llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences; + /// \brief Contains the strings used for mangled names. /// /// FIXME: Eventually, this should map from the semantic/canonical @@ -198,6 +204,7 @@ public: const llvm::TargetData &getTargetData() const { return TheTargetData; } llvm::LLVMContext &getLLVMContext() { return VMContext; } const TargetCodeGenInfo &getTargetCodeGenInfo() const; + bool isTargetDarwin() const; /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; @@ -243,6 +250,9 @@ public: void BuildThunksForVirtual(GlobalDecl GD); void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD); + /// GetWeakRefReference - Get a reference to the target of VD. + llvm::Constant *GetWeakRefReference(const ValueDecl *VD); + /// BuildThunk - Build a thunk for the given method. llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern, const ThunkAdjustment &ThisAdjustment); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 64743c7696f7..20d54b34105d 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -37,7 +37,19 @@ using namespace clang; using namespace CodeGen; namespace { - + +static const DeclContext *GetLocalClassFunctionDeclContext( + const DeclContext *DC) { + if (isa<CXXRecordDecl>(DC)) { + while (!DC->isNamespace() && !DC->isTranslationUnit() && + !isa<FunctionDecl>(DC)) + DC = DC->getParent(); + if (isa<FunctionDecl>(DC)) + return DC; + } + return 0; +} + static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) && "Passed in decl is not a ctor or dtor!"); @@ -61,7 +73,7 @@ class CXXNameMangler { const CXXMethodDecl *Structor; unsigned StructorType; - + llvm::DenseMap<uintptr_t, unsigned> Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -128,11 +140,12 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); - void mangleNestedName(const NamedDecl *ND, const DeclContext *DC); + void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void manglePrefix(const DeclContext *DC); + void manglePrefix(const DeclContext *DC, bool NoFunction=false); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -342,7 +355,12 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // ::= <local-name> // const DeclContext *DC = ND->getDeclContext(); - + + if (GetLocalClassFunctionDeclContext(DC)) { + mangleLocalName(ND); + return; + } + // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. if (isa<FunctionDecl>(DC) && ND->hasLinkage()) @@ -603,7 +621,8 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { } void CXXNameMangler::mangleNestedName(const NamedDecl *ND, - const DeclContext *DC) { + const DeclContext *DC, + bool NoFunction) { // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E @@ -616,8 +635,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC); + } + else { + manglePrefix(DC, NoFunction); mangleUnqualifiedName(ND); } @@ -640,18 +660,35 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] // <discriminator> := _ <non-negative number> + const DeclContext *DC = ND->getDeclContext(); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND->getDeclContext())) + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) mangleObjCMethodName(MD); + else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) { + mangleFunctionEncoding(cast<FunctionDecl>(CDC)); + Out << 'E'; + mangleNestedName(ND, DC, true /*NoFunction*/); + + // FIXME. This still does not cover all cases. + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + + return; + } else - mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext())); + mangleFunctionEncoding(cast<FunctionDecl>(DC)); Out << 'E'; mangleUnqualifiedName(ND); } -void CXXNameMangler::manglePrefix(const DeclContext *DC) { +void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // <prefix> ::= <prefix> <unqualified-name> // ::= <template-prefix> <template-args> // ::= <template-param> @@ -672,8 +709,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC->getParent()); + } + else if(NoFunction && isa<FunctionDecl>(DC)) + return; + else { + manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast<NamedDecl>(DC)); } diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 8d9629528d63..97f94b69b432 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -44,7 +44,9 @@ class MangleContext { ASTContext &Context; llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; - + unsigned Discriminator; + llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; + public: explicit MangleContext(ASTContext &Context) : Context(Context) { } @@ -85,7 +87,20 @@ public: llvm::SmallVectorImpl<char> &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, llvm::SmallVectorImpl<char> &); + + void mangleInitDiscriminator() { + Discriminator = 0; + } + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return false; + disc = discriminator-2; + return true; + } /// @} }; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f4ec914a4e05..cb6a7df68d45 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -328,6 +328,16 @@ public: void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + // Darwin uses different dwarf register numbers for EH. + if (CGM.isTargetDarwin()) return 5; + + return 4; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const; }; } @@ -568,6 +578,51 @@ void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D, } } +bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( + CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); + + // 0-7 are the eight integer registers; the order is different + // on Darwin (for EH), but the range is the same. + // 8 is %eip. + for (unsigned I = 0, E = 9; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Four8, Slot); + } + + if (CGF.CGM.isTargetDarwin()) { + // 12-16 are st(0..4). Not sure why we stop at 4. + // These have size 16, which is sizeof(long double) on + // platforms with 8-byte alignment for that type. + llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); + for (unsigned I = 12, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Sixteen8, Slot); + } + + } else { + // 9 is %eflags, which doesn't get a size on Darwin for some + // reason. + Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9)); + + // 11-16 are st(0..5). Not sure why we stop at 5. + // These have size 12, which is sizeof(long double) on + // platforms with 4-byte alignment for that type. + llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12); + for (unsigned I = 11, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Twelve8, Slot); + } + } + + return false; +} + namespace { /// X86_64ABIInfo - The X86_64 ABI information. class X86_64ABIInfo : public ABIInfo { @@ -656,6 +711,28 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + return 7; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); + + // 0-16 are the 16 integer registers. + // 17 is %rip. + for (unsigned I = 0, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Eight8, Slot); + } + + return false; + } }; } @@ -1559,6 +1636,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo { public: ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K) :TargetCodeGenInfo(new ARMABIInfo(K)) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return 13; + } }; } diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 9e80081429cc..f0a78243ff79 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -56,6 +56,23 @@ namespace clang { /// through such registers. virtual bool extendPointerWithSExt() const { return false; } + /// Determines the DWARF register number for the stack pointer, for + /// exception-handling purposes. Implements __builtin_dwarf_sp_column. + /// + /// Returns -1 if the operation is unsupported by this target. + virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return -1; + } + + /// Initializes the given DWARF EH register-size table, a char*. + /// Implements __builtin_init_dwarf_reg_size_table. + /// + /// Returns true if the operation is unsupported by this target. + virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + return true; + } + /// Performs the code-generation required to convert a return /// address as stored by the system into the actual address of the /// next instruction that will be executed. |