2012-09-05 13:37:39 +04:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
# ifndef CLING_INCREMENTAL_PARSER_H
# define CLING_INCREMENTAL_PARSER_H
# include "clang/Basic/SourceLocation.h"
# include "llvm/ADT/OwningPtr.h"
2013-04-09 13:03:54 +04:00
# include "llvm/ADT/SmallVector.h"
2012-09-05 13:37:39 +04:00
# include "llvm/ADT/StringRef.h"
# include <vector>
2013-05-27 17:24:57 +04:00
# include <deque>
2012-09-05 13:37:39 +04:00
namespace llvm {
struct GenericValue ;
class MemoryBuffer ;
}
namespace clang {
class CodeGenerator ;
class CompilerInstance ;
2013-09-13 12:37:54 +04:00
class Decl ;
2012-09-05 13:37:39 +04:00
class FileID ;
class Parser ;
}
namespace cling {
2012-10-02 14:30:25 +04:00
class CompilationOptions ;
2012-09-05 13:37:39 +04:00
class CIFactory ;
class DeclCollector ;
class ExecutionContext ;
class Interpreter ;
2012-10-02 14:30:25 +04:00
class Transaction ;
2013-07-06 15:04:31 +04:00
class TransactionPool ;
2012-09-05 13:37:39 +04:00
class TransactionTransformer ;
///\brief Responsible for the incremental parsing and compilation of input.
///
/// The class manages the entire process of compilation line-by-line by
/// appending the compiled delta to clang'a AST. It provides basic operations
/// on the already compiled code. See cling::Transaction class.
///
class IncrementalParser {
private :
// our interpreter context
2013-04-09 13:04:30 +04:00
// FIXME: Get rid of that back reference to the interpreter.
2012-09-05 13:37:39 +04:00
Interpreter * m_Interpreter ;
// compiler instance.
llvm : : OwningPtr < clang : : CompilerInstance > m_CI ;
// parser (incremental)
llvm : : OwningPtr < clang : : Parser > m_Parser ;
// One buffer for each command line, owner by the source file manager
2013-08-18 12:49:14 +04:00
std : : deque < llvm : : MemoryBuffer * > m_MemoryBuffers ;
2012-09-05 13:37:39 +04:00
// file ID of the memory buffer
clang : : FileID m_VirtualFileID ;
// CI owns it
DeclCollector * m_Consumer ;
2013-05-27 17:24:57 +04:00
///\brief The storage for our transactions.
2012-09-05 13:37:39 +04:00
///
2013-05-27 17:24:57 +04:00
/// We don't need the elements to be contiguous in memory, that is why we
/// don't use std::vector. We don't need to copy the elements every time the
/// capacity is exceeded.
2012-10-19 18:17:20 +04:00
///
2013-05-27 17:24:57 +04:00
std : : deque < Transaction * > m_Transactions ;
2012-09-05 13:37:39 +04:00
///\brief Code generator
///
llvm : : OwningPtr < clang : : CodeGenerator > m_CodeGen ;
2013-06-26 22:51:05 +04:00
///\brief Contains the transaction AST transformers.
2012-09-05 13:37:39 +04:00
///
2013-06-26 22:51:05 +04:00
llvm : : SmallVector < TransactionTransformer * , 6 > m_ASTTransformers ;
///\brief Contains the transaction IR transformers.
///
llvm : : SmallVector < TransactionTransformer * , 2 > m_IRTransformers ;
2012-09-05 13:37:39 +04:00
2013-07-06 15:04:31 +04:00
///\brief Pool of reusable block-allocated transactions.
///
llvm : : OwningPtr < TransactionPool > m_TransactionPool ;
2012-09-05 13:37:39 +04:00
public :
enum EParseResult {
kSuccess ,
kSuccessWithWarnings ,
kFailed
} ;
IncrementalParser ( Interpreter * interp , int argc , const char * const * argv ,
const char * llvmdir ) ;
~ IncrementalParser ( ) ;
2014-03-04 22:02:42 +04:00
void Initialize ( llvm : : SmallVectorImpl < Transaction * > & result ) ;
2012-09-05 13:37:39 +04:00
clang : : CompilerInstance * getCI ( ) const { return m_CI . get ( ) ; }
clang : : Parser * getParser ( ) const { return m_Parser . get ( ) ; }
clang : : CodeGenerator * getCodeGenerator ( ) const { return m_CodeGen . get ( ) ; }
bool hasCodeGenerator ( ) const { return m_CodeGen . get ( ) ; }
/// \{
/// \name Transaction Support
///\brief Starts a transaction.
///
2012-11-15 02:06:58 +04:00
Transaction * beginTransaction ( const CompilationOptions & Opts ) ;
2012-09-05 13:37:39 +04:00
///\brief Finishes a transaction.
///
2013-07-06 15:04:31 +04:00
Transaction * endTransaction ( Transaction * T ) ;
2012-09-05 13:37:39 +04:00
2013-06-25 12:51:58 +04:00
///\brief Commits a transaction if it was complete. I.e pipes it
2012-09-05 13:37:39 +04:00
/// through the consumer chain, including codegen.
///
2013-06-25 12:51:58 +04:00
///\param[in] T - the transaction to be committed
2013-06-20 20:37:38 +04:00
///
2013-06-25 12:51:58 +04:00
void commitTransaction ( Transaction * T ) ;
///\brief Runs the consumers (e.g. CodeGen) on a transaction.
///
///\param[in] T - the transaction to be consumed
///
void codeGenTransaction ( Transaction * T ) ;
2012-09-05 13:37:39 +04:00
2014-03-24 15:02:41 +04:00
///\brief Reverts the interpreter into its previous state.
2012-09-05 13:37:39 +04:00
///
/// If one of the declarations caused error in clang it is rolled back from
/// the AST. This is essential feature for the error recovery subsystem.
2014-03-24 15:02:41 +04:00
/// Also this is a key entry point for the code unloading.
2012-09-05 13:37:39 +04:00
///
///\param[in] T - The transaction to be reverted from the AST
///
2014-03-24 15:02:41 +04:00
void rollbackTransaction ( Transaction * T ) ;
2012-09-05 13:37:39 +04:00
2012-10-19 18:17:20 +04:00
///\brief Returns the first transaction the incremental parser saw.
2012-09-05 13:37:39 +04:00
///
2013-05-27 17:24:57 +04:00
const Transaction * getFirstTransaction ( ) const {
if ( ! m_Transactions . size ( ) )
return 0 ;
return m_Transactions . front ( ) ;
2012-09-05 13:37:39 +04:00
}
///\brief Returns the last transaction the incremental parser saw.
///
2013-05-27 17:24:57 +04:00
Transaction * getLastTransaction ( ) {
if ( ! m_Transactions . size ( ) )
return 0 ;
return m_Transactions . back ( ) ;
2012-10-19 17:29:03 +04:00
}
2012-10-19 18:17:20 +04:00
///\brief Returns the last transaction the incremental parser saw.
2012-10-19 17:29:03 +04:00
///
2013-05-27 17:24:57 +04:00
const Transaction * getLastTransaction ( ) const {
if ( ! m_Transactions . size ( ) )
return 0 ;
return m_Transactions . back ( ) ;
2012-10-19 17:29:03 +04:00
}
2012-11-15 02:06:58 +04:00
///\brief Returns the list of transactions seen by the interpreter.
/// Intentionally makes a copy - that function is meant to be use for debug
/// purposes.
///
std : : vector < const Transaction * > getAllTransactions ( ) ;
2012-09-05 13:37:39 +04:00
/// \}
///\brief Compiles the given input with the given compilation options.
///
2012-10-15 17:42:09 +04:00
///\param[in] input - The code to compile.
///\param[in] Opts - The compilation options to use.
2012-11-20 07:26:52 +04:00
///\returns the declarations that were compiled.
2012-10-15 17:42:09 +04:00
///
2012-11-20 07:26:52 +04:00
Transaction * Compile ( llvm : : StringRef input , const CompilationOptions & Opts ) ;
2012-09-05 13:37:39 +04:00
///\brief Parses the given input without calling the custom consumers and
/// code generation.
///
/// I.e changes to the decls in the transaction commiting it will cause
/// different executable code.
///
///\param[in] input - The code to parse.
2012-10-15 17:42:09 +04:00
///\param[in] Opts - The compilation options to use.
///\returns The transaction corresponding to the input.
2012-09-05 13:37:39 +04:00
///
2012-10-15 17:42:09 +04:00
Transaction * Parse ( llvm : : StringRef input , const CompilationOptions & Opts ) ;
2012-09-05 13:37:39 +04:00
2013-07-06 15:02:49 +04:00
void printTransactionStructure ( ) const ;
2012-09-05 13:37:39 +04:00
2013-06-25 12:51:58 +04:00
///\brief Adds a UsedAttr to all decls in the transaction.
///
///\param[in] T - the transaction for which all decls will get a UsedAttr.
///
2013-06-27 16:30:07 +04:00
void markWholeTransactionAsUsed ( Transaction * T ) const ;
///\brief Runs the static initializers created by codegening a transaction.
///
///\param[in] T - the transaction for which to run the initializers.
///
bool runStaticInitOnTransaction ( Transaction * T ) const ;
2013-06-25 12:51:58 +04:00
2012-09-05 13:37:39 +04:00
private :
2013-06-27 16:30:07 +04:00
///\brief Runs AST transformers on a transaction.
///
///\param[in] T - the transaction to be transformed.
///
2013-08-08 13:22:29 +04:00
void transformTransactionAST ( Transaction * T ) ;
2013-06-27 16:30:07 +04:00
///\brief Runs IR transformers on a transaction.
///
///\param[in] T - the transaction to be transformed.
///
2014-03-24 15:02:41 +04:00
bool transformTransactionIR ( Transaction * T ) ;
2013-06-27 16:30:07 +04:00
2013-08-22 17:52:00 +04:00
///\brief Initializes a virtual file, which will be able to produce valid
/// source locations, with the proper offsets.
///
void initializeVirtualFile ( ) ;
///\brief The work horse for parsing. It queries directly clang.
///
///\param[in] input - The incremental input that needs to be parsed.
///
2012-09-05 13:37:39 +04:00
EParseResult ParseInternal ( llvm : : StringRef input ) ;
2013-08-26 19:59:33 +04:00
///\brief Return true if this decl (which comes from an AST file) should
/// not be sent to CodeGen. The module is assumed to describe the contents
/// of a library; symbols inside the library must thus not be reemitted /
/// duplicated by CodeGen.
///
2013-09-13 12:37:54 +04:00
bool shouldIgnore ( const clang : : Decl * D ) const ;
2012-09-05 13:37:39 +04:00
} ;
} // end namespace cling
# endif // CLING_INCREMENTAL_PARSER_H