/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
-void CodeGenFunction::EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg) {
+void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
+ // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
+ assert(isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) &&
+ "Invalid argument to EmitParmDecl");
QualType Ty = D.getType();
llvm::Value *DeclPtr;
// Emit allocs for param decls. Give the LLVM Argument nodes names.
llvm::Function::arg_iterator AI = CurFn->arg_begin();
+ // Name the struct return argument.
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 *&SelfEntry = LocalDeclMap[OMD->getSelfDecl()];
- const llvm::Type *IPTy = AI->getType();
- llvm::Value *DeclPtr = new llvm::AllocaInst(IPTy, 0, AI->getName() +
- ".addr", AllocaInsertPt);
- // Store the initial value into the alloca.
- Builder.CreateStore(AI, DeclPtr);
- SelfEntry = DeclPtr;
+ EmitParmDecl(*OMD->getSelfDecl(), AI);
+ ++AI;
+
+ EmitParmDecl(*OMD->getCmdDecl(), AI);
++AI;
- llvm::Value *&CmdEntry = LocalDeclMap[OMD->getCmdDecl()];
- IPTy = AI->getType();
- DeclPtr = new llvm::AllocaInst(IPTy, 0, AI->getName() +
- ".addr", AllocaInsertPt);
- // Store the initial value into the alloca.
- Builder.CreateStore(AI, DeclPtr);
- CmdEntry = DeclPtr;
for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i, ++AI) {
assert(AI != CurFn->arg_end() && "Argument mismatch!");
EmitParmDecl(*OMD->getParamDecl(i), AI);
}
-
+ assert(AI == CurFn->arg_end() && "Argument mismatch");
+
GenerateFunction(OMD->getBody());
}
-llvm::Value *CodeGenFunction::LoadObjCSelf(void)
-{
- if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurFuncDecl)) {
- ValueDecl *Decl = OMD->getSelfDecl();
- llvm::Value *SelfPtr = LocalDeclMap[&(*(Decl))];
- return Builder.CreateLoad(SelfPtr, "self");
- }
- return NULL;
+llvm::Value *CodeGenFunction::LoadObjCSelf(void) {
+ const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
+ return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
}
CGObjCRuntime::~CGObjCRuntime() {}
llvm::GlobalValue::InternalLinkage,
FunctionName,
&TheModule);
- llvm::Function::arg_iterator AI = Method->arg_begin();
- // Name the struct return argument.
- // FIXME: This is probably the wrong test.
- if (!ReturnTy->isFirstClassType() && ReturnTy != llvm::Type::VoidTy) {
- AI->setName("agg.result");
- ++AI;
- }
- AI->setName("self");
- ++AI;
- AI->setName("_cmd");
return Method;
}
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Target/TargetData.h"
+#include <sstream>
using namespace clang;
/// the name.
llvm::Constant *GetMethodVarType(ObjCMethodDecl *D);
+ /// GetNameForMethod - Return a name for the given method.
+ /// \param[out] NameOut - The return value.
+ void GetNameForMethod(const ObjCMethodDecl *OMD,
+ std::string &NameOut);
+
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const std::string &String);
}
void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ClassDecl) {
- assert(0 && "Cannot generate class for Mac runtime.");
+ //assert(0 && "Cannot generate class for Mac runtime.");
+}
+
+llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) {
+ const llvm::Type *ReturnTy =
+ CGM.getTypes().ConvertReturnType(OMD->getResultType());
+ const llvm::Type *SelfTy =
+ CGM.getTypes().ConvertType(OMD->getSelfDecl()->getType());
+
+ std::vector<const llvm::Type*> ArgTys;
+ ArgTys.reserve(1 + 2 + OMD->param_size());
+
+ // FIXME: This is not something we should have to be dealing with
+ // here.
+ bool useStructRet =
+ CodeGen::CodeGenFunction::hasAggregateLLVMType(OMD->getResultType());
+ if (useStructRet) {
+ ArgTys.push_back(llvm::PointerType::getUnqual(ReturnTy));
+ ReturnTy = llvm::Type::VoidTy;
+ }
+
+ // Implicit arguments
+ ArgTys.push_back(SelfTy);
+ ArgTys.push_back(ObjCTypes.SelectorPtrTy);
+
+ for (ObjCMethodDecl::param_const_iterator
+ i = OMD->param_begin(), e = OMD->param_end();
+ i != e; ++i) {
+ const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
+ if (Ty->isFirstClassType()) {
+ ArgTys.push_back(Ty);
+ } else {
+ ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
+ }
+ }
+
+ std::string Name;
+ GetNameForMethod(OMD, Name);
+
+ llvm::Function *Method =
+ llvm::Function::Create(llvm::FunctionType::get(ReturnTy,
+ ArgTys,
+ OMD->isVariadic()),
+ llvm::GlobalValue::InternalLinkage,
+ Name,
+ &CGM.getModule());
+
+ if (useStructRet)
+ Method->addParamAttr(1, llvm::ParamAttr::StructRet);
+
+ return Method;
}
llvm::Function *CGObjCMac::ModuleInitFunction() {
return NULL;
}
-llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) {
- assert(0 && "Cannot generate method preamble for Mac runtime.");
- return 0;
-}
-
/* *** Private Interface *** */
/// EmitImageInfo - Emit the image info marker used to encode some module
return getConstantGEP(Entry, 0, 0);
}
+void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D,
+ std::string &NameOut) {
+ // FIXME: Find the mangling GCC uses.
+ std::stringstream s;
+ s << (D->isInstance() ? "-" : "+");
+ s << "[";
+ s << D->getClassInterface()->getName();
+ s << " ";
+ s << D->getSelector().getName();
+ s << "]";
+ NameOut = s.str();
+}
+
void CGObjCMac::FinishModule() {
EmitModuleInfo();
const llvm::Type *ConvertType(QualType T);
+ /// LoadObjCSelf - Load the value of self. This function is only
+ /// valid while generating code for an Objective-C method.
llvm::Value *LoadObjCSelf();
/// isObjCPointerType - Return true if the specificed AST type will map onto
void EmitBlockVarDecl(const VarDecl &D);
void EmitLocalBlockVarDecl(const VarDecl &D);
void EmitStaticBlockVarDecl(const VarDecl &D);
- void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg);
+
+ /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
+ void EmitParmDecl(const VarDecl &D, llvm::Value *Arg);
//===--------------------------------------------------------------------===//
// Statement Emission
gv->setSection("llvm.metadata");
}
-bool hasAggregateLLVMType(QualType T) {
- return !T->isRealType() && !T->isPointerLikeType() &&
- !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
-}
-
void CodeGenModule::SetGlobalValueAttributes(const FunctionDecl *FD,
llvm::GlobalValue *GV) {
// TODO: Set up linkage and many other things. Note, this is a simple
if (FuncAttrs)
ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(0, FuncAttrs));
// Note that there is parallel code in CodeGenFunction::EmitCallExpr
- bool AggregateReturn = hasAggregateLLVMType(FD->getResultType());
+ bool AggregateReturn = CodeGenFunction::hasAggregateLLVMType(FD->getResultType());
if (AggregateReturn)
ParamAttrList.push_back(
llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet));