/// FinishNonFragileABIModule - Write out global data structures at the end of
/// processing a translation unit.
void FinishNonFragileABIModule();
-
+
llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
unsigned InstanceStart,
unsigned InstanceSize,
/// for the given selector.
llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
- /// GetInterfaceEHType - Get the ehtype for the given Objective-C
+ /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
/// interface. The return value has type EHTypePtrTy.
- llvm::Value *GetInterfaceEHType(const ObjCInterfaceType *IT);
+ llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
+ bool ForDefinition);
const char *getMetaclassSymbolPrefix() const {
return "OBJC_METACLASS_$_";
return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
}
+/// hasObjCExceptionAttribute - Return true if this class or any super
+/// class has the __objc_exception__ attribute.
+static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
+ if (OID->getAttr<ObjCExceptionAttr>())
+ return true;
+ if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
+ return hasObjCExceptionAttribute(Super);
+ return false;
+}
+
/* *** CGObjCMac Public Interface *** */
CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
flags = CLS;
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
+
+ if (hasObjCExceptionAttribute(ID->getClassInterface()))
+ flags |= CLS_EXCEPTION;
+
if (!ID->getClassInterface()->getSuperClass()) {
flags |= CLS_ROOT;
SuperClassGV = 0;
classIsHidden);
UsedGlobals.push_back(ClassMD);
DefinedClasses.push_back(ClassMD);
+
+ // Force the definition of the EHType if necessary.
+ if (flags & CLS_EXCEPTION)
+ GetInterfaceEHType(ID->getClassInterface(), true);
}
/// GenerateProtocolRef - This routine is called to generate code for
const ObjCInterfaceType *IT =
PT->getPointeeType()->getAsObjCInterfaceType();
assert(IT && "Invalid @catch type.");
- llvm::Value *EHType = GetInterfaceEHType(IT);
+ llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false);
SelectorArgs.push_back(EHType);
}
}
CGF.Builder.ClearInsertionPoint();
}
-static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
- if (OID->getAttr<ObjCExceptionAttr>())
- return true;
- if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
- return hasObjCExceptionAttribute(Super);
- return false;
-}
-
llvm::Value *
-CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceType *IT) {
- const ObjCInterfaceDecl *ID = IT->getDecl();
+CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
+ bool ForDefinition) {
llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
- if (Entry)
- return Entry;
-
- // If this type (or a super class) has the __objc_exception__
- // attribute, emit an external reference.
- if (hasObjCExceptionAttribute(IT->getDecl()))
- return Entry =
- new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- (std::string("OBJC_EHTYPE_$_") +
- ID->getIdentifier()->getName()),
- &CGM.getModule());
+ // If we don't need a definition, return the entry if found or check
+ // if we use an external reference.
+ if (!ForDefinition) {
+ if (Entry)
+ return Entry;
+
+ // If this type (or a super class) has the __objc_exception__
+ // attribute, emit an external reference.
+ if (hasObjCExceptionAttribute(ID))
+ return Entry =
+ new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ (std::string("OBJC_EHTYPE_$_") +
+ ID->getIdentifier()->getName()),
+ &CGM.getModule());
+ }
+
+ // Otherwise we need to either make a new entry or fill in the
+ // initializer.
+ assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
std::string VTableName = "objc_ehtype_vtable";
llvm::GlobalVariable *VTableGV =
Values[2] = GetClassGlobal(ClassName, false);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
- Entry =
- new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- (std::string("OBJC_EHTYPE_$_") +
- ID->getIdentifier()->getName()),
- &CGM.getModule());
+ if (Entry) {
+ Entry->setInitializer(Init);
+ } else {
+ Entry = new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
+ llvm::GlobalValue::WeakAnyLinkage,
+ Init,
+ (std::string("OBJC_EHTYPE_$_") +
+ ID->getIdentifier()->getName()),
+ &CGM.getModule());
+ }
+
if (CGM.getLangOptions().getVisibilityMode() ==
LangOptions::HiddenVisibility)
Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
- Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ Entry->setAlignment(8);
+
+ if (ForDefinition) {
+ Entry->setSection("__DATA,__objc_const");
+ Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else {
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ }
return Entry;
}
// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced", align 8' %t &&
// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH3" = global .*section "__DATA,__objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 &&
// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
// FIXME: Should include category name.
// RUN: grep -F 'define internal void @"\01-[A im1]"' %t &&
// RUN: grep '@"OBJC_METACLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t &&
// RUN: grep '@"OBJC_CLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t &&
// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH3" = hidden global .*section "__DATA,__objc_const", align 8' %t &&
// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
// FIXME: Should include category name.
// RUN: grep -F 'define internal void @"\01-[A im1]"' %t &&
@interface EH2
@end
+__attribute__((__objc_exception__))
+@interface EH3
+@end
+
void f1();
void f0(id x) {
f1();
} @catch (EH1 *x) {
} @catch (EH2 *x) {
+ } @catch (EH3 *x) {
}
}
+
+@implementation EH3
+@end