diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1642e2d3ee3b..12900e8b9d3a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -82,6 +82,7 @@ RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, LValue CodeGenFunction::EmitLValue(const Expr *E) { switch (E->getStmtClass()) { default: { + printf("Statement class: %d\n", E->getStmtClass()); WarnUnsupported(E, "l-value expression"); llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); return LValue::MakeAddr(llvm::UndefValue::get(Ty)); @@ -94,6 +95,9 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitPreDefinedLValue(cast(E)); case Expr::StringLiteralClass: return EmitStringLiteralLValue(cast(E)); + + case Expr::ObjCIvarRefExprClass: + return EmitObjCIvarRefLValue(cast(E)); case Expr::UnaryOperatorClass: return EmitUnaryOpLValue(cast(E)); @@ -555,6 +559,41 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { return LValue::MakeAddr(RV.getAggregateAddr()); } +LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { + // Objective-C objects are traditionally C structures with their layout + // defined at compile-time. In some implementations, their layout is not + // defined until run time in order to allow instance variables to be added to + // a class without recompiling all of the subclasses. If this is the case + // then the CGObjCRuntime subclass must return true to LateBoundIvars and + // implement the lookup itself. + if(CGM.getObjCRuntime()->LateBoundIVars()) { + assert(0 && "FIXME: Implement support for late-bound instance variables"); + return LValue(); // Not reached. + } + else { + // Get a structure type for the object + QualType ExprTy = E->getBase()->getType(); + const llvm::Type *ObjectType = ConvertType(ExprTy); + //TODO: Add a special case for isa (index 0) + // Work out which index the ivar is + const ObjCIvarDecl *Decl = E->getDecl(); + unsigned Index = CGM.getTypes().getLLVMFieldNo(Decl); + + // Get object pointer + llvm::Value * Object = EmitLValue(E->getBase()).getAddress(); + // Coerce object pointer to correct type. + if (Object->getType() != ObjectType) { + Object = Builder.CreateBitCast(Object, ObjectType); + } + // Get the correct element + llvm::Value * Element = Builder.CreateStructGEP(Object, + Index, + Decl->getName()); + // Element = Builder.CreateLoad(Element); + return LValue::MakeAddr(Element); + } +} + RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, Expr *const *ArgExprs, unsigned NumArgs) { // The callee type will always be a pointer to function type, get the function diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 2d42f8f812a0..6c5326105fea 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -19,6 +19,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" #include "llvm/Support/Compiler.h" +#include "llvm/ValueSymbolTable.h" #include using namespace clang; @@ -126,6 +127,7 @@ public: return EmitLoadOfLValue(E); } Value *VisitObjCMessageExpr(ObjCMessageExpr *E); + Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); Value *VisitMemberExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitOCUVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } @@ -449,6 +451,10 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) { return llvm::UndefValue::get(CGF.ConvertType(E->getType())); } +Value *ScalarExprEmitter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + return Builder.CreateLoad(CGF.EmitObjCIvarRefLValue(E).getAddress()); +} + Value *ScalarExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { // Only the lookup mechanism and first two arguments of the method // implementation vary between runtimes. We can get the receiver and @@ -481,11 +487,13 @@ Value *ScalarExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { // Get the selector string std::string SelStr = E->getSelector().getName(); llvm::Constant *Selector = CGF.CGM.GetAddrOfConstantString(SelStr); - ConvertType(E->getType()); + + llvm::Value *SelPtr = Builder.CreateStructGEP(Selector, 0); return Runtime->generateMessageSend(Builder, ConvertType(E->getType()), + CGF.CurFn->getValueSymbolTable().lookup("self"), Receiver, - Selector, + SelPtr, &Args[0], Args.size()); } diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 33419a3d51d3..7894e83c0588 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -23,3 +23,4 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){ return CGM.GetAddrOfConstantCFString(S); } + diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 1cc5cffb82ae..dd0eaa3b7c3e 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -1,4 +1,4 @@ -//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// +//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// // // The LLVM Compiler Infrastructure // @@ -17,60 +17,124 @@ #include "llvm/Support/LLVMBuilder.h" #include "llvm/ADT/SmallVector.h" -using namespace clang::CodeGen; -using namespace clang; -CGObjCRuntime::~CGObjCRuntime() {} +clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {} namespace { -class CGObjCGNU : public CGObjCRuntime { +class CGObjCGNU : public clang::CodeGen::CGObjCRuntime { private: llvm::Module &TheModule; + const llvm::Type *SelectorTy; + const llvm::Type *PtrToInt8Ty; + const llvm::Type *IMPTy; + const llvm::Type *IdTy; + const llvm::Type *IntTy; + const llvm::Type *PtrTy; + const llvm::Type *LongTy; + const llvm::Type *PtrToIntTy; public: - CGObjCGNU(llvm::Module &M) : TheModule(M) {}; + CGObjCGNU(llvm::Module &Mp, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType); virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, const llvm::Type *ReturnTy, + llvm::Value *Sender, llvm::Value *Receiver, - llvm::Constant *Selector, + llvm::Value *Selector, llvm::Value** ArgV, unsigned ArgC); + llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder, + llvm::Value *SelName, + llvm::Value *SelTypes); + virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy, + const llvm::Type *SelfTy, + const llvm::Type **ArgTy, + unsigned ArgC, + bool isVarArg); }; } // end anonymous namespace -// Generate code for a message send expression on the GNU runtime. -// BIG FAT WARNING: Much of this code will need factoring out later. -// FIXME: This currently only handles id returns. Other return types -// need some explicit casting. +CGObjCGNU::CGObjCGNU(llvm::Module &M, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType) : + TheModule(M), + IntTy(LLVMIntType), + LongTy(LLVMLongType) +{ + // C string type. Used in lots of places. + PtrToInt8Ty = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + // Get the selector Type. + const llvm::Type *SelStructTy = llvm::StructType::get( + PtrToInt8Ty, + PtrToInt8Ty, + NULL); + SelectorTy = llvm::PointerType::getUnqual(SelStructTy); + PtrToIntTy = llvm::PointerType::getUnqual(IntTy); + PtrTy = PtrToInt8Ty; + + // Object type + llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get(); + llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy); + IdTy = llvm::StructType::get(OpaqueIdTy, NULL); + llvm::cast(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy); + IdTy = llvm::cast(OpaqueObjTy.get()); + IdTy = llvm::PointerType::getUnqual(IdTy); + + // IMP type + std::vector IMPArgs; + IMPArgs.push_back(IdTy); + IMPArgs.push_back(SelectorTy); + IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); + +} + +/// Looks up the selector for the specified name / type pair. +// FIXME: Selectors should be statically cached, not looked up on every call. +llvm::Value *CGObjCGNU::getSelector(llvm::LLVMFoldingBuilder &Builder, + llvm::Value *SelName, + llvm::Value *SelTypes) +{ + // Look up the selector. + llvm::Value *cmd; + if(SelTypes == 0) { + llvm::Constant *SelFunction = TheModule.getOrInsertFunction("sel_get_uid", + SelectorTy, + PtrToInt8Ty, + NULL); + cmd = Builder.CreateCall(SelFunction, SelName); + } + else { + llvm::Constant *SelFunction = + TheModule.getOrInsertFunction("sel_get_typed_uid", + SelectorTy, + PtrToInt8Ty, + PtrToInt8Ty, + NULL); + llvm::Value *Args[] = { SelName, SelTypes }; + cmd = Builder.CreateCall(SelFunction, Args, Args+2); + } + return cmd; +} + + +/// Generate code for a message send expression on the GNU runtime. +// FIXME: Much of this code will need factoring out later. +// TODO: This should take a sender argument (pointer to self in the calling +// context) llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, const llvm::Type *ReturnTy, + llvm::Value *Sender, llvm::Value *Receiver, - llvm::Constant *Selector, + llvm::Value *Selector, llvm::Value** ArgV, unsigned ArgC) { - // Get the selector Type. - const llvm::Type *PtrToInt8Ty = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - const llvm::Type *SelStructTy = - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL); - const llvm::Type *SelTy = llvm::PointerType::getUnqual(SelStructTy); - - // Look up the selector. - // If we haven't got the selector lookup function, look it up now. - // TODO: Factor this out and use it to implement @selector() too. - llvm::Constant *SelFunction = - TheModule.getOrInsertFunction("sel_get_uid", SelTy, PtrToInt8Ty, NULL); - // FIXME: Selectors should be statically cached, not looked up on every call. - - // TODO: Pull this out into the caller. - llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); - llvm::Constant *Ops[] = {Idx0, Idx0}; - llvm::Value *SelStr = llvm::ConstantExpr::getGetElementPtr(Selector, Ops, 2); - llvm::Value *cmd = Builder.CreateCall(SelFunction, &SelStr, &SelStr+1); + llvm::Value *cmd = getSelector(Builder, Selector, 0); // Look up the method implementation. std::vector impArgTypes; impArgTypes.push_back(Receiver->getType()); - impArgTypes.push_back(SelTy); + impArgTypes.push_back(SelectorTy); // Avoid an explicit cast on the IMP by getting a version that has the right // return type. @@ -79,8 +143,8 @@ llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, llvm::Constant *lookupFunction = TheModule.getOrInsertFunction("objc_msg_lookup", - llvm::PointerType::get(impType, 0), - Receiver->getType(), SelTy, NULL); + llvm::PointerType::getUnqual(impType), + Receiver->getType(), SelectorTy, NULL); llvm::SmallVector lookupArgs; lookupArgs.push_back(Receiver); lookupArgs.push_back(cmd); @@ -92,6 +156,35 @@ llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end()); } -CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) { - return new CGObjCGNU(M); +llvm::Function *CGObjCGNU::MethodPreamble( + const llvm::Type *ReturnTy, + const llvm::Type *SelfTy, + const llvm::Type **ArgTy, + unsigned ArgC, + bool isVarArg) { + std::vector Args; + Args.push_back(SelfTy); + Args.push_back(SelectorTy); + Args.insert(Args.end(), ArgTy, ArgTy+ArgC); + + llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy, + Args, + isVarArg); + llvm::Function *Method = new llvm::Function(MethodTy, + llvm::GlobalValue::InternalLinkage, + ".objc.method", + &TheModule); + // Set the names of the hidden arguments + llvm::Function::arg_iterator AI = Method->arg_begin(); + AI->setName("self"); + ++AI; + AI->setName("_cmd"); + return Method; +} + +clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime( + llvm::Module &M, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType) { + return new CGObjCGNU(M, LLVMIntType, LLVMLongType); } diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index d8fc60f99c0b..749984d9f17d 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -22,8 +22,10 @@ namespace llvm { class Type; class Value; class Module; + class Function; } + namespace clang { namespace CodeGen { @@ -32,16 +34,35 @@ class CGObjCRuntime { public: virtual ~CGObjCRuntime(); - // Generate an Objective-C message send operation + /// Generate an Objective-C message send operation virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, const llvm::Type *ReturnTy, + llvm::Value *Sender, llvm::Value *Receiver, - llvm::Constant *Selector, + llvm::Value *Selector, llvm::Value** ArgV, unsigned ArgC) = 0; + /// Generate the function required to register all Objective-C components in + /// this compilation unit with the runtime library. + virtual llvm::Function *ModuleInitFunction() { return 0; } + /// Generate a function preamble for a method with the specified types + virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy, + const llvm::Type *SelfTy, + const llvm::Type **ArgTy, + unsigned ArgC, + bool isVarArg) = 0; + /// If instance variable addresses are determined at runtime then this should + /// return true, otherwise instance variables will be accessed directly from + /// the structure. If this returns true then @defs is invalid for this + /// runtime and a warning should be generated. + virtual bool LateBoundIVars() { return false; } }; -CGObjCRuntime *CreateObjCRuntime(llvm::Module &M); +/// Creates an instance of an Objective-C runtime class. +//TODO: This should include some way of selecting which runtime to target. +CGObjCRuntime *CreateObjCRuntime(llvm::Module &M, + const llvm::Type *LLVMIntType, + const llvm::Type *LLVMLongType); } } #endif diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 5fdc61b46f88..df62e4aa1d07 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -332,9 +332,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // Emit the result value, even if unused, to evalute the side effects. const Expr *RV = S.getRetValue(); - QualType FnRetTy = CurFuncDecl->getType().getCanonicalType(); - FnRetTy = cast(FnRetTy)->getResultType(); - if (FnRetTy->isVoidType()) { // If the function returns void, emit ret void. Builder.CreateRetVoid(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 49f23f27c346..3e811a73b71d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -26,7 +26,7 @@ using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL), - CaseRangeBlock(NULL) {} + CaseRangeBlock(NULL) {} ASTContext &CodeGenFunction::getContext() const { return CGM.getContext(); @@ -55,6 +55,80 @@ bool CodeGenFunction::hasAggregateLLVMType(QualType T) { !T->isVoidType() && !T->isVectorType() && !T->isFunctionType(); } +/// Generate an Objective-C method. An Objective-C method is a C function with +/// its pointer, name, and types registered in the class struture. +// FIXME: This method contains a lot of code copied and pasted from +// GenerateCode. This should be factored out. +void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { + llvm::SmallVector ParamTypes; + for (unsigned i=0 ; iparam_size() ; i++) { + ParamTypes.push_back(ConvertType(OMD->getParamDecl(i)->getType())); + } + CurFn = CGM.getObjCRuntime()->MethodPreamble(ConvertType(OMD->getResultType()), + llvm::PointerType::getUnqual(llvm::Type::Int32Ty), + ParamTypes.begin(), + OMD->param_size(), + OMD->isVariadic()); + llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn); + + // Create a marker to make it easy to insert allocas into the entryblock + // later. Don't create this with the builder, because we don't want it + // folded. + llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty); + AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt", + EntryBB); + + FnRetTy = OMD->getResultType(); + + Builder.SetInsertPoint(EntryBB); + + // Emit allocs for param decls. Give the LLVM Argument nodes names. + llvm::Function::arg_iterator AI = CurFn->arg_begin(); + + // Name the struct return argument. + // FIXME: Probably should be in the runtime, or it will trample the other + // hidden arguments. + if (hasAggregateLLVMType(OMD->getResultType())) { + AI->setName("agg.result"); + ++AI; + } + + // Add implicit parameters to the decl map. + // TODO: Add something to AST to let the runtime specify the names and types + // of these. + llvm::Value *&DMEntry = LocalDeclMap[&(*OMD->getSelfDecl())]; + DMEntry = AI; + ++AI; ++AI; + + + for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i, ++AI) { + assert(AI != CurFn->arg_end() && "Argument mismatch!"); + EmitParmDecl(*OMD->getParamDecl(i), AI); + } + + // Emit the function body. + EmitStmt(OMD->getBody()); + + // Emit a return for code that falls off the end. If insert point + // is a dummy block with no predecessors then remove the block itself. + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (isDummyBlock(BB)) + BB->eraseFromParent(); + else { + if (CurFn->getReturnType() == llvm::Type::VoidTy) + Builder.CreateRetVoid(); + else + Builder.CreateRet(llvm::UndefValue::get(CurFn->getReturnType())); + } + assert(BreakContinueStack.empty() && + "mismatched push/pop in break/continue stack!"); + + // Remove the AllocaInsertPt instruction, which is just a convenience for us. + AllocaInsertPt->eraseFromParent(); + AllocaInsertPt = 0; + // Verify that the function is well formed. + assert(!verifyFunction(*CurFn) && "Generated method is not well formed."); +} void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { LLVMIntTy = ConvertType(getContext().IntTy); @@ -62,6 +136,9 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy))); CurFuncDecl = FD; + FnRetTy = CurFuncDecl->getType()->getAsFunctionType()->getResultType(); + + CurFn = cast(CGM.GetAddrOfFunctionDecl(FD, true)); assert(CurFn->isDeclaration() && "Function already has body?"); @@ -144,7 +221,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { AllocaInsertPt = 0; // Verify that the function is well formed. - assert(!verifyFunction(*CurFn)); + assert(!verifyFunction(*CurFn) && "Generated function is not well formed."); } /// isDummyBlock - Return true if BB is an empty basic block diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 509e8296d20c..121b7953bdc1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -14,6 +14,7 @@ #ifndef CLANG_CODEGEN_CODEGENFUNCTION_H #define CLANG_CODEGEN_CODEGENFUNCTION_H +#include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/LLVMBuilder.h" @@ -27,8 +28,8 @@ namespace clang { class ASTContext; class Decl; class FunctionDecl; + class ObjCMethodDecl; class TargetInfo; - class QualType; class FunctionTypeProto; class Stmt; @@ -66,6 +67,7 @@ namespace clang { class ChooseExpr; class PreDefinedExpr; class ObjCStringLiteral; + class ObjCIvarRefExpr; class MemberExpr; class BlockVarDecl; @@ -245,6 +247,7 @@ public: llvm::LLVMFoldingBuilder Builder; const FunctionDecl *CurFuncDecl; + QualType FnRetTy; llvm::Function *CurFn; /// AllocaInsertPoint - This is an instruction in the entry block before which @@ -286,6 +289,7 @@ public: ASTContext &getContext() const; + void GenerateObjCMethod(const ObjCMethodDecl *OMD); void GenerateCode(const FunctionDecl *FD); const llvm::Type *ConvertType(QualType T); @@ -422,7 +426,8 @@ public: LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field, bool isUnion); - + + LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E); //===--------------------------------------------------------------------===// // Scalar Expression Emission //===--------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b5d9db98ef9e..8374f2bab6c0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -34,10 +34,16 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO, : Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags), Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) { //TODO: Make this selectable at runtime - Runtime = CreateObjCRuntime(M); + Runtime = CreateObjCRuntime(M, + getTypes().ConvertType(getContext().IntTy), + getTypes().ConvertType(getContext().LongTy)); } CodeGenModule::~CodeGenModule() { + llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction(); + if (ObjCInitFunction) { + AddGlobalCtor(ObjCInitFunction); + } EmitGlobalCtors(); delete Runtime; } @@ -70,7 +76,10 @@ void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor) { GlobalCtors.push_back(Ctor); } +/// EmitGlobalCtors - Generates the array of contsturctor functions to be +/// called on module load, if any have been registered with AddGlobalCtor. void CodeGenModule::EmitGlobalCtors() { + if (GlobalCtors.empty()) return; // Get the type of @llvm.global_ctors std::vector CtorFields; CtorFields.push_back(llvm::IntegerType::get(32)); @@ -114,6 +123,8 @@ void CodeGenModule::EmitGlobalCtors() { } + + /// ReplaceMapValuesWith - This is a really slow and bad function that /// searches for any entries in GlobalDeclMap that point to OldVal, changing /// them to point to NewVal. This is badbadbad, FIXME! @@ -263,6 +274,12 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, } +void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) { + // If this is not a prototype, emit the body. + if (OMD->getBody()) + CodeGenFunction(*this).GenerateObjCMethod(OMD); +} + void CodeGenModule::EmitFunction(const FunctionDecl *FD) { // If this is not a prototype, emit the body. if (FD->getBody()) diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index cbea09fd3ec4..553b36677620 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -30,6 +30,7 @@ namespace llvm { namespace clang { class ASTContext; class FunctionDecl; + class ObjCMethodDecl; class Decl; class Expr; class Stmt; @@ -100,6 +101,7 @@ public: void AddGlobalCtor(llvm::Function * Ctor); void EmitGlobalCtors(void); + void EmitObjCMethod(const ObjCMethodDecl *OMD); void EmitFunction(const FunctionDecl *FD); void EmitGlobalVar(const FileVarDecl *D); void EmitGlobalVarDeclarator(const FileVarDecl *D); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 65c5757edbd3..afa20e411071 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -144,7 +144,22 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { cast(OpaqueHolder.get())->refineAbstractTypeTo(NT); } - +/// Produces a vector containing the all of the instance variables in an +/// Objective-C object, in the order that they appear. Used to create LLVM +/// structures corresponding to Objective-C objects. +void CodeGenTypes::CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass, + std::vector &IvarTypes) { + ObjCInterfaceDecl *SuperClass = ObjCClass->getSuperClass(); + if(SuperClass) { + CollectObjCIvarTypes(SuperClass, IvarTypes); + } + for(ObjCInterfaceDecl::ivar_iterator ivar=ObjCClass->ivar_begin() ; + ivar != ObjCClass->ivar_end() ; + ivar++) { + IvarTypes.push_back(ConvertType((*ivar)->getType())); + ObjCIvarInfo[*ivar] = IvarTypes.size() - 1; + } +} const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const clang::Type &Ty = *T.getCanonicalType(); @@ -263,9 +278,21 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case Type::ASQual: return ConvertType(QualType(cast(Ty).getBaseType(), 0)); - case Type::ObjCInterface: - assert(0 && "FIXME: add missing functionality here"); - break; + case Type::ObjCInterface: { + // Warning: Use of this is strongly discouraged. Late binding of instance + // variables is supported on some runtimes and so using static binding can + // break code when libraries are updated. Only use this if you have + // previously checked that the ObjCRuntime subclass in use does not support + // late-bound ivars. + ObjCInterfaceType OIT = cast(Ty); + std::vector IvarTypes; + // Pointer to the class. This is just a placeholder. Operations that + // actually use the isa pointer should cast it to the Class type provided + // by the runtime. + IvarTypes.push_back(llvm::PointerType::getUnqual(llvm::Type::Int8Ty)); + CollectObjCIvarTypes(OIT.getDecl(), IvarTypes); + return llvm::StructType::get(IvarTypes); + } case Type::ObjCQualifiedInterface: assert(0 && "FIXME: add missing functionality here"); @@ -399,6 +426,13 @@ unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) { return I->second; } +unsigned CodeGenTypes::getLLVMFieldNo(const ObjCIvarDecl *OID) { + llvm::DenseMap::iterator + I = ObjCIvarInfo.find(OID); + assert (I != ObjCIvarInfo.end() && "Unable to find field info"); + return I->second; +} + /// addFieldInfo - Assign field number to field FD. void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) { FieldInfo[FD] = No; diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index 08a2467106aa..f1a680c46f64 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -34,6 +34,8 @@ namespace clang { class FunctionTypeProto; class FieldDecl; class RecordDecl; + class ObjCInterfaceDecl; + class ObjCIvarDecl; namespace CodeGen { class CodeGenTypes; @@ -86,6 +88,7 @@ class CodeGenTypes { /// FieldInfo - This maps struct field with corresponding llvm struct type /// field no. This info is populated by record organizer. llvm::DenseMap FieldInfo; + llvm::DenseMap ObjCIvarInfo; public: class BitFieldInfo { @@ -128,12 +131,15 @@ public: /// memory representation is usually i8 or i32, depending on the target. const llvm::Type *ConvertTypeForMem(QualType T); + void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass, + std::vector &IvarTypes); const CGRecordLayout *getCGRecordLayout(const TagDecl*) const; /// getLLVMFieldNo - Return llvm::StructType element number /// that corresponds to the field FD. unsigned getLLVMFieldNo(const FieldDecl *FD); + unsigned getLLVMFieldNo(const ObjCIvarDecl *OID); /// UpdateCompletedType - When we find the full definition for a TagDecl, diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 06467488a5e9..5710d8bf9801 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -65,6 +65,10 @@ namespace { Builder->EmitFunction(FD); } else if (FileVarDecl *FVD = dyn_cast(D)) { Builder->EmitGlobalVarDeclarator(FVD); + } else if (isa(D) || isa(D)) { + // Forward declaration. Only used for type checking. + } else if (ObjCMethodDecl *OMD = dyn_cast(D)){ + Builder->EmitObjCMethod(OMD); } else if (LinkageSpecDecl *LSD = dyn_cast(D)) { if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx) Builder->WarnUnsupported(LSD, "linkage spec");