forked from OSchip/llvm-project
Change self/_cmd to be instances of ImplicitParamDecl instead of ParmVarDecl.
Patch by David Chisnall! llvm-svn: 52422
This commit is contained in:
parent
5e4188f1ac
commit
5696e7badf
|
@ -1975,7 +1975,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
|||
llvm::SmallVector<Expr*, 4> InitExprs;
|
||||
|
||||
// set the receiver to self, the first argument to all methods.
|
||||
InitExprs.push_back(new DeclRefExpr(CurMethodDecl->getSelfDecl(),
|
||||
InitExprs.push_back(new DeclRefExpr(
|
||||
CurMethodDecl->getSelfDecl(),
|
||||
Context->getObjCIdType(),
|
||||
SourceLocation()));
|
||||
llvm::SmallVector<Expr*, 8> ClsExprs;
|
||||
|
|
|
@ -308,6 +308,20 @@ protected:
|
|||
static VarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
class ImplicitParamDecl : public VarDecl {
|
||||
protected:
|
||||
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
|
||||
: VarDecl(DK, DC, L, Id, T, VarDecl::None, PrevDecl) {}
|
||||
public:
|
||||
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, ScopedDecl *PrevDecl);
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const ImplicitParamDecl *D) { return true; }
|
||||
static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; }
|
||||
};
|
||||
|
||||
/// ParmVarDecl - Represent a parameter to a function.
|
||||
class ParmVarDecl : public VarDecl {
|
||||
// NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
Function, // [DeclContext]
|
||||
CXXMethod,
|
||||
Var,
|
||||
ImplicitParam,
|
||||
CXXClassVar,
|
||||
ParmVar,
|
||||
ObjCInterface, // [DeclContext]
|
||||
|
@ -172,6 +173,7 @@ public:
|
|||
IdentifierNamespace getIdentifierNamespace() const {
|
||||
switch (DeclKind) {
|
||||
default: assert(0 && "Unknown decl kind!");
|
||||
case ImplicitParam:
|
||||
case Typedef:
|
||||
case Function:
|
||||
case Var:
|
||||
|
|
|
@ -91,7 +91,9 @@ private:
|
|||
// The following are only used for method definitions, null otherwise.
|
||||
// FIXME: space savings opportunity, consider a sub-class.
|
||||
Stmt *Body;
|
||||
ParmVarDecl *SelfDecl;
|
||||
// Decls for implicit parameters
|
||||
ImplicitParamDecl *SelfDecl;
|
||||
ImplicitParamDecl *CmdDecl;
|
||||
|
||||
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
|
||||
Selector SelInfo, QualType T,
|
||||
|
@ -107,8 +109,8 @@ private:
|
|||
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
|
||||
MethodContext(static_cast<NamedDecl*>(contextDecl)),
|
||||
SelName(SelInfo), MethodDeclType(T),
|
||||
ParamInfo(0), NumMethodParams(0),
|
||||
MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {}
|
||||
ParamInfo(0), NumMethodParams(0), MethodAttrs(M),
|
||||
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
|
||||
|
||||
virtual ~ObjCMethodDecl();
|
||||
|
||||
|
@ -165,6 +167,11 @@ public:
|
|||
}
|
||||
void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
|
||||
|
||||
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
|
||||
void setSelfDecl(ImplicitParamDecl *decl) { SelfDecl = decl; }
|
||||
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
|
||||
void setCmdDecl(ImplicitParamDecl *decl) { CmdDecl = decl; }
|
||||
|
||||
AttributeList *getMethodAttrs() const {return MethodAttrs;}
|
||||
bool isInstance() const { return IsInstance; }
|
||||
bool isVariadic() const { return IsVariadic; }
|
||||
|
@ -182,10 +189,6 @@ public:
|
|||
const Stmt *getBody() const { return Body; }
|
||||
void setBody(Stmt *B) { Body = B; }
|
||||
|
||||
const ParmVarDecl *getSelfDecl() const { return SelfDecl; }
|
||||
ParmVarDecl *getSelfDecl() { return SelfDecl; }
|
||||
void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
|
||||
static bool classof(const ObjCMethodDecl *D) { return true; }
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
DISPATCH_CASE(Function,FunctionDecl)
|
||||
DISPATCH_CASE(Var,VarDecl)
|
||||
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
|
||||
DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
|
||||
DISPATCH_CASE(EnumConstant,EnumConstantDecl)
|
||||
DISPATCH_CASE(Typedef,TypedefDecl)
|
||||
DISPATCH_CASE(Struct,RecordDecl) // FIXME: Refine. VisitStructDecl?
|
||||
|
@ -70,6 +71,7 @@ public:
|
|||
DEFAULT_DISPATCH(VarDecl)
|
||||
DEFAULT_DISPATCH(FunctionDecl)
|
||||
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
|
||||
DEFAULT_DISPATCH(ImplicitParamDecl)
|
||||
DEFAULT_DISPATCH(EnumConstantDecl)
|
||||
DEFAULT_DISPATCH(TypedefDecl)
|
||||
DEFAULT_DISPATCH(RecordDecl)
|
||||
|
|
|
@ -40,6 +40,12 @@ void NamespaceDecl::Destroy(ASTContext& C) {
|
|||
}
|
||||
|
||||
|
||||
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl) {
|
||||
void *Mem = C.getAllocator().Allocate<ImplicitParamDecl>();
|
||||
return new (Mem) ImplicitParamDecl(ImplicitParam, DC, L, Id, T, PrevDecl);
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
|
|
|
@ -206,6 +206,7 @@ void Decl::addDeclKind(Kind k) {
|
|||
case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
|
||||
case LinkageSpec: nLinkageSpecDecl++; break;
|
||||
case FileScopeAsm: nFileScopeAsmDecl++; break;
|
||||
case ImplicitParam:
|
||||
case TranslationUnit: break;
|
||||
|
||||
// FIXME: Statistics for C++ decls.
|
||||
|
|
|
@ -389,10 +389,12 @@ Expr::isLvalueResult Expr::isLvalue() const {
|
|||
if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType())
|
||||
return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue();
|
||||
return LV_Valid;
|
||||
case DeclRefExprClass: // C99 6.5.1p2
|
||||
if (isa<VarDecl>(cast<DeclRefExpr>(this)->getDecl()))
|
||||
case DeclRefExprClass: { // C99 6.5.1p2
|
||||
const Decl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
|
||||
if (isa<VarDecl>(RefdDecl) || isa<ImplicitParamDecl>(RefdDecl))
|
||||
return LV_Valid;
|
||||
break;
|
||||
}
|
||||
case MemberExprClass: { // C99 6.5.2.3p4
|
||||
const MemberExpr *m = cast<MemberExpr>(this);
|
||||
return m->isArrow() ? LV_Valid : m->getBase()->isLvalue();
|
||||
|
|
|
@ -144,12 +144,18 @@ ValueState* GRExprEngine::getInitialState() {
|
|||
|
||||
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
|
||||
|
||||
VarDecl* VD = cast<VarDecl>(const_cast<ScopedDecl*>(I->first));
|
||||
|
||||
ScopedDecl *SD = const_cast<ScopedDecl*>(I->first);
|
||||
if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
|
||||
if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD)) {
|
||||
RVal X = RVal::GetSymbolValue(SymMgr, VD);
|
||||
StateMgr.BindVar(StateImpl, VD, X);
|
||||
}
|
||||
} else if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(SD)) {
|
||||
RVal X = RVal::GetSymbolValue(SymMgr, IPD);
|
||||
StateMgr.BindVar(StateImpl, IPD, X);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return StateMgr.getPersistentState(StateImpl);
|
||||
|
|
|
@ -60,6 +60,11 @@ public:
|
|||
AD.AlwaysLive(*I, AD) = Alive;
|
||||
}
|
||||
|
||||
void VisitImplicitParamDecl(ImplicitParamDecl* IPD) {
|
||||
// Register the VarDecl for tracking.
|
||||
AD.Register(IPD);
|
||||
}
|
||||
|
||||
void VisitVarDecl(VarDecl* VD) {
|
||||
// Register the VarDecl for tracking.
|
||||
AD.Register(VD);
|
||||
|
|
|
@ -370,7 +370,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
|
|||
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
|
||||
|
||||
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD))) {
|
||||
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) ||
|
||||
isa<ImplicitParamDecl>(VD))) {
|
||||
if (VD->getStorageClass() == VarDecl::Extern)
|
||||
return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false),
|
||||
E->getType().getCVRQualifiers());
|
||||
|
@ -386,6 +387,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
|||
return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false),
|
||||
E->getType().getCVRQualifiers());
|
||||
}
|
||||
else if (const ImplicitParamDecl *IPD =
|
||||
dyn_cast<ImplicitParamDecl>(E->getDecl())) {
|
||||
llvm::Value *V = LocalDeclMap[IPD];
|
||||
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
|
||||
return LValue::MakeAddr(V, E->getType().getCVRQualifiers());
|
||||
}
|
||||
assert(0 && "Unimp declref");
|
||||
//an invalid LValue, but the assert will
|
||||
//ensure that this point is never reached.
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "CodeGenModule.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "llvm/Constant.h"
|
||||
#include "llvm/Function.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
|
@ -24,4 +26,91 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){
|
|||
return CGM.GetAddrOfConstantCFString(S);
|
||||
}
|
||||
|
||||
/// Generate an Objective-C method. An Objective-C method is a C function with
|
||||
/// its pointer, name, and types registered in the class struture.
|
||||
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
|
||||
|
||||
llvm::SmallVector<const llvm::Type *, 16> ParamTypes;
|
||||
for (unsigned i=0 ; i<OMD->param_size() ; i++) {
|
||||
const llvm::Type *Ty = ConvertType(OMD->getParamDecl(i)->getType());
|
||||
if (Ty->isFirstClassType())
|
||||
ParamTypes.push_back(Ty);
|
||||
else
|
||||
ParamTypes.push_back(llvm::PointerType::getUnqual(Ty));
|
||||
}
|
||||
std::string CategoryName = "";
|
||||
if (ObjCCategoryImplDecl *OCD =
|
||||
dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext())) {
|
||||
CategoryName = OCD->getName();
|
||||
}
|
||||
const llvm::Type *ReturnTy = CGM.getTypes().ConvertReturnType(OMD->getResultType());
|
||||
CurFn = CGM.getObjCRuntime()->MethodPreamble(
|
||||
OMD->getClassInterface()->getName(),
|
||||
CategoryName,
|
||||
OMD->getSelector().getName(),
|
||||
ReturnTy,
|
||||
llvm::PointerType::getUnqual(
|
||||
llvm::Type::Int32Ty),
|
||||
ParamTypes.begin(),
|
||||
OMD->param_size(),
|
||||
!OMD->isInstance(),
|
||||
OMD->isVariadic());
|
||||
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("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();
|
||||
CurFuncDecl = OMD;
|
||||
|
||||
Builder.SetInsertPoint(EntryBB);
|
||||
|
||||
// Emit allocs for param decls. Give the LLVM Argument nodes names.
|
||||
llvm::Function::arg_iterator AI = CurFn->arg_begin();
|
||||
|
||||
if (hasAggregateLLVMType(OMD->getResultType())) {
|
||||
++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;
|
||||
++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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
CGObjCRuntime::~CGObjCRuntime() {}
|
||||
|
|
|
@ -27,7 +27,10 @@ using namespace CodeGen;
|
|||
|
||||
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
||||
: CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL),
|
||||
CaseRangeBlock(NULL) {}
|
||||
CaseRangeBlock(NULL) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
LLVMPointerWidth = Target.getPointerWidth(0);
|
||||
}
|
||||
|
||||
ASTContext &CodeGenFunction::getContext() const {
|
||||
return CGM.getContext();
|
||||
|
@ -51,169 +54,20 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T) {
|
|||
return CGM.getTypes().ConvertType(T);
|
||||
}
|
||||
|
||||
bool CodeGenFunction::isObjCPointerType(QualType T) {
|
||||
// All Objective-C types are pointers.
|
||||
return T->isObjCInterfaceType() ||
|
||||
T->isObjCQualifiedInterfaceType() || T->isObjCQualifiedIdType();
|
||||
}
|
||||
|
||||
bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
|
||||
return !T->isRealType() && !T->isPointerLikeType() &&
|
||||
return !isObjCPointerType(T) &&!T->isRealType() && !T->isPointerLikeType() &&
|
||||
!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()));
|
||||
}
|
||||
std::string CategoryName = "";
|
||||
if (ObjCCategoryImplDecl *OCD =
|
||||
dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext())) {
|
||||
CategoryName = OCD->getName();
|
||||
}
|
||||
|
||||
CurFn =CGM.getObjCRuntime()->MethodPreamble(
|
||||
OMD->getClassInterface()->getName(),
|
||||
CategoryName,
|
||||
OMD->getSelector().getName(),
|
||||
ConvertType(OMD->getResultType()),
|
||||
llvm::PointerType::getUnqual(llvm::Type::Int32Ty),
|
||||
ParamTypes.begin(),
|
||||
OMD->param_size(),
|
||||
!OMD->isInstance(),
|
||||
OMD->isVariadic());
|
||||
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("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())];
|
||||
const llvm::Type *SelfTy = AI->getType();
|
||||
llvm::Value *DeclPtr = new llvm::AllocaInst(SelfTy, 0, "self.addr",
|
||||
AllocaInsertPt);
|
||||
|
||||
// Store the initial value into the alloca.
|
||||
// FIXME: volatility
|
||||
Builder.CreateStore(AI, DeclPtr);
|
||||
DMEntry = DeclPtr;
|
||||
++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);
|
||||
}
|
||||
|
||||
void CodeGenFunction::GenerateFunction(const Stmt *Body) {
|
||||
// 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.");
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::LoadObjCSelf(void)
|
||||
{
|
||||
if(const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurFuncDecl)) {
|
||||
llvm::Value *SelfPtr = LocalDeclMap[&(*OMD->getSelfDecl())];
|
||||
// FIXME: Volatility
|
||||
return Builder.CreateLoad(SelfPtr, "self");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
LLVMPointerWidth = static_cast<unsigned>(
|
||||
getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));
|
||||
|
||||
CurFuncDecl = FD;
|
||||
FnRetTy = FD->getType()->getAsFunctionType()->getResultType();
|
||||
|
||||
CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
|
||||
assert(CurFn->isDeclaration() && "Function already has body?");
|
||||
|
||||
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("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);
|
||||
|
||||
Builder.SetInsertPoint(EntryBB);
|
||||
|
||||
CGDebugInfo *DI = CGM.getDebugInfo();
|
||||
if (DI) {
|
||||
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
|
||||
if (body->getLBracLoc().isValid()) {
|
||||
DI->setLocation(body->getLBracLoc());
|
||||
}
|
||||
DI->EmitFunctionStart(FD, CurFn, Builder);
|
||||
}
|
||||
|
||||
// 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(FD->getResultType())) {
|
||||
AI->setName("agg.result");
|
||||
++AI;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
|
||||
assert(AI != CurFn->arg_end() && "Argument mismatch!");
|
||||
EmitParmDecl(*FD->getParamDecl(i), AI);
|
||||
}
|
||||
|
||||
// Emit the function body.
|
||||
EmitStmt(FD->getBody());
|
||||
|
||||
if (DI) {
|
||||
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
|
||||
if (body->getRBracLoc().isValid()) {
|
||||
DI->setLocation(body->getRBracLoc());
|
||||
}
|
||||
DI->EmitRegionEnd(CurFn, Builder);
|
||||
}
|
||||
EmitStmt(Body);
|
||||
|
||||
// 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.
|
||||
|
@ -238,6 +92,39 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
|||
assert(!verifyFunction(*CurFn) && "Generated function is not well formed.");
|
||||
}
|
||||
|
||||
void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
||||
CurFuncDecl = FD;
|
||||
FnRetTy = FD->getResultType();
|
||||
CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
|
||||
assert(CurFn->isDeclaration() && "Function already has body?");
|
||||
|
||||
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("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);
|
||||
|
||||
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.
|
||||
if (hasAggregateLLVMType(FD->getResultType())) {
|
||||
AI->setName("agg.result");
|
||||
++AI;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
|
||||
assert(AI != CurFn->arg_end() && "Argument mismatch!");
|
||||
EmitParmDecl(*FD->getParamDecl(i), AI);
|
||||
}
|
||||
GenerateFunction(FD->getBody());
|
||||
}
|
||||
|
||||
/// isDummyBlock - Return true if BB is an empty basic block
|
||||
/// with no predecessors.
|
||||
bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) {
|
||||
|
|
|
@ -232,7 +232,7 @@ public:
|
|||
llvm::IRBuilder Builder;
|
||||
|
||||
// Holds the Decl for the current function or method
|
||||
const FunctionDecl *CurFuncDecl;
|
||||
const Decl *CurFuncDecl;
|
||||
QualType FnRetTy;
|
||||
llvm::Function *CurFn;
|
||||
|
||||
|
@ -277,11 +277,16 @@ public:
|
|||
|
||||
void GenerateObjCMethod(const ObjCMethodDecl *OMD);
|
||||
void GenerateCode(const FunctionDecl *FD);
|
||||
void GenerateFunction(const Stmt *Body);
|
||||
|
||||
const llvm::Type *ConvertType(QualType T);
|
||||
|
||||
llvm::Value *LoadObjCSelf();
|
||||
|
||||
/// isObjCPointerType - Return true if the specificed AST type will map onto
|
||||
/// some Objective-C pointer type.
|
||||
static bool isObjCPointerType(QualType T);
|
||||
|
||||
/// hasAggregateLLVMType - Return true if the specified AST type will map into
|
||||
/// an aggregate LLVM type or is void.
|
||||
static bool hasAggregateLLVMType(QualType T);
|
||||
|
|
|
@ -161,6 +161,13 @@ void CodeGenTypes::CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
|
|||
}
|
||||
}
|
||||
|
||||
const llvm::Type *CodeGenTypes::ConvertReturnType(QualType T) {
|
||||
if (T->isVoidType())
|
||||
return llvm::Type::VoidTy; // Result of function uses llvm void.
|
||||
else
|
||||
return ConvertType(T);
|
||||
}
|
||||
|
||||
static const llvm::Type* getTypeForFormat(const llvm::fltSemantics * format) {
|
||||
if (format == &llvm::APFloat::IEEEsingle)
|
||||
return llvm::Type::FloatTy;
|
||||
|
|
|
@ -132,6 +132,9 @@ public:
|
|||
/// ConvertType - Convert type T into a llvm::Type.
|
||||
const llvm::Type *ConvertType(QualType T);
|
||||
const llvm::Type *ConvertTypeRecursive(QualType T);
|
||||
/// ConvertReturnType - Convert T into an llvm::Type assuming that it will be
|
||||
/// used as a function return type.
|
||||
const llvm::Type *ConvertReturnType(QualType T);
|
||||
|
||||
/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
|
||||
/// ConvertType in that it is used to convert to the memory representation for
|
||||
|
@ -143,6 +146,8 @@ public:
|
|||
std::vector<const llvm::Type*> &IvarTypes);
|
||||
|
||||
const CGRecordLayout *getCGRecordLayout(const TagDecl*) const;
|
||||
/// Returns a StructType representing an Objective-C object
|
||||
const llvm::Type *ConvertObjCInterfaceToStruct(const ObjCInterfaceDecl *OID);
|
||||
|
||||
/// getLLVMFieldNo - Return llvm::StructType element number
|
||||
/// that corresponds to the field FD.
|
||||
|
|
|
@ -277,7 +277,7 @@ private:
|
|||
|
||||
/// Helpers for dealing with function parameters
|
||||
bool CheckParmsForFunctionDef(FunctionDecl *FD);
|
||||
ParmVarDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
|
||||
ImplicitParamDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
|
||||
SourceLocation IdLoc, QualType Type);
|
||||
void CheckCXXDefaultArguments(FunctionDecl *FD);
|
||||
void CheckExtraCXXDefaultArguments(Declarator &D);
|
||||
|
|
|
@ -480,11 +480,11 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
|
|||
/// in the scope S and with the given type. This routine is used, for
|
||||
/// example, to create the implicit "self" parameter in an Objective-C
|
||||
/// method.
|
||||
ParmVarDecl *
|
||||
ImplicitParamDecl *
|
||||
Sema::CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
|
||||
SourceLocation IdLoc, QualType Type) {
|
||||
ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext, IdLoc, Id, Type,
|
||||
VarDecl::None, 0, 0);
|
||||
ImplicitParamDecl *New = ImplicitParamDecl::Create(Context, CurContext,
|
||||
IdLoc, Id, Type, 0);
|
||||
if (Id)
|
||||
PushOnScopeChains(New, S);
|
||||
|
||||
|
|
|
@ -53,12 +53,12 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
}
|
||||
} else // we have a factory method.
|
||||
selfTy = Context.getObjCClassType();
|
||||
CurMethodDecl->setSelfDecl(CreateImplicitParameter(FnBodyScope, PI.Ident,
|
||||
PI.IdentLoc, selfTy));
|
||||
CurMethodDecl->setSelfDecl(CreateImplicitParameter(FnBodyScope,
|
||||
PI.Ident, PI.IdentLoc, selfTy));
|
||||
|
||||
PI.Ident = &Context.Idents.get("_cmd");
|
||||
CreateImplicitParameter(FnBodyScope, PI.Ident, PI.IdentLoc,
|
||||
Context.getObjCSelType());
|
||||
CurMethodDecl->setCmdDecl(CreateImplicitParameter(FnBodyScope,
|
||||
PI.Ident, PI.IdentLoc, Context.getObjCSelType()));
|
||||
|
||||
// Introduce all of the other parameters into this scope.
|
||||
for (unsigned i = 0, e = MDecl->getNumParams(); i != e; ++i) {
|
||||
|
|
Loading…
Reference in New Issue