Exemple #1
0
  void IncrementalParser::SetTransformers(bool isChildInterpreter) {
    // Add transformers to the IncrementalParser, which owns them
    Sema* TheSema = &m_CI->getSema();
    // Register the AST Transformers
    typedef std::unique_ptr<ASTTransformer> ASTTPtr_t;
    std::vector<ASTTPtr_t> ASTTransformers;
    ASTTransformers.emplace_back(new AutoSynthesizer(TheSema));
    ASTTransformers.emplace_back(new EvaluateTSynthesizer(TheSema));
    if (hasCodeGenerator() && !m_Interpreter->getOptions().NoRuntime) {
       // Don't protect against crashes if we cannot run anything.
       // cling might also be in a PCH-generation mode; don't inject our Sema pointer
       // into the PCH.
       ASTTransformers.emplace_back(new NullDerefProtectionTransformer(m_Interpreter));
    }

    typedef std::unique_ptr<WrapperTransformer> WTPtr_t;
    std::vector<WTPtr_t> WrapperTransformers;
    if (!m_Interpreter->getOptions().NoRuntime)
      WrapperTransformers.emplace_back(new ValuePrinterSynthesizer(TheSema));
    WrapperTransformers.emplace_back(new DeclExtractor(TheSema));
    if (!m_Interpreter->getOptions().NoRuntime)
      WrapperTransformers.emplace_back(new ValueExtractionSynthesizer(TheSema,
                                                           isChildInterpreter));
    WrapperTransformers.emplace_back(new CheckEmptyTransactionTransformer(TheSema));

    m_Consumer->SetTransformers(std::move(ASTTransformers),
                                std::move(WrapperTransformers));
  }
Exemple #2
0
  void IncrementalParser::codeGenTransaction(Transaction* T) {
    // codegen the transaction
    assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off");
    assert(T->getState() == Transaction::kCompleted && "Must be completed");
    assert(hasCodeGenerator() && "No CodeGen");

    // Could trigger derserialization of decls.
    Transaction* deserT = beginTransaction(CompilationOptions());


    // Commit this transaction first - T might need symbols from it, so
    // trigger emission of weak symbols by providing use.
    ParseResultTransaction PRT = endTransaction(deserT);
    commitTransaction(PRT);
    deserT = PRT.getPointer();

    // This llvm::Module is done; finalize it and pass it to the execution
    // engine.
    if (!T->isNestedTransaction() && hasCodeGenerator()) {
      // The initializers are emitted to the symbol "_GLOBAL__sub_I_" + filename.
      // Make that unique!
      deserT = beginTransaction(CompilationOptions());
      // Reset the module builder to clean up global initializers, c'tors, d'tors
      getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
      auto PRT = endTransaction(deserT);
      commitTransaction(PRT);
      deserT = PRT.getPointer();

      std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule());

      if (M) {
        m_Interpreter->addModule(M.get(), T->getCompilationOpts().OptLevel);
        T->setModule(std::move(M));
      }

      if (T->getIssuedDiags() != Transaction::kNone) {
        // Module has been released from Codegen, reset the Diags now.
        DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics();
        Diags.Reset(/*soft=*/true);
        Diags.getClient()->clear();
      }

      // Create a new module.
      StartModule();
    }
  }
