From 88a69ad80e1550e9932666e6efa050a5b1223889 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 13 Jul 2007 05:13:43 +0000 Subject: [PATCH] implement support for basic codegen of global variables with no initializers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39795 91177308-0d34-0410-b5e6-96231b3b80d8 --- CodeGen/CGDecl.cpp | 1 - CodeGen/CodeGenModule.cpp | 35 ++++++++++++++++++++++++++- CodeGen/CodeGenModule.h | 4 ++- CodeGen/ModuleBuilder.cpp | 6 +++++ Driver/LLVMCodegen.cpp | 8 +++--- include/clang/CodeGen/ModuleBuilder.h | 4 +++ 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/CodeGen/CGDecl.cpp b/CodeGen/CGDecl.cpp index 1cce124a82..d86f305151 100644 --- a/CodeGen/CGDecl.cpp +++ b/CodeGen/CGDecl.cpp @@ -19,7 +19,6 @@ using namespace CodeGen; void CodeGenFunction::EmitDecl(const Decl &D) { - switch (D.getKind()) { default: assert(0 && "Unknown decl kind!"); case Decl::FileVariable: diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp index cdc3e63026..b610d3eb27 100644 --- a/CodeGen/CodeGenModule.cpp +++ b/CodeGen/CodeGenModule.cpp @@ -48,12 +48,45 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const Decl *D) { 0, D->getName(), &getModule()); } -void CodeGenModule::EmitFunction(FunctionDecl *FD) { +void CodeGenModule::EmitFunction(const FunctionDecl *FD) { // If this is not a prototype, emit the body. if (FD->getBody()) CodeGenFunction(*this).GenerateCode(FD); } +void CodeGenModule::EmitGlobalVar(const FileVarDecl *D) { + llvm::GlobalVariable *GV = cast(GetAddrOfGlobalDecl(D)); + + // If the storage class is external and there is no initializer, just leave it + // as a declaration. + if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0) + return; + + // Otherwise, convert the initializer, or use zero if appropriate. + llvm::Constant *Init; + if (D->getInit() == 0) + Init = llvm::Constant::getNullValue(GV->getType()->getElementType()); + else + assert(D->getInit() == 0 && "FIXME: Global variable initializers unimp!"); + + GV->setInitializer(Init); + + // Set the llvm linkage type as appropriate. + // FIXME: This isn't right. This should handle common linkage and other + // stuff. + switch (D->getStorageClass()) { + case VarDecl::Auto: + case VarDecl::Register: + assert(0 && "Can't have auto or register globals"); + case VarDecl::None: + case VarDecl::Extern: + // todo: common + break; + case VarDecl::Static: + GV->setLinkage(llvm::GlobalVariable::InternalLinkage); + break; + } +} llvm::Function *CodeGenModule::getMemCpyFn() { diff --git a/CodeGen/CodeGenModule.h b/CodeGen/CodeGenModule.h index 885fb97a9f..9d8547030e 100644 --- a/CodeGen/CodeGenModule.h +++ b/CodeGen/CodeGenModule.h @@ -27,6 +27,7 @@ namespace clang { class ASTContext; class FunctionDecl; class Decl; + class FileVarDecl; namespace CodeGen { @@ -50,7 +51,8 @@ public: llvm::Function *getMemCpyFn(); - void EmitFunction(FunctionDecl *FD); + void EmitFunction(const FunctionDecl *FD); + void EmitGlobalVar(const FileVarDecl *D); void PrintStats() {} }; diff --git a/CodeGen/ModuleBuilder.cpp b/CodeGen/ModuleBuilder.cpp index 16b13d1c4d..e525514df5 100644 --- a/CodeGen/ModuleBuilder.cpp +++ b/CodeGen/ModuleBuilder.cpp @@ -32,6 +32,12 @@ void clang::CodeGen::CodeGenFunction(BuilderTy *B, FunctionDecl *D) { static_cast(B)->EmitFunction(D); } +/// CodeGenGlobalVar - Emit the specified global variable to LLVM. +void clang::CodeGen::CodeGenGlobalVar(BuilderTy *Builder, FileVarDecl *D) { + static_cast(Builder)->EmitGlobalVar(D); +} + + /// PrintStats - Emit statistic information to stderr. /// void clang::CodeGen::PrintStats(BuilderTy *B) { diff --git a/Driver/LLVMCodegen.cpp b/Driver/LLVMCodegen.cpp index e593b66cfd..b969ff81ca 100644 --- a/Driver/LLVMCodegen.cpp +++ b/Driver/LLVMCodegen.cpp @@ -45,10 +45,12 @@ void clang::EmitLLVMFromASTs(Preprocessor &PP, unsigned MainFileID, if (FunctionDecl *FD = dyn_cast(D)) { CodeGen::CodeGenFunction(Builder, FD); - } else if (isa(D)) { - std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n"; + } else if (FileVarDecl *FVD = dyn_cast(D)) { + CodeGen::CodeGenGlobalVar(Builder, FVD); } else { - std::cerr << "Read top-level variable decl: '" << D->getName() << "'\n"; + assert(isa(D) && "Only expected typedefs here"); + // don't codegen for now, eventually pass down for debug info. + //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n"; } } diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index e9cb2b5bd4..0b1ae476ed 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -21,6 +21,7 @@ namespace llvm { namespace clang { class ASTContext; class FunctionDecl; + class FileVarDecl; namespace CodeGen { /// BuilderTy - This is an opaque type used to reference ModuleBuilder @@ -34,6 +35,9 @@ namespace CodeGen { /// void CodeGenFunction(BuilderTy *Builder, FunctionDecl *D); + /// CodeGenGlobalVar - Emit the specified global variable to LLVM. + void CodeGenGlobalVar(BuilderTy *Builder, FileVarDecl *D); + /// PrintStats - Emit statistic information to stderr. /// void PrintStats(BuilderTy *Builder);