aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-03-06 09:23:02 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-03-06 09:23:02 +0000
commitdd5132ce2569a1ef901c92772eb8581aa1705f25 (patch)
tree7e0a88c3c6cb70271946aaa95a231b3da55d9f91 /lib/CodeGen
parent79ade4e028932fcb9dab15e2fb2305ca15ab0f14 (diff)
downloadsrc-dd5132ce2569a1ef901c92772eb8581aa1705f25.tar.gz
src-dd5132ce2569a1ef901c92772eb8581aa1705f25.zip
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBlocks.cpp17
-rw-r--r--lib/CodeGen/CGBlocks.h4
-rw-r--r--lib/CodeGen/CGBuiltin.cpp48
-rw-r--r--lib/CodeGen/CGCXX.cpp6
-rw-r--r--lib/CodeGen/CGExpr.cpp10
-rw-r--r--lib/CodeGen/CGExprConstant.cpp4
-rw-r--r--lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--lib/CodeGen/CGStmt.cpp11
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp60
-rw-r--r--lib/CodeGen/CodeGenModule.h10
-rw-r--r--lib/CodeGen/Mangle.cpp66
-rw-r--r--lib/CodeGen/Mangle.h17
-rw-r--r--lib/CodeGen/TargetInfo.cpp81
-rw-r--r--lib/CodeGen/TargetInfo.h17
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.