Exemple #3
0
  void IncrementalParser::Initialize() {
    if (hasCodeGenerator())
      getCodeGenerator()->Initialize(getCI()->getASTContext());

    CompilationOptions CO;
    CO.DeclarationExtraction = 0;
    CO.ValuePrinting = CompilationOptions::VPDisabled;
    CO.CodeGeneration = hasCodeGenerator();

    // pull in PCHs
    const std::string& PCHFileName
      = m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude;
    if (!PCHFileName.empty()) {
      
      Transaction* CurT = beginTransaction(CO);
      m_CI->createPCHExternalASTSource(PCHFileName,
                                       true /*DisablePCHValidation*/,
                                       true /*AllowPCHWithCompilerErrors*/,
                                       0 /*DeserializationListener*/);
      Transaction* EndedT = endTransaction(CurT);
      commitTransaction(EndedT);
    }

    Transaction* CurT = beginTransaction(CO);
    Sema* TheSema = &m_CI->getSema();
    m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema,
                              false /*skipFuncBodies*/));
    m_CI->getPreprocessor().EnterMainSourceFile();
    // Initialize the parser after we have entered the main source file.
    m_Parser->Initialize();
    // Perform initialization that occurs after the parser has been initialized
    // but before it parses anything. Initializes the consumers too.
    TheSema->Initialize();

    ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
    if (External)
      External->StartTranslationUnit(m_Consumer);

    Transaction* EndedT = endTransaction(CurT);
    commitTransaction(EndedT);
  }
Exemple #4
0
  IncrementalParser::~IncrementalParser() {
    if (hasCodeGenerator()) {
      getCodeGenerator()->ReleaseModule();
    }
    const Transaction* T = getFirstTransaction();
    const Transaction* nextT = 0;
    while (T) {
      nextT = T->getNext();
      delete T;
      T = nextT;
    }

    for (size_t i = 0; i < m_TTransformers.size(); ++i)
      delete m_TTransformers[i];
  }
Exemple #5
0
  void IncrementalParser::codeGenTransaction(Transaction* T) {
    // codegen the transaction
    assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off");
    assert(hasCodeGenerator() && "No CodeGen");

    T->setModule(getCodeGenerator()->GetModule());

    for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) {
      // Copy DCI; it might get relocated below.
      Transaction::DelayCallInfo I = (*T)[Idx];

      if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
        getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
      else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) {
        // Usually through BackendConsumer which doesn't implement
        // HandleInterestingDecl() and thus calls
        // ASTConsumer::HandleInterestingDecl()
        getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
      } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) {
        TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleTagDeclDefinition(TD);
      }
      else if (I.m_Call == Transaction::kCCIHandleVTable) {
        CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true);
      }
      else if (I.m_Call
               == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) {
        FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD);
      }
      else if (I.m_Call
               == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) {
        VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD);
      }
      else if (I.m_Call == Transaction::kCCINone)
        ; // We use that internally as delimiter in the Transaction.
      else
        llvm_unreachable("We shouldn't have decl without call info.");
    }

    getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
  }
Exemple #6
0
  IncrementalParser::~IncrementalParser() {
    if (hasCodeGenerator()) {
      getCodeGenerator()->ReleaseModule();
    }
    const Transaction* T = getFirstTransaction();
    const Transaction* nextT = 0;
    while (T) {
      assert((T->getState() == Transaction::kCommitted 
              || T->getState() == Transaction::kRolledBack)
             && "Not committed?");
      nextT = T->getNext();
      delete T;
      T = nextT;
    }

    for (size_t i = 0; i < m_ASTTransformers.size(); ++i)
      delete m_ASTTransformers[i];

    for (size_t i = 0; i < m_IRTransformers.size(); ++i)
      delete m_IRTransformers[i];
  }
