r311845 - Add forgotten file in r311844.

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 27 04:31:01 PDT 2017


Author: vvassilev
Date: Sun Aug 27 04:31:01 2017
New Revision: 311845

URL: http://llvm.org/viewvc/llvm-project?rev=311845&view=rev
Log:
Add forgotten file in r311844.

Added:
    cfe/trunk/unittests/CodeGen/IncrementalProcessingTest.cpp

Added: cfe/trunk/unittests/CodeGen/IncrementalProcessingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/CodeGen/IncrementalProcessingTest.cpp?rev=311845&view=auto
==============================================================================
--- cfe/trunk/unittests/CodeGen/IncrementalProcessingTest.cpp (added)
+++ cfe/trunk/unittests/CodeGen/IncrementalProcessingTest.cpp Sun Aug 27 04:31:01 2017
@@ -0,0 +1,174 @@
+//=== unittests/CodeGen/IncrementalProcessingTest.cpp - IncrementalCodeGen ===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+
+#include <memory>
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// Incremental processing produces several modules, all using the same "main
+// file". Make sure CodeGen can cope with that, e.g. for static initializers.
+const char TestProgram1[] =
+    "extern \"C\" int funcForProg1() { return 17; }\n"
+    "struct EmitCXXGlobalInitFunc1 {\n"
+    "   EmitCXXGlobalInitFunc1() {}\n"
+    "} test1;";
+
+const char TestProgram2[] =
+    "extern \"C\" int funcForProg2() { return 42; }\n"
+    "struct EmitCXXGlobalInitFunc2 {\n"
+    "   EmitCXXGlobalInitFunc2() {}\n"
+    "} test2;";
+
+
+/// An incremental version of ParseAST().
+static std::unique_ptr<llvm::Module>
+IncrementalParseAST(CompilerInstance& CI, Parser& P,
+                    CodeGenerator& CG, const char* code) {
+  static int counter = 0;
+  struct IncreaseCounterOnRet {
+    ~IncreaseCounterOnRet() {
+      ++counter;
+    }
+  } ICOR;
+
+  Sema& S = CI.getSema();
+  clang::SourceManager &SM = S.getSourceManager();
+  if (!code) {
+    // Main file
+    SM.setMainFileID(SM.createFileID(
+        llvm::MemoryBuffer::getMemBuffer("    "), clang::SrcMgr::C_User));
+
+    S.getPreprocessor().EnterMainSourceFile();
+    P.Initialize();
+  } else {
+    FileID FID = SM.createFileID(
+        llvm::MemoryBuffer::getMemBuffer(code), clang::SrcMgr::C_User);
+    SourceLocation MainStartLoc = SM.getLocForStartOfFile(SM.getMainFileID());
+    SourceLocation InclLoc = MainStartLoc.getLocWithOffset(counter);
+    S.getPreprocessor().EnterSourceFile(FID, 0, InclLoc);
+  }
+
+  ExternalASTSource *External = S.getASTContext().getExternalSource();
+  if (External)
+    External->StartTranslationUnit(&CG);
+
+  Parser::DeclGroupPtrTy ADecl;
+  for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
+       AtEOF = P.ParseTopLevelDecl(ADecl)) {
+    // If we got a null return and something *was* parsed, ignore it.  This
+    // is due to a top-level semicolon, an action override, or a parse error
+    // skipping something.
+    if (ADecl && !CG.HandleTopLevelDecl(ADecl.get()))
+      return nullptr;
+  }
+
+  // Process any TopLevelDecls generated by #pragma weak.
+  for (Decl *D : S.WeakTopLevelDecls())
+    CG.HandleTopLevelDecl(DeclGroupRef(D));
+
+  CG.HandleTranslationUnit(S.getASTContext());
+
+  std::unique_ptr<llvm::Module> M(CG.ReleaseModule());
+  // Switch to next module.
+  CG.StartModule("incremental-module-" + std::to_string(counter),
+                 M->getContext());
+  return M;
+}
+
+const Function* getGlobalInit(llvm::Module& M) {
+  for (const auto& Func: M)
+    if (Func.hasName() && Func.getName().startswith("_GLOBAL__sub_I_"))
+      return &Func;
+
+  return nullptr;
+}
+
+TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) {
+    LLVMContext Context;
+    CompilerInstance compiler;
+
+    compiler.createDiagnostics();
+    compiler.getLangOpts().CPlusPlus = 1;
+    compiler.getLangOpts().CPlusPlus11 = 1;
+
+    compiler.getTargetOpts().Triple = llvm::Triple::normalize(
+        llvm::sys::getProcessTriple());
+    compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
+      compiler.getDiagnostics(),
+      std::make_shared<clang::TargetOptions>(
+        compiler.getTargetOpts())));
+
+    compiler.createFileManager();
+    compiler.createSourceManager(compiler.getFileManager());
+    compiler.createPreprocessor(clang::TU_Prefix);
+    compiler.getPreprocessor().enableIncrementalProcessing();
+
+    compiler.createASTContext();
+
+    CodeGenerator* CG =
+        CreateLLVMCodeGen(
+            compiler.getDiagnostics(),
+            "main-module",
+            compiler.getHeaderSearchOpts(),
+            compiler.getPreprocessorOpts(),
+            compiler.getCodeGenOpts(),
+            Context);
+    compiler.setASTConsumer(std::unique_ptr<ASTConsumer>(CG));
+    compiler.createSema(clang::TU_Prefix, nullptr);
+    Sema& S = compiler.getSema();
+
+    std::unique_ptr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
+                                               /*SkipFunctionBodies*/ false));
+    Parser &P = *ParseOP.get();
+
+    std::array<std::unique_ptr<llvm::Module>, 3> M;
+    M[0] = IncrementalParseAST(compiler, P, *CG, nullptr);
+    ASSERT_TRUE(M[0]);
+
+    M[1] = IncrementalParseAST(compiler, P, *CG, TestProgram1);
+    ASSERT_TRUE(M[1]);
+    ASSERT_TRUE(M[1]->getFunction("funcForProg1"));
+
+    M[2] = IncrementalParseAST(compiler, P, *CG, TestProgram2);
+    ASSERT_TRUE(M[2]);
+    ASSERT_TRUE(M[2]->getFunction("funcForProg2"));
+    // First code should not end up in second module:
+    ASSERT_FALSE(M[2]->getFunction("funcForProg1"));
+
+    // Make sure global inits exist and are unique:
+    const Function* GlobalInit1 = getGlobalInit(*M[1]);
+    ASSERT_TRUE(GlobalInit1);
+
+    const Function* GlobalInit2 = getGlobalInit(*M[2]);
+    ASSERT_TRUE(GlobalInit2);
+
+    ASSERT_FALSE(GlobalInit1->getName() == GlobalInit2->getName());
+
+}
+
+} // end anonymous namespace




More information about the cfe-commits mailing list