2017-03-20 01:03:53 +03:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
//
// 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.
//------------------------------------------------------------------------------
2017-03-20 00:46:38 +03:00
# include <cling/Interpreter/Interpreter.h>
# include <cling/Interpreter/Value.h>
2017-03-21 23:02:24 +03:00
# include <cling/Utils/Casting.h>
2017-03-20 00:46:38 +03:00
# include <iostream>
# include <string>
# include <sstream>
2017-03-21 23:02:24 +03:00
/// Definitions of declarations injected also into cling.
/// NOTE: this could also stay in a header #included here and into cling, but
/// for the sake of simplicity we just redeclare them here.
int aGlobal = 42 ;
static float anotherGlobal = 3.141 ;
2017-03-31 17:35:37 +03:00
float getAnotherGlobal ( ) { return anotherGlobal ; }
2017-03-21 23:02:24 +03:00
void setAnotherGlobal ( float val ) { anotherGlobal = val ; }
///\brief Call compiled functions from the interpreter.
void useHeader ( cling : : Interpreter & interp ) {
// We could use a header, too...
interp . declare ( " int aGlobal; \n "
" float getAnotherGlobal(); \n "
" void setAnotherGlobal(float val); \n " ) ;
cling : : Value res ; // Will hold the result of the expression evaluation.
interp . process ( " aGlobal; " , & res ) ;
std : : cout < < " aGlobal is " < < res . getAs < long long > ( ) < < ' \n ' ;
interp . process ( " getAnotherGlobal(); " , & res ) ;
std : : cout < < " getAnotherGlobal() returned " < < res . getAs < float > ( ) < < ' \n ' ;
setAnotherGlobal ( 1. ) ; // We modify the compiled value,
interp . process ( " getAnotherGlobal(); " , & res ) ; // does the interpreter see it?
std : : cout < < " getAnotherGlobal() returned " < < res . getAs < float > ( ) < < ' \n ' ;
// We modify using the interpreter, now the binary sees the new value.
interp . process ( " setAnotherGlobal(7.777); getAnotherGlobal(); " ) ;
std : : cout < < " getAnotherGlobal() returned " < < getAnotherGlobal ( ) < < ' \n ' ;
2017-03-20 00:46:38 +03:00
}
2017-03-21 23:02:24 +03:00
///\brief Call an interpreted function using its symbol address.
void useSymbolAddress ( cling : : Interpreter & interp ) {
// Declare a function to the interpreter. Make it extern "C" to remove
// mangling from the game.
interp . declare ( " extern \" C \" int plutification(int siss, int sat) "
" { return siss * sat; } " ) ;
void * addr = interp . getAddressOfGlobal ( " plutification " ) ;
using func_t = int ( int , int ) ;
func_t * pFunc = cling : : utils : : VoidToFunctionPtr < func_t * > ( addr ) ;
std : : cout < < " 7 * 8 = " < < pFunc ( 7 , 8 ) < < ' \n ' ;
}
2017-03-20 00:46:38 +03:00
2017-03-21 23:02:24 +03:00
///\brief Pass a pointer into cling as a string.
void usePointerLiteral ( cling : : Interpreter & interp ) {
int res = 17 ; // The value that will be modified
// Update the value of res by passing it to the interpreter.
std : : ostringstream sstr ;
2018-03-22 15:34:29 +03:00
// on Windows, to prefix the hexadecimal value of a pointer with '0x',
// one need to write: std::hex << std::showbase << (size_t)pointer
sstr < < " int& ref = *(int*) " < < std : : hex < < std : : showbase < < ( size_t ) & res < < ' ; ' ;
2017-03-21 23:02:24 +03:00
sstr < < " ref = ref * ref; " ;
interp . process ( sstr . str ( ) ) ;
std : : cout < < " The square of 17 is " < < res < < ' \n ' ;
2017-03-20 00:46:38 +03:00
}
int main ( int argc , const char * const * argv ) {
2017-03-21 23:02:24 +03:00
// Create the Interpreter. LLVMDIR is provided as -D during compilation.
cling : : Interpreter interp ( argc , argv , LLVMDIR ) ;
2017-03-20 00:46:38 +03:00
2017-03-21 23:02:24 +03:00
useHeader ( interp ) ;
useSymbolAddress ( interp ) ;
usePointerLiteral ( interp ) ;
2017-03-20 00:46:38 +03:00
2017-03-21 23:02:24 +03:00
return 0 ;
2017-03-20 00:46:38 +03:00
}