Exemple #7
0
  void IncrementalParser::commitTransaction(Transaction* T) {
    //Transaction* CurT = m_Consumer->getTransaction();
    assert(T->isCompleted() && "Transaction not ended!?");
    assert(T->getState() != Transaction::kCommitted
           && "Committing an already committed transaction.");

    // Check for errors...
    if (T->getIssuedDiags() == Transaction::kErrors) {
      rollbackTransaction(T);
      return;
    }

    if (T->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        if ((*I)->getState() != Transaction::kCommitted)
          commitTransaction(*I);
    }

    // We are sure it's safe to pipe it through the transformers
    bool success = true;
    for (size_t i = 0; i < m_TTransformers.size(); ++i) {
      success = m_TTransformers[i]->TransformTransaction(*T);
      if (!success) {
        break;
      }
    }

    m_CI->getDiagnostics().Reset(); // FIXME: Should be in rollback transaction.

    if (!success) {
      // Roll back on error in a transformer
      rollbackTransaction(T);
      return;
    }

    // Pull all template instantiations in that came from the consumers.
    getCI()->getSema().PerformPendingInstantiations();

    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      // codegen the transaction
      for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) {
        // Copy DCI; it might get relocated below.
        Transaction::DelayCallInfo I = (*T)[Idx];
        if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
          getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
        else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) {
          // Usually through BackendConsumer which doesn't implement
          // HandleInterestingDecl() and thus calls
          // ASTConsumer::HandleInterestingDecl()
          getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
        } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) {
          TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleTagDeclDefinition(TD);
        }
        else if (I.m_Call == Transaction::kCCIHandleVTable) {
          CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true);
        }
        else if (I.m_Call
                 == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) {
          FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD);
        }
        else if (I.m_Call
                 == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) {
          VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD);
        }
        else if (I.m_Call == Transaction::kCCINone)
          ; // We use that internally as delimiter in the Transaction.
        else
          llvm_unreachable("We shouldn't have decl without call info.");
      }

      getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
      T->setModule(getCodeGenerator()->GetModule());

      // The static initializers might run anything and can thus cause more
      // decls that need to end up in a transaction. But this one is done
      // with CodeGen...
      T->setState(Transaction::kCommitting);

      // run the static initializers that came from codegenning
      if (m_Interpreter->runStaticInitializersOnce()
          >= Interpreter::kExeFirstError) {
        // Roll back on error in a transformer
        rollbackTransaction(T);
        return;
      }
    } else
      T->setState(Transaction::kCommitting);

    InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();

    if (callbacks) {
      callbacks->TransactionCommitted(*T);
    }
    if (T->hasNestedTransactions()) {
      Transaction* SubTransactionWhileCommitting = *T->rnested_begin();
      if (SubTransactionWhileCommitting->getState()
          == Transaction::kCollecting) {
        // A nested transaction was created while committing this
        // transaction; commit it now.
        SubTransactionWhileCommitting->setState(Transaction::kCompleted);
        commitTransaction(SubTransactionWhileCommitting);
      }
    }

    T->setState(Transaction::kCommitted);

    // If the transaction is empty do nothing.
    // Except it was nested transaction and we want to reuse it later on.
    if (T->empty() && T->isNestedTransaction()) {
      // We need to remove the marker from its parent.
      Transaction* ParentT = T->getParent();
      for (size_t i = 0; i < ParentT->size(); ++i)
        if ((*ParentT)[i].m_DGR.isNull())
          ParentT->erase(i);
    }

    if (T->isNestedTransaction()) {
      // TODO: Add proper logic in the case where there are multiple nested
      // transaction. This now won't handle the case where there are more than
      // one level 1 nested transactions.
      m_Consumer->setTransaction(T->getParent());
    }
  }
Exemple #8
0
  void IncrementalParser::commitTransaction(Transaction* T) {
    //Transaction* CurT = m_Consumer->getTransaction();
    assert(T->isCompleted() && "Transaction not ended!?");
    assert(T->getState() != Transaction::kCommitted
           && "Committing an already committed transaction.");

    // If committing a nested transaction the active one should be its parent
    // from now on.
    if (T->isNestedTransaction())
      m_Consumer->setTransaction(T->getParent());

    // Check for errors...
    if (T->getIssuedDiags() == Transaction::kErrors) {
      rollbackTransaction(T);
      return;
    }

    if (T->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        if ((*I)->getState() != Transaction::kCommitted)
          commitTransaction(*I);
    }

    if (!transformTransactionAST(T))
      return;

    // Here we expect a template instantiation. We need to open the transaction
    // that we are currently work with.
    Transaction::State oldState = T->getState();
    T->setState(Transaction::kCollecting);
    // Pull all template instantiations in that came from the consumers.
    getCI()->getSema().PerformPendingInstantiations();
    T->setState(oldState);

    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      codeGenTransaction(T);
      transformTransactionIR(T);
    }

    // The static initializers might run anything and can thus cause more
    // decls that need to end up in a transaction. But this one is done
    // with CodeGen...
    T->setState(Transaction::kCommitted);

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      runStaticInitOnTransaction(T);
    }

    InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();

    if (callbacks)
      callbacks->TransactionCommitted(*T);

    // If the transaction is empty do nothing.
    // Except it was nested transaction and we want to reuse it later on.
    if (T->empty() && T->isNestedTransaction()) {
      // We need to remove the marker from its parent.
      Transaction* ParentT = T->getParent();
      for (size_t i = 0; i < ParentT->size(); ++i)
        if ((*ParentT)[i].m_DGR.isNull())
          ParentT->erase(i);
    }
  }
Exemple #9
0
  void IncrementalParser::commitTransaction(ParseResultTransaction& PRT,
                                            bool ClearDiagClient) {
    Transaction* T = PRT.getPointer();
    if (!T) {
      if (PRT.getInt() != kSuccess) {
        // Nothing has been emitted to Codegen, reset the Diags.
        DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics();
        Diags.Reset(/*soft=*/true);
        if (ClearDiagClient)
          Diags.getClient()->clear();
      }
      return;
    }

    assert(T->isCompleted() && "Transaction not ended!?");
    assert(T->getState() != Transaction::kCommitted
           && "Committing an already committed transaction.");
    assert((T->getIssuedDiags() == Transaction::kErrors || !T->empty())
           && "Valid Transactions must not be empty;");

    // If committing a nested transaction the active one should be its parent
    // from now on.
    if (T->isNestedTransaction())
      m_Consumer->setTransaction(T->getParent());

    // Check for errors...
    if (T->getIssuedDiags() == Transaction::kErrors) {
      // Make module visible to TransactionUnloader.
      bool MustStartNewModule = false;
      if (!T->isNestedTransaction() && hasCodeGenerator()) {
        MustStartNewModule = true;
        std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule());

        if (M) {
          T->setModule(std::move(M));
        }
      }
      // Module has been released from Codegen, reset the Diags now.
      DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics();
      Diags.Reset(/*soft=*/true);
      if (ClearDiagClient)
        Diags.getClient()->clear();

      PRT.setPointer(nullptr);
      PRT.setInt(kFailed);
      m_Interpreter->unload(*T);

      // Create a new module if necessary.
      if (MustStartNewModule)
        StartModule();

      return;
    }

    if (T->hasNestedTransactions()) {
      Transaction* TopmostParent = T->getTopmostParent();
      EParseResult PR = kSuccess;
      if (TopmostParent->getIssuedDiags() == Transaction::kErrors)
        PR = kFailed;
      else if (TopmostParent->getIssuedDiags() == Transaction::kWarnings)
        PR = kSuccessWithWarnings;

      for (Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        if ((*I)->getState() != Transaction::kCommitted) {
          ParseResultTransaction PRT(*I, PR);
          commitTransaction(PRT);
        }
    }

    // If there was an error coming from the transformers.
    if (T->getIssuedDiags() == Transaction::kErrors) {
      m_Interpreter->unload(*T);
      return;
    }

    // Here we expect a template instantiation. We need to open the transaction
    // that we are currently work with.
    {
      Transaction* prevConsumerT = m_Consumer->getTransaction();
      m_Consumer->setTransaction(T);
      Transaction* nestedT = beginTransaction(T->getCompilationOpts());
      // Pull all template instantiations in that came from the consumers.
      getCI()->getSema().PerformPendingInstantiations();
      ParseResultTransaction nestedPRT = endTransaction(nestedT);
      commitTransaction(nestedPRT);
      m_Consumer->setTransaction(prevConsumerT);
    }
    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());


    // The static initializers might run anything and can thus cause more
    // decls that need to end up in a transaction. But this one is done
    // with CodeGen...
    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      Transaction* prevConsumerT = m_Consumer->getTransaction();
      m_Consumer->setTransaction(T);
      codeGenTransaction(T);
      T->setState(Transaction::kCommitted);
      if (!T->getParent()) {
        if (m_Interpreter->executeTransaction(*T)
            >= Interpreter::kExeFirstError) {
          // Roll back on error in initializers.
          // T maybe pointing to freed memory after this call:
          // Interpreter::unload
          //   IncrementalParser::deregisterTransaction
          //     TransactionPool::releaseTransaction
          m_Interpreter->unload(*T);
          return;
        }
      }
      m_Consumer->setTransaction(prevConsumerT);
    }
    T->setState(Transaction::kCommitted);

    if (InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks())
      callbacks->TransactionCommitted(*T);

  }
Exemple #10
0
  bool
  IncrementalParser::Initialize(llvm::SmallVectorImpl<ParseResultTransaction>&
                                result, bool isChildInterpreter) {
    m_TransactionPool.reset(new TransactionPool);
    if (hasCodeGenerator())
      getCodeGenerator()->Initialize(getCI()->getASTContext());

    CompilationOptions CO = m_Interpreter->makeDefaultCompilationOpts();
    Transaction* CurT = beginTransaction(CO);
    Preprocessor& PP = m_CI->getPreprocessor();
    DiagnosticsEngine& Diags = m_CI->getSema().getDiagnostics();

    // Pull in PCH.
    const std::string& PCHFileName
      = m_CI->getInvocation().getPreprocessorOpts().ImplicitPCHInclude;
    if (!PCHFileName.empty()) {
      Transaction* PchT = beginTransaction(CO);
      DiagnosticErrorTrap Trap(Diags);
      m_CI->createPCHExternalASTSource(PCHFileName,
                                       true /*DisablePCHValidation*/,
                                       true /*AllowPCHWithCompilerErrors*/,
                                       0 /*DeserializationListener*/,
                                       true /*OwnsDeserializationListener*/);
      result.push_back(endTransaction(PchT));
      if (Trap.hasErrorOccurred()) {
        result.push_back(endTransaction(CurT));
        return false;
      }
    }

    addClingPragmas(*m_Interpreter);

    // Must happen after attaching the PCH, else PCH elements will end up
    // being lexed.
    PP.EnterMainSourceFile();

    Sema* TheSema = &m_CI->getSema();
    m_Parser.reset(new Parser(PP, *TheSema, false /*skipFuncBodies*/));

    // Initialize the parser after PP has entered the main source file.
    m_Parser->Initialize();

    ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
    if (External)
      External->StartTranslationUnit(m_Consumer);

    // Start parsing the "main file" to warm up lexing (enter caching lex mode
    // for ParseInternal()'s call EnterSourceFile() to make sense.
    while (!m_Parser->ParseTopLevelDecl()) {}

    // If I belong to the parent Interpreter, am using C++, and -noruntime
    // wasn't given on command line, then #include <new> and check ABI
    if (!isChildInterpreter && m_CI->getLangOpts().CPlusPlus &&
        !m_Interpreter->getOptions().NoRuntime) {
      // <new> is needed by the ValuePrinter so it's a good thing to include it.
      // We need to include it to determine the version number of the standard
      // library implementation.
      ParseInternal("#include <new>");
      // That's really C++ ABI compatibility. C has other problems ;-)
      CheckABICompatibility(*m_Interpreter);
    }

    // DO NOT commit the transactions here: static initialization in these
    // transactions requires gCling through local_cxa_atexit(), but that has not
    // been defined yet!
    ParseResultTransaction PRT = endTransaction(CurT);
    result.push_back(PRT);
    return true;
  }