summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp97
1 files changed, 60 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index db0bd95..6d129d0 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -99,8 +99,8 @@ class LazyRuntimeFunction {
/// GNU Objective-C runtime code generation. This class implements the parts of
-/// Objective-C support that are specific to the GNU family of runtimes (GCC and
-/// GNUstep).
+/// Objective-C support that are specific to the GNU family of runtimes (GCC,
+/// GNUstep and ObjFW).
class CGObjCGNU : public CGObjCRuntime {
protected:
/// The LLVM module into which output is inserted
@@ -292,8 +292,8 @@ private:
protected:
/// Function used for throwing Objective-C exceptions.
LazyRuntimeFunction ExceptionThrowFn;
- /// Function used for rethrowing exceptions, used at the end of @finally or
- /// @synchronize blocks.
+ /// Function used for rethrowing exceptions, used at the end of \@finally or
+ /// \@synchronize blocks.
LazyRuntimeFunction ExceptionReThrowFn;
/// Function called when entering a catch function. This is required for
/// differentiating Objective-C exceptions and foreign exceptions.
@@ -301,9 +301,9 @@ protected:
/// Function called when exiting from a catch block. Used to do exception
/// cleanup.
LazyRuntimeFunction ExitCatchFn;
- /// Function called when entering an @synchronize block. Acquires the lock.
+ /// Function called when entering an \@synchronize block. Acquires the lock.
LazyRuntimeFunction SyncEnterFn;
- /// Function called when exiting an @synchronize block. Releases the lock.
+ /// Function called when exiting an \@synchronize block. Releases the lock.
LazyRuntimeFunction SyncExitFn;
private:
@@ -350,7 +350,7 @@ private:
ArrayRef<Selector> MethodSels,
ArrayRef<llvm::Constant *> MethodTypes,
bool isClassMethodList);
- /// Emits an empty protocol. This is used for @protocol() where no protocol
+ /// Emits an empty protocol. This is used for \@protocol() where no protocol
/// is found. The runtime will (hopefully) fix up the pointer to refer to the
/// real protocol.
llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
@@ -397,11 +397,11 @@ private:
const ObjCIvarDecl *Ivar);
/// Emits a reference to a class. This allows the linker to object if there
/// is no class of the matching name.
+protected:
void EmitClassRef(const std::string &className);
/// Emits a pointer to the named class
- llvm::Value *GetClassNamed(CGBuilderTy &Builder, const std::string &Name,
- bool isWeak);
-protected:
+ virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
+ const std::string &Name, bool isWeak);
/// Looks up the method for sending a message to the specified object. This
/// mechanism differs between the GCC and GNU runtimes, so this method must be
/// overridden in subclasses.
@@ -653,6 +653,33 @@ class CGObjCGNUstep : public CGObjCGNU {
}
};
+/// The ObjFW runtime, which closely follows the GCC runtime's
+/// compiler ABI. Support here is due to Jonathan Schleifer, the
+/// ObjFW maintainer.
+class CGObjCObjFW : public CGObjCGCC {
+ /// Emit class references unconditionally as direct symbol references.
+ virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
+ const std::string &Name, bool isWeak) {
+ if (isWeak)
+ return CGObjCGNU::GetClassNamed(Builder, Name, isWeak);
+
+ EmitClassRef(Name);
+
+ std::string SymbolName = "_OBJC_CLASS_" + Name;
+
+ llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
+
+ if (!ClassSymbol)
+ ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, SymbolName);
+
+ return ClassSymbol;
+ }
+
+public:
+ CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {}
+};
} // end anonymous namespace
@@ -889,7 +916,7 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
// foreign exceptions. With the new ABI, we use __objc_id_typeinfo as
// a pointer indicating object catchalls, and NULL to indicate real
// catchalls
- if (CGM.getLangOpts().ObjCNonFragileABI) {
+ if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
return MakeConstantString("@id");
} else {
return 0;
@@ -1627,7 +1654,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
iter = PD->prop_begin(), endIter = PD->prop_end();
iter != endIter ; iter++) {
std::vector<llvm::Constant*> Fields;
- ObjCPropertyDecl *property = (*iter);
+ ObjCPropertyDecl *property = *iter;
Fields.push_back(MakeConstantString(property->getNameAsString()));
Fields.push_back(llvm::ConstantInt::get(Int8Ty,
@@ -1877,7 +1904,7 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
iter != endIter ; iter++) {
std::vector<llvm::Constant*> Fields;
- ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
+ ObjCPropertyDecl *property = iter->getPropertyDecl();
ObjCPropertyImplDecl *propertyImpl = *iter;
bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Synthesize);
@@ -1984,7 +2011,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
// For non-fragile ivars, set the instance size to 0 - {the size of just this
// class}. The runtime will then set this to the correct value on load.
- if (CGM.getContext().getLangOpts().ObjCNonFragileABI) {
+ if (CGM.getContext().getLangOpts().ObjCRuntime.isNonFragile()) {
instanceSize = 0 - (instanceSize - superInstanceSize);
}
@@ -1999,7 +2026,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
// Get the offset
uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
uint64_t Offset = BaseOffset;
- if (CGM.getContext().getLangOpts().ObjCNonFragileABI) {
+ if (CGM.getContext().getLangOpts().ObjCRuntime.isNonFragile()) {
Offset = BaseOffset - superInstanceSize;
}
llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
@@ -2486,25 +2513,8 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
ExceptionAsObject = CGF.ObjCEHValueStack.back();
}
ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
-
- // Note: This may have to be an invoke, if we want to support constructs like:
- // @try {
- // @throw(obj);
- // }
- // @catch(id) ...
- //
- // This is effectively turning @throw into an incredibly-expensive goto, but
- // it may happen as a result of inlining followed by missed optimizations, or
- // as a result of stupidity.
- llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
- if (!UnwindBB) {
- CGF.Builder.CreateCall(ExceptionThrowFn, ExceptionAsObject);
- CGF.Builder.CreateUnreachable();
- } else {
- CGF.Builder.CreateInvoke(ExceptionThrowFn, UnwindBB, UnwindBB,
- ExceptionAsObject);
- }
- // Clear the insertion point to indicate we are in unreachable code.
+ CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ CGF.Builder.CreateUnreachable();
CGF.Builder.ClearInsertionPoint();
}
@@ -2640,7 +2650,7 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) {
- if (CGM.getLangOpts().ObjCNonFragileABI) {
+ if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
if (RuntimeVersion < 10)
return CGF.Builder.CreateZExtOrBitCast(
@@ -2665,7 +2675,20 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
CGObjCRuntime *
clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
- if (CGM.getLangOpts().ObjCNonFragileABI)
+ switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
+ case ObjCRuntime::GNUstep:
return new CGObjCGNUstep(CGM);
- return new CGObjCGCC(CGM);
+
+ case ObjCRuntime::GCC:
+ return new CGObjCGCC(CGM);
+
+ case ObjCRuntime::ObjFW:
+ return new CGObjCObjFW(CGM);
+
+ case ObjCRuntime::FragileMacOSX:
+ case ObjCRuntime::MacOSX:
+ case ObjCRuntime::iOS:
+ llvm_unreachable("these runtimes are not GNU runtimes");
+ }
+ llvm_unreachable("bad runtime");
}
OpenPOWER on IntegriCloud