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()); } }
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); } }