First pass at abstracting out a class for the target C++ ABI.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173514 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index fff2f82..b5d60f5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -583,12 +583,13 @@
CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
if (!LangOpts.CPlusPlus) return 0;
- switch (T.getCXXABI()) {
- case CXXABI_ARM:
+ switch (T.getCXXABI().getKind()) {
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::iOS:
return CreateARMCXXABI(*this);
- case CXXABI_Itanium:
+ case TargetCXXABI::GenericItanium:
return CreateItaniumCXXABI(*this);
- case CXXABI_Microsoft:
+ case TargetCXXABI::Microsoft:
return CreateMicrosoftCXXABI(*this);
}
llvm_unreachable("Invalid CXXABI type!");
@@ -7607,7 +7608,8 @@
}
CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const {
- if (CC == CC_C && !LangOpts.MRTD && getTargetInfo().getCXXABI() != CXXABI_Microsoft)
+ if (CC == CC_C && !LangOpts.MRTD &&
+ getTargetInfo().getCXXABI().isMemberFunctionCCDefault())
return CC_Default;
return CC;
}
@@ -7618,11 +7620,12 @@
}
MangleContext *ASTContext::createMangleContext() {
- switch (Target->getCXXABI()) {
- case CXXABI_ARM:
- case CXXABI_Itanium:
+ switch (Target->getCXXABI().getKind()) {
+ case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::iOS:
return createItaniumMangleContext(*this, getDiagnostics());
- case CXXABI_Microsoft:
+ case TargetCXXABI::Microsoft:
return createMicrosoftMangleContext(*this, getDiagnostics());
}
llvm_unreachable("Unsupported ABI");
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 2ae0aab..f6cfe63 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -75,10 +75,9 @@
#ifndef NDEBUG
if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
if (isPrimaryBaseVirtual()) {
- // Microsoft ABI doesn't have primary virtual base
- if (Ctx.getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
- assert(getVBaseClassOffset(PrimaryBase).isZero() &&
- "Primary virtual base must be at offset 0!");
+ if (Ctx.getTargetInfo().getCXXABI().hasPrimaryVBases()) {
+ assert(getVBaseClassOffset(PrimaryBase).isZero() &&
+ "Primary virtual base must be at offset 0!");
}
} else {
assert(getBaseClassOffset(PrimaryBase).isZero() &&
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 7f84c56..08f6d5c 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -676,8 +676,12 @@
bool FieldPacked, const FieldDecl *D);
void LayoutBitField(const FieldDecl *D);
+ TargetCXXABI getCXXABI() const {
+ return Context.getTargetInfo().getCXXABI();
+ }
+
bool isMicrosoftCXXABI() const {
- return Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft;
+ return getCXXABI().isMicrosoft();
}
void MSLayoutVirtualBases(const CXXRecordDecl *RD);
@@ -2606,7 +2610,7 @@
// Vtable pointer.
if (RD->isDynamicClass() && !PrimaryBase &&
- C.getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
+ !C.getTargetInfo().getCXXABI().isMicrosoft()) {
PrintOffset(OS, Offset, IndentLevel);
OS << '(' << *RD << " vtable pointer)\n";
}
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 00a186e..5af3b65 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2197,7 +2197,8 @@
VTableContext::VTableContext(ASTContext &Context)
: Context(Context),
- IsMicrosoftABI(Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) { }
+ IsMicrosoftABI(Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+}
VTableContext::~VTableContext() {
llvm::DeleteContainerSeconds(VTableLayouts);
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 9cf04af..fe68a9d 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -84,7 +84,7 @@
ComplexLongDoubleUsesFP2Ret = false;
// Default to using the Itanium ABI.
- CXXABI = CXXABI_Itanium;
+ TheCXXABI.set(TargetCXXABI::GenericItanium);
// Default to an empty address space map.
AddrSpaceMap = &DefaultAddrSpaceMap;
@@ -496,3 +496,17 @@
return true;
}
+
+bool TargetCXXABI::tryParse(llvm::StringRef name) {
+ const Kind unknown = static_cast<Kind>(-1);
+ Kind kind = llvm::StringSwitch<Kind>(name)
+ .Case("arm", GenericARM)
+ .Case("ios", iOS)
+ .Case("itanium", GenericItanium)
+ .Case("microsoft", Microsoft)
+ .Default(unknown);
+ if (kind == unknown) return false;
+
+ set(kind);
+ return true;
+}
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 084b6b3..b90d49e 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -3081,7 +3081,7 @@
}
// ARM targets default to using the ARM C++ ABI.
- CXXABI = CXXABI_ARM;
+ TheCXXABI.set(TargetCXXABI::GenericARM);
// ARM has atomics up to 8 bytes
// FIXME: Set MaxAtomicInlineWidth if we have the feature v6e
@@ -3491,6 +3491,9 @@
// iOS always has 64-bit atomic instructions.
// FIXME: This should be based off of the target features in ARMTargetInfo.
MaxAtomicInlineWidth = 64;
+
+ // Darwin on iOS uses a variant of the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::iOS);
}
};
} // end anonymous namespace.
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 585d3ba..5d1e30f 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -721,7 +721,7 @@
// Before we go any further, try the complete->base constructor
// delegation optimization.
if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
- CGM.getContext().getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
+ CGM.getContext().getTargetInfo().getCXXABI().hasConstructorVariants()) {
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitLocation(Builder, Ctor->getLocEnd());
EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
@@ -920,7 +920,8 @@
// Enter the cleanup scopes for virtual bases.
EnterDtorCleanups(Dtor, Dtor_Complete);
- if (!isTryBody && CGM.getContext().getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
+ if (!isTryBody &&
+ CGM.getContext().getTargetInfo().getCXXABI().hasDestructorVariants()) {
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
LoadCXXThis());
break;
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 02920cd..2c6438b 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -814,7 +814,7 @@
// Lay out the virtual bases. The MS ABI uses a different
// algorithm here due to the lack of primary virtual bases.
- if (Types.getContext().getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
+ if (Types.getContext().getTargetInfo().getCXXABI().hasPrimaryVBases()) {
RD->getIndirectPrimaryBases(IndirectPrimaryBases);
if (Layout.isPrimaryBaseVirtual())
IndirectPrimaryBases.insert(Layout.getPrimaryBase());
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index d5284f8..2da9dba 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -52,10 +52,13 @@
static const char AnnotationSection[] = "llvm.metadata";
static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
- switch (CGM.getContext().getTargetInfo().getCXXABI()) {
- case CXXABI_ARM: return *CreateARMCXXABI(CGM);
- case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM);
- case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM);
+ switch (CGM.getContext().getTargetInfo().getCXXABI().getKind()) {
+ // For IR-generation purposes, there's no significant difference
+ // between the ARM and iOS ABIs.
+ case TargetCXXABI::GenericARM: return *CreateARMCXXABI(CGM);
+ case TargetCXXABI::iOS: return *CreateARMCXXABI(CGM);
+ case TargetCXXABI::GenericItanium: return *CreateItaniumCXXABI(CGM);
+ case TargetCXXABI::Microsoft: return *CreateMicrosoftCXXABI(CGM);
}
llvm_unreachable("invalid C++ ABI kind");
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f6cad26..4819363 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1667,11 +1667,16 @@
return QualType();
}
- // In the Microsoft ABI, the class is allowed to be an incomplete
- // type. In such cases, the compiler makes a worst-case assumption.
- // We make no such assumption right now, so emit an error if the
- // class isn't a complete type.
- if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
+ // C++ allows the class type in a member pointer to be an incomplete type.
+ // In the Microsoft ABI, the size of the member pointer can vary
+ // according to the class type, which means that we really need a
+ // complete type if possible, which means we need to instantiate templates.
+ //
+ // For now, just require a complete type, which will instantiate
+ // templates. This will also error if the type is just forward-declared,
+ // which is a bug, but it's a bug that saves us from dealing with some
+ // complexities at the moment.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
RequireCompleteType(Loc, Class, diag::err_incomplete_type))
return QualType();