aboutsummaryrefslogtreecommitdiff
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.cpp156
1 files changed, 110 insertions, 46 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index 6d129d02a561..68d234dde6ea 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -33,7 +33,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Target/TargetData.h"
+#include "llvm/DataLayout.h"
#include <cstdarg>
@@ -224,6 +224,25 @@ protected:
llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size());
return MakeGlobal(ArrayTy, V, Name, linkage);
}
+ /// Returns a property name and encoding string.
+ llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
+ const Decl *Container) {
+ ObjCRuntime R = CGM.getLangOpts().ObjCRuntime;
+ if ((R.getKind() == ObjCRuntime::GNUstep) &&
+ (R.getVersion() >= VersionTuple(1, 6))) {
+ std::string NameAndAttributes;
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
+ NameAndAttributes += '\0';
+ NameAndAttributes += TypeStr.length() + 3;
+ NameAndAttributes += TypeStr;
+ NameAndAttributes += '\0';
+ NameAndAttributes += PD->getNameAsString();
+ return llvm::ConstantExpr::getGetElementPtr(
+ CGM.GetAddrOfConstantString(NameAndAttributes), Zeros);
+ }
+ return MakeConstantString(PD->getNameAsString());
+ }
/// Ensures that the value has the required type, by inserting a bitcast if
/// required. This function lets us avoid inserting bitcasts that are
/// redundant.
@@ -514,7 +533,10 @@ public:
const CGBlockInfo &blockInfo) {
return NULLPtr;
}
-
+ virtual llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ return NULLPtr;
+ }
virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
return 0;
}
@@ -578,6 +600,8 @@ class CGObjCGNUstep : public CGObjCGNU {
/// Type of an slot structure pointer. This is returned by the various
/// lookup functions.
llvm::Type *SlotTy;
+ public:
+ virtual llvm::Constant *GetEHType(QualType T);
protected:
virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
llvm::Value *&Receiver,
@@ -653,11 +677,40 @@ 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.
+/// Support for the ObjFW runtime. Support here is due to
+/// Jonathan Schleifer <js@webkeks.org>, the ObjFW maintainer.
+class CGObjCObjFW: public CGObjCGNU {
+protected:
+ /// The GCC ABI message lookup function. Returns an IMP pointing to the
+ /// method implementation for this message.
+ LazyRuntimeFunction MsgLookupFn;
+ /// The GCC ABI superclass message lookup function. Takes a pointer to a
+ /// structure describing the receiver and the class, and a selector as
+ /// arguments. Returns the IMP for the corresponding method.
+ LazyRuntimeFunction MsgLookupSuperFn;
+
+ virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
+ llvm::Value *&Receiver,
+ llvm::Value *cmd,
+ llvm::MDNode *node) {
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *args[] = {
+ EnforceType(Builder, Receiver, IdTy),
+ EnforceType(Builder, cmd, SelectorTy) };
+ llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args);
+ imp->setMetadata(msgSendMDKind, node);
+ return imp.getInstruction();
+ }
+
+ virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
+ llvm::Value *ObjCSuper,
+ llvm::Value *cmd) {
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
+ PtrToObjCSuperTy), cmd};
+ return Builder.CreateCall(MsgLookupSuperFn, lookupArgs);
+ }
+
virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
const std::string &Name, bool isWeak) {
if (isWeak)
@@ -678,7 +731,13 @@ class CGObjCObjFW : public CGObjCGCC {
}
public:
- CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {}
+ CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
+ // IMP objc_msg_lookup(id, SEL);
+ MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL);
+ // IMP objc_msg_lookup_super(struct objc_super*, SEL);
+ MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
+ PtrToObjCSuperTy, SelectorTy, NULL);
+ }
};
} // end anonymous namespace
@@ -909,29 +968,30 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
}
llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
- if (!CGM.getLangOpts().CPlusPlus) {
- if (T->isObjCIdType()
- || T->isObjCQualifiedIdType()) {
- // With the old ABI, there was only one kind of catchall, which broke
- // 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().ObjCRuntime.isNonFragile()) {
- return MakeConstantString("@id");
- } else {
- return 0;
- }
- }
-
- // All other types should be Objective-C interface pointer types.
- const ObjCObjectPointerType *OPT =
- T->getAs<ObjCObjectPointerType>();
- assert(OPT && "Invalid @catch type.");
- const ObjCInterfaceDecl *IDecl =
- OPT->getObjectType()->getInterface();
- assert(IDecl && "Invalid @catch type.");
- return MakeConstantString(IDecl->getIdentifier()->getName());
+ if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
+ // With the old ABI, there was only one kind of catchall, which broke
+ // 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().ObjCRuntime.isNonFragile()) {
+ return MakeConstantString("@id");
+ } else {
+ return 0;
+ }
}
+
+ // All other types should be Objective-C interface pointer types.
+ const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>();
+ assert(OPT && "Invalid @catch type.");
+ const ObjCInterfaceDecl *IDecl = OPT->getObjectType()->getInterface();
+ assert(IDecl && "Invalid @catch type.");
+ return MakeConstantString(IDecl->getIdentifier()->getName());
+}
+
+llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
+ if (!CGM.getLangOpts().CPlusPlus)
+ return CGObjCGNU::GetEHType(T);
+
// For Objective-C++, we want to provide the ability to catch both C++ and
// Objective-C objects in the same function.
@@ -1436,7 +1496,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
Elements.push_back(Zero);
Elements.push_back(llvm::ConstantInt::get(LongTy, info));
if (isMeta) {
- llvm::TargetData td(&TheModule);
+ llvm::DataLayout td(&TheModule);
Elements.push_back(
llvm::ConstantInt::get(LongTy,
td.getTypeSizeInBits(ClassTy) /
@@ -1595,13 +1655,13 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
std::string TypeStr;
Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
- InstanceMethodNames.push_back(
- MakeConstantString((*iter)->getSelector().getAsString()));
- InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
- } else {
OptionalInstanceMethodNames.push_back(
MakeConstantString((*iter)->getSelector().getAsString()));
OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ InstanceMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
}
}
// Collect information about class methods:
@@ -1615,13 +1675,13 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
std::string TypeStr;
Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
- ClassMethodNames.push_back(
- MakeConstantString((*iter)->getSelector().getAsString()));
- ClassMethodTypes.push_back(MakeConstantString(TypeStr));
- } else {
OptionalClassMethodNames.push_back(
MakeConstantString((*iter)->getSelector().getAsString()));
OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ ClassMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
}
}
@@ -1656,7 +1716,9 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
std::vector<llvm::Constant*> Fields;
ObjCPropertyDecl *property = *iter;
- Fields.push_back(MakeConstantString(property->getNameAsString()));
+
+ Fields.push_back(MakePropertyEncodingString(property, PD));
+
Fields.push_back(llvm::ConstantInt::get(Int8Ty,
property->getPropertyAttributes()));
Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
@@ -1909,7 +1971,7 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Synthesize);
- Fields.push_back(MakeConstantString(property->getNameAsString()));
+ Fields.push_back(MakePropertyEncodingString(property, OID));
Fields.push_back(llvm::ConstantInt::get(Int8Ty,
property->getPropertyAttributes()));
Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized));
@@ -2011,7 +2073,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().ObjCRuntime.isNonFragile()) {
+ if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
instanceSize = 0 - (instanceSize - superInstanceSize);
}
@@ -2026,7 +2088,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().ObjCRuntime.isNonFragile()) {
+ if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
Offset = BaseOffset - superInstanceSize;
}
llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
@@ -2334,7 +2396,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
// Runtime version, used for ABI compatibility checking.
Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
// sizeof(ModuleTy)
- llvm::TargetData td(&TheModule);
+ llvm::DataLayout td(&TheModule);
Elements.push_back(
llvm::ConstantInt::get(LongTy,
td.getTypeSizeInBits(ModuleTy) /
@@ -2488,7 +2550,7 @@ void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
// Unlike the Apple non-fragile runtimes, which also uses
// unwind-based zero cost exceptions, the GNU Objective C runtime's
// EH support isn't a veneer over C++ EH. Instead, exception
- // objects are created by __objc_exception_throw and destroyed by
+ // objects are created by objc_exception_throw and destroyed by
// the personality function; this avoids the need for bracketing
// catch handlers with calls to __blah_begin_catch/__blah_end_catch
// (or even _Unwind_DeleteException), but probably doesn't
@@ -2513,7 +2575,9 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
ExceptionAsObject = CGF.ObjCEHValueStack.back();
}
ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
- CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ llvm::CallSite Throw =
+ CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ Throw.setDoesNotReturn();
CGF.Builder.CreateUnreachable();
CGF.Builder.ClearInsertionPoint();
}