[cfe-dev] Function Redefinition

David PirrĂ² david.pirro at gmail.com
Mon Nov 15 08:56:09 PST 2010


Dear List,

I have a problem.
I've written a short test program basing on the Clan interpreter example.
The aim of the program is to input from commandline cpp file names that are compiled and jitted.
The cpp files contain function definitions.
like:
in file input01.cpp:
#include <stdio.h>
void test1() {	printf("Function One\n");};

in file input02.cpp:
#include <stdio.h>
void test2() {	printf("Function Two\n");};

I take the function pointers from the jitted code and then evaluate the functions.
This works but, 
if I input 2 times the same file from the command line (while program is running) after having modified for example file input02.cpp to:

#include <stdio.h>
void test2() {	printf("Function Two Modified\n");};

the program somehow doesn't recompile the file.
So I get in the output:
"Function Two"
instead of 
"Function Two Modified"
This even if I change the name of the function in input02.cpp

Do you know how to do this?

Further I would like to redefine functions.
That is, if I tell the program to compile and run the file input03.cpp:
#include <stdio.h>
void test1() {	printf("Function One Modified\n");};
with a function definition with the same name of the function in input01.cpp, 
I would like to redefine the function previously defined.
My idea would be to store in the program in a container function names associated to the actual function pointers.
Then check if the newly compiled function has same name and arguments, then "dropAllReferences()" etc. of the previous function and redefine the function.
Are there better ways to do this?
Do you have any examples doing this?

Thank you very much for your help.

Here is the little program:

int main(int argc, const char **argv) {

	char str[1024];
	char *opt = "-v";
	std::string Error;
	
	char *cargv[2];
	cargv[0] = str;
	cargv[1] = opt;
	
	void (*testf)();
	void (*testf2)();	
	
	llvm::ExecutionEngine *EE;
	
	CompilerInstance CI;
	CI.createDiagnostics(0, NULL);
	Diagnostic &diag = CI.getDiagnostics();	
	TextDiagnosticPrinter *tdp = new TextDiagnosticPrinter(llvm::errs(), CI.getDiagnosticOpts());
	diag.setClient(tdp);
	CompilerInvocation::CreateFromArgs(CI.getInvocation(), argv + 1, argv + argc, diag);
	
	
	  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
	  llvm::sys::Path Path = GetExecutablePath(argv[0]);
	  CI.setLLVMContext(new llvm::LLVMContext);

  // Infer the builtin include path if unspecified.
  if (CI.getHeaderSearchOpts().UseBuiltinIncludes &&
      CI.getHeaderSearchOpts().ResourceDir.empty())
    CI.getHeaderSearchOpts().ResourceDir =
      CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
	
  // Create and execute the frontend to generate an LLVM bitcode module.
  llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());
  if (!CI.ExecuteAction(*Act))
    return 1;

	if (llvm::Module *Module = Act->takeModule()) {
		llvm::InitializeNativeTarget();
		EE = llvm::ExecutionEngine::createJIT(Module, &Error);
		llvm::Function *func = Module->getFunctionList().begin();
		void *ptrtestf = EE->getPointerToFunction(func);
		testf = (void (*) ())ptrtestf;
		testf();		
	}


	while (1) {
		llvm::errs() << ">>>";
		std::cin.width (1024);        // limit width
		std::cin >> str;
		
		CompilerInvocation::CreateFromArgs(CI.getInvocation(), cargv, cargv + 1, diag);		

		llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());

		CI.ExecuteAction(*Act);
		if (llvm::Module *Module = Act->takeModule()) {
			
			llvm::Function *func = Module->getFunctionList().begin();

			void *ptrtestf = EE->getPointerToFunction(func);
			testf2= (void (*) ())ptrtestf;			
			testf2();
			testf();
		}		
	};

  // Shutdown.

  llvm::llvm_shutdown();

  return 0;
}

David






More information about the cfe-dev mailing list