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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54827 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 3340cdf..99390c1 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -86,10 +86,10 @@
                     &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 @@
     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 @@
   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 @@
   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::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");
+  }
+}
+