mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 01:16:05 +00:00
Clean up CodeGenModule interface.
- Add CodeGenModule::EmitTopLevelDecl which uses switch on kind instead of ugly & slow dyn_cast chains. - Drop some simple forwarding methods into the ObjC runtime. - Privatize appropriate methods. llvm-svn: 54827
This commit is contained in:
parent
db0b7f942a
commit
fce4be843e
@ -86,10 +86,10 @@ void CodeGenModule::WarnUnsupported(const Decl *D, const char *Type) {
|
||||
&Msg, 1);
|
||||
}
|
||||
|
||||
/// setVisibility - Set the visibility for the given LLVM GlobalValue
|
||||
/// according to the given clang AST visibility value.
|
||||
void CodeGenModule::setVisibility(llvm::GlobalValue *GV,
|
||||
VisibilityAttr::VisibilityTypes Vis) {
|
||||
/// setGlobalVisibility - Set the visibility for the given LLVM
|
||||
/// GlobalValue according to the given clang AST visibility value.
|
||||
static void setGlobalVisibility(llvm::GlobalValue *GV,
|
||||
VisibilityAttr::VisibilityTypes Vis) {
|
||||
switch (Vis) {
|
||||
default: assert(0 && "Unknown visibility!");
|
||||
case VisibilityAttr::DefaultVisibility:
|
||||
@ -185,7 +185,7 @@ void CodeGenModule::SetGlobalValueAttributes(const FunctionDecl *FD,
|
||||
GV->setLinkage(llvm::Function::WeakLinkage);
|
||||
|
||||
if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>())
|
||||
CodeGenModule::setVisibility(GV, attr->getVisibility());
|
||||
setGlobalVisibility(GV, attr->getVisibility());
|
||||
// FIXME: else handle -fvisibility
|
||||
|
||||
if (const AsmLabelAttr *ALA = FD->getAttr<AsmLabelAttr>()) {
|
||||
@ -242,24 +242,6 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
|
||||
SetGlobalValueAttributes(FD, F);
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) {
|
||||
// If this is not a prototype, emit the body.
|
||||
if (OMD->getBody())
|
||||
CodeGenFunction(*this).GenerateObjCMethod(OMD);
|
||||
}
|
||||
void CodeGenModule::EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD){
|
||||
Runtime->GenerateProtocol(PD);
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) {
|
||||
Runtime->GenerateCategory(OCD);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenModule::EmitObjCClassImplementation(const ObjCImplementationDecl *OID) {
|
||||
Runtime->GenerateClass(OID);
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitStatics() {
|
||||
// Emit code for each used static decl encountered. Since a previously unused
|
||||
// static decl may become used during the generation of code for a static
|
||||
@ -486,7 +468,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
GV->setAlignment(Align / 8);
|
||||
|
||||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>())
|
||||
setVisibility(GV, attr->getVisibility());
|
||||
setGlobalVisibility(GV, attr->getVisibility());
|
||||
// FIXME: else handle -fvisibility
|
||||
|
||||
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
|
||||
@ -849,3 +831,88 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) {
|
||||
llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str) {
|
||||
return GetAddrOfConstantString(str + "\0");
|
||||
}
|
||||
|
||||
/// EmitTopLevelDecl - Emit code for a single top level declaration.
|
||||
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
// If an error has occurred, stop code generation, but continue
|
||||
// parsing and semantic analysis (to ensure all warnings and errors
|
||||
// are emitted).
|
||||
if (Diags.hasErrorOccurred())
|
||||
return;
|
||||
|
||||
switch (D->getKind()) {
|
||||
case Decl::Function:
|
||||
case Decl::Var:
|
||||
EmitGlobal(cast<ValueDecl>(D));
|
||||
break;
|
||||
|
||||
case Decl::Namespace:
|
||||
assert(0 && "FIXME: Namespace unsupported");
|
||||
break;
|
||||
|
||||
// Objective-C Decls
|
||||
|
||||
// Forward declarations, no (immediate) code generation.
|
||||
case Decl::ObjCClass:
|
||||
case Decl::ObjCCategory:
|
||||
case Decl::ObjCForwardProtocol:
|
||||
case Decl::ObjCInterface:
|
||||
break;
|
||||
|
||||
case Decl::ObjCProtocol:
|
||||
Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
|
||||
break;
|
||||
|
||||
case Decl::ObjCCategoryImpl:
|
||||
Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
|
||||
break;
|
||||
|
||||
case Decl::ObjCImplementation:
|
||||
Runtime->GenerateClass(cast<ObjCImplementationDecl>(D));
|
||||
break;
|
||||
|
||||
case Decl::ObjCMethod: {
|
||||
ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
|
||||
// If this is not a prototype, emit the body.
|
||||
if (OMD->getBody())
|
||||
CodeGenFunction(*this).GenerateObjCMethod(OMD);
|
||||
break;
|
||||
}
|
||||
case Decl::ObjCPropertyImpl:
|
||||
assert(0 && "FIXME: ObjCPropertyImpl unsupported");
|
||||
break;
|
||||
case Decl::ObjCCompatibleAlias:
|
||||
assert(0 && "FIXME: ObjCCompatibleAlias unsupported");
|
||||
break;
|
||||
|
||||
case Decl::LinkageSpec: {
|
||||
LinkageSpecDecl *LSD = cast<LinkageSpecDecl>(D);
|
||||
if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx)
|
||||
WarnUnsupported(LSD, "linkage spec");
|
||||
// FIXME: implement C++ linkage, C linkage works mostly by C
|
||||
// language reuse already.
|
||||
break;
|
||||
}
|
||||
|
||||
case Decl::FileScopeAsm: {
|
||||
FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
|
||||
std::string AsmString(AD->getAsmString()->getStrData(),
|
||||
AD->getAsmString()->getByteLength());
|
||||
|
||||
const std::string &S = getModule().getModuleInlineAsm();
|
||||
if (S.empty())
|
||||
getModule().setModuleInlineAsm(AsmString);
|
||||
else
|
||||
getModule().setModuleInlineAsm(S + '\n' + AsmString);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Make sure we handled everything we should, every other kind is
|
||||
// a non-top-level decl. FIXME: Would be nice to have an
|
||||
// isTopLevelDeclKind function. Need to recode Decl::Kind to do
|
||||
// that easily.
|
||||
assert(isa<TypeDecl>(D) && "Unsupported decl kind");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,8 @@ namespace CodeGen {
|
||||
class CGDebugInfo;
|
||||
class CGObjCRuntime;
|
||||
|
||||
/// CodeGenModule - This class organizes the cross-module state that is used
|
||||
/// while generating LLVM code.
|
||||
/// CodeGenModule - This class organizes the cross-function state that
|
||||
/// is used while generating LLVM code.
|
||||
class CodeGenModule {
|
||||
typedef std::vector< std::pair<llvm::Constant*, int> > CtorList;
|
||||
|
||||
@ -138,11 +138,6 @@ public:
|
||||
/// GetAddrOfFunction - Return the llvm::Constant for the address
|
||||
/// of the given function.
|
||||
llvm::Constant *GetAddrOfFunction(const FunctionDecl *D);
|
||||
|
||||
/// getBuiltinLibFunction - Given a builtin id for a function like
|
||||
/// "__builtin_fabsf", return a Function* for "fabsf".
|
||||
///
|
||||
llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
|
||||
|
||||
/// GetStringForStringLiteral - Return the appropriate bytes for a
|
||||
/// string literal, properly padded to match the literal type. If
|
||||
@ -150,6 +145,8 @@ public:
|
||||
/// GetAddrOfConstantStringLiteral.
|
||||
std::string GetStringForStringLiteral(const StringLiteral *E);
|
||||
|
||||
/// GetAddrOfConstantCFString - Return a pointer to a
|
||||
/// constant CFString object for the given string.
|
||||
llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
|
||||
|
||||
/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
|
||||
@ -170,21 +167,19 @@ public:
|
||||
/// array containing the literal and a terminating '\-'
|
||||
/// character. The result has pointer to array type.
|
||||
llvm::Constant *GetAddrOfConstantCString(const std::string &str);
|
||||
|
||||
/// getBuiltinLibFunction - Given a builtin id for a function like
|
||||
/// "__builtin_fabsf", return a Function* for "fabsf".
|
||||
llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
|
||||
|
||||
llvm::Function *getMemCpyFn();
|
||||
llvm::Function *getMemMoveFn();
|
||||
llvm::Function *getMemSetFn();
|
||||
llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0,
|
||||
unsigned NumTys = 0);
|
||||
|
||||
void EmitObjCMethod(const ObjCMethodDecl *OMD);
|
||||
void EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD);
|
||||
void EmitObjCClassImplementation(const ObjCImplementationDecl *OID);
|
||||
void EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD);
|
||||
|
||||
/// EmitGlobal - Emit code for a singal global function or var
|
||||
/// decl. Forward declarations are emitted lazily.
|
||||
void EmitGlobal(const ValueDecl *D);
|
||||
/// EmitTopLevelDecl - Emit code for a single top level declaration.
|
||||
void EmitTopLevelDecl(Decl *D);
|
||||
|
||||
void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
|
||||
|
||||
@ -194,18 +189,12 @@ public:
|
||||
const AnnotateAttr *AA, unsigned LineNo);
|
||||
|
||||
/// WarnUnsupported - Print out a warning that codegen doesn't support the
|
||||
/// specified stmt yet.
|
||||
|
||||
/// specified stmt yet.
|
||||
void WarnUnsupported(const Stmt *S, const char *Type);
|
||||
|
||||
/// WarnUnsupported - Print out a warning that codegen doesn't support the
|
||||
/// specified decl yet.
|
||||
void WarnUnsupported(const Decl *D, const char *Type);
|
||||
|
||||
/// setVisibility - Set the visibility for the given LLVM GlobalValue
|
||||
/// according to the given clang AST visibility value.
|
||||
static void setVisibility(llvm::GlobalValue *GV,
|
||||
VisibilityAttr::VisibilityTypes);
|
||||
|
||||
private:
|
||||
void SetFunctionAttributes(const FunctionDecl *FD,
|
||||
@ -215,6 +204,10 @@ private:
|
||||
void SetGlobalValueAttributes(const FunctionDecl *FD,
|
||||
llvm::GlobalValue *GV);
|
||||
|
||||
/// EmitGlobal - Emit code for a singal global function or var
|
||||
/// decl. Forward declarations are emitted lazily.
|
||||
void EmitGlobal(const ValueDecl *D);
|
||||
|
||||
void EmitGlobalDefinition(const ValueDecl *D);
|
||||
llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D);
|
||||
void EmitGlobalFunctionDefinition(const FunctionDecl *D);
|
||||
|
@ -63,63 +63,15 @@ namespace {
|
||||
}
|
||||
|
||||
virtual void HandleTopLevelDecl(Decl *D) {
|
||||
// If an error occurred, stop code generation, but continue parsing and
|
||||
// semantic analysis (to ensure all warnings and errors are emitted).
|
||||
if (Diags.hasErrorOccurred())
|
||||
return;
|
||||
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
Builder->EmitGlobal(FD);
|
||||
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
Builder->EmitGlobal(VD);
|
||||
} else if (isa<ObjCClassDecl>(D) || isa<ObjCForwardProtocolDecl>(D)) {
|
||||
//Forward declaration. Only used for type checking.
|
||||
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)){
|
||||
// Generate Protocol object.
|
||||
Builder->EmitObjCProtocolImplementation(PD);
|
||||
} else if (isa<ObjCCategoryDecl>(D)){
|
||||
//Only used for typechecking.
|
||||
} else if (ObjCCategoryImplDecl *OCD = dyn_cast<ObjCCategoryImplDecl>(D)){
|
||||
// Generate methods, attach to category structure
|
||||
Builder->EmitObjCCategoryImpl(OCD);
|
||||
} else if (ObjCImplementationDecl * OID =
|
||||
dyn_cast<ObjCImplementationDecl>(D)){
|
||||
// Generate methods, attach to class structure
|
||||
Builder->EmitObjCClassImplementation(OID);
|
||||
} else if (isa<ObjCInterfaceDecl>(D)){
|
||||
// Ignore - generated when the implementation decl is CodeGen'd
|
||||
} else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){
|
||||
Builder->EmitObjCMethod(OMD);
|
||||
} 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");
|
||||
// FIXME: implement C++ linkage, C linkage works mostly by C
|
||||
// language reuse already.
|
||||
} else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
|
||||
std::string AsmString(AD->getAsmString()->getStrData(),
|
||||
AD->getAsmString()->getByteLength());
|
||||
|
||||
const std::string &S = Builder->getModule().getModuleInlineAsm();
|
||||
if (S.empty())
|
||||
Builder->getModule().setModuleInlineAsm(AsmString);
|
||||
else
|
||||
Builder->getModule().setModuleInlineAsm(S + '\n' + AsmString);
|
||||
} else {
|
||||
assert(isa<TypeDecl>(D) && "Unknown top level decl");
|
||||
// TODO: handle debug info?
|
||||
}
|
||||
|
||||
// Make sure to emit all elements of a ScopedDecl.
|
||||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
|
||||
SD = SD->getNextDeclarator();
|
||||
if (SD)
|
||||
HandleTopLevelDecl(SD);
|
||||
for (; SD; SD = SD->getNextDeclarator())
|
||||
Builder->EmitTopLevelDecl(SD);
|
||||
} else {
|
||||
Builder->EmitTopLevelDecl(D);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
|
||||
/// (e.g. struct, union, enum, class) is completed. This allows the client to
|
||||
/// hack on the type, which can occur at any point in the file (because these
|
||||
|
Loading…
x
Reference in New Issue
Block a user