[cfe-commits] r48969 - in /cfe/trunk/lib/CodeGen: CGExpr.cpp CGExprScalar.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCRuntime.h CGStmt.cpp CodeGenFunction.cpp CodeGenFunction.h CodeGenModule.cpp CodeGenModule.h CodeGenTypes.cpp CodeGenTypes.h ModuleBuilder.cpp
Chris Lattner
sabre at nondot.org
Sun Mar 30 16:03:08 PDT 2008
Author: lattner
Date: Sun Mar 30 18:03:07 2008
New Revision: 48969
URL: http://llvm.org/viewvc/llvm-project?rev=48969&view=rev
Log:
Add initial support for objc codegen for methods, ivars, and the
etoile runtime, patch by David Chisnall!
Modified:
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCRuntime.h
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.h
cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Mar 30 18:03:07 2008
@@ -82,6 +82,7 @@
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 @@
return EmitPreDefinedLValue(cast<PreDefinedExpr>(E));
case Expr::StringLiteralClass:
return EmitStringLiteralLValue(cast<StringLiteral>(E));
+
+ case Expr::ObjCIvarRefExprClass:
+ return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
case Expr::UnaryOperatorClass:
return EmitUnaryOpLValue(cast<UnaryOperator>(E));
@@ -555,6 +559,41 @@
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
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Mar 30 18:03:07 2008
@@ -19,6 +19,7 @@
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/ValueSymbolTable.h"
#include <cstdarg>
using namespace clang;
@@ -126,6 +127,7 @@
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 @@
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 @@
// 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());
}
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Mar 30 18:03:07 2008
@@ -23,3 +23,4 @@
return CGM.GetAddrOfConstantCFString(S);
}
+
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sun Mar 30 18:03:07 2008
@@ -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<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
+ IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
+ IdTy = llvm::PointerType::getUnqual(IdTy);
+
+ // IMP type
+ std::vector<const llvm::Type*> 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<const llvm::Type*> 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::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<llvm::Value*, 16> lookupArgs;
lookupArgs.push_back(Receiver);
lookupArgs.push_back(cmd);
@@ -92,6 +156,35 @@
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<const llvm::Type*> 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);
}
Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Sun Mar 30 18:03:07 2008
@@ -22,8 +22,10 @@
class Type;
class Value;
class Module;
+ class Function;
}
+
namespace clang {
namespace CodeGen {
@@ -32,16 +34,35 @@
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
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sun Mar 30 18:03:07 2008
@@ -332,9 +332,6 @@
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
- QualType FnRetTy = CurFuncDecl->getType().getCanonicalType();
- FnRetTy = cast<FunctionType>(FnRetTy)->getResultType();
-
if (FnRetTy->isVoidType()) {
// If the function returns void, emit ret void.
Builder.CreateRetVoid();
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Mar 30 18:03:07 2008
@@ -26,7 +26,7 @@
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 @@
!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<const llvm::Type *, 16> ParamTypes;
+ for (unsigned i=0 ; i<OMD->param_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 @@
getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));
CurFuncDecl = FD;
+ FnRetTy = CurFuncDecl->getType()->getAsFunctionType()->getResultType();
+
+
CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
assert(CurFn->isDeclaration() && "Function already has body?");
@@ -144,7 +221,7 @@
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
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun Mar 30 18:03:07 2008
@@ -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 @@
class ASTContext;
class Decl;
class FunctionDecl;
+ class ObjCMethodDecl;
class TargetInfo;
- class QualType;
class FunctionTypeProto;
class Stmt;
@@ -66,6 +67,7 @@
class ChooseExpr;
class PreDefinedExpr;
class ObjCStringLiteral;
+ class ObjCIvarRefExpr;
class MemberExpr;
class BlockVarDecl;
@@ -245,6 +247,7 @@
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 @@
ASTContext &getContext() const;
+ void GenerateObjCMethod(const ObjCMethodDecl *OMD);
void GenerateCode(const FunctionDecl *FD);
const llvm::Type *ConvertType(QualType T);
@@ -422,7 +426,8 @@
LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
bool isUnion);
-
+
+ LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Mar 30 18:03:07 2008
@@ -34,10 +34,16 @@
: 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 @@
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<const llvm::Type*> CtorFields;
CtorFields.push_back(llvm::IntegerType::get(32));
@@ -114,6 +123,8 @@
}
+
+
/// 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 @@
}
+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())
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun Mar 30 18:03:07 2008
@@ -30,6 +30,7 @@
namespace clang {
class ASTContext;
class FunctionDecl;
+ class ObjCMethodDecl;
class Decl;
class Expr;
class Stmt;
@@ -100,6 +101,7 @@
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);
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sun Mar 30 18:03:07 2008
@@ -144,7 +144,22 @@
cast<llvm::OpaqueType>(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<const llvm::Type*> &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 @@
case Type::ASQual:
return ConvertType(QualType(cast<ASQualType>(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<ObjCInterfaceType>(Ty);
+ std::vector<const llvm::Type*> 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 @@
return I->second;
}
+unsigned CodeGenTypes::getLLVMFieldNo(const ObjCIvarDecl *OID) {
+ llvm::DenseMap<const ObjCIvarDecl*, unsigned>::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;
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Sun Mar 30 18:03:07 2008
@@ -34,6 +34,8 @@
class FunctionTypeProto;
class FieldDecl;
class RecordDecl;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
namespace CodeGen {
class CodeGenTypes;
@@ -86,6 +88,7 @@
/// FieldInfo - This maps struct field with corresponding llvm struct type
/// field no. This info is populated by record organizer.
llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
+ llvm::DenseMap<const ObjCIvarDecl *, unsigned> ObjCIvarInfo;
public:
class BitFieldInfo {
@@ -128,12 +131,15 @@
/// memory representation is usually i8 or i32, depending on the target.
const llvm::Type *ConvertTypeForMem(QualType T);
+ void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
+ std::vector<const llvm::Type*> &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,
Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=48969&r1=48968&r2=48969&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Sun Mar 30 18:03:07 2008
@@ -65,6 +65,10 @@
Builder->EmitFunction(FD);
} else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
Builder->EmitGlobalVarDeclarator(FVD);
+ } else if (isa<ObjCClassDecl>(D) || isa<ObjCCategoryDecl>(D)) {
+ // Forward declaration. Only used for type checking.
+ } else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){
+ Builder->EmitObjCMethod(OMD);
} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx)
Builder->WarnUnsupported(LSD, "linkage spec");
More information about the cfe-commits
mailing list