All pastes #2055981 Raw Edit

mattst88

public text v1 · immutable
#2055981 ·published 2011-05-10 01:13 UTC
rendered paste body
#ifdef __cplusplus
extern "C" {
#endif
#include "vm_local.h"
#ifdef __cplusplus
}
#endif

#include "vm_llvm.h"

#define INT64_C(C)  ((int64_t) C ## LL) 
#define UINT64_C(C) ((uint64_t) C ## ULL) 

#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#include <llvm/Module.h>
#include <llvm/LLVMContext.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/PassManager.h>
#include <llvm/Target/TargetSelect.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/JIT.h>

using namespace llvm;

#ifdef __cplusplus
extern "C" {
#endif

static ExecutionEngine *engine = NULL;

void *VM_LoadLLVM( vm_t *vm, intptr_t (*systemcalls)(intptr_t, ...) ) {
	char name[MAX_QPATH];
	char filename[MAX_QPATH];
	int len;
	char *bytes;
	std::string error;

	COM_StripExtension( vm->name, name, sizeof(name) );
	Com_sprintf( filename, sizeof(filename), "%sllvm.bc", name );
	len = FS_ReadFile( filename, (void **)&bytes );

	if ( !bytes ) {
		Com_Printf( "Couldn't load llvm file: %s\n", filename );
		return NULL;
	}

	StringRef strref = StringRef(bytes, len);
	MemoryBuffer *buffer = MemoryBuffer::getMemBuffer( strref );
	Module *module = ParseBitcodeFile( buffer, getGlobalContext(), &error );
	delete buffer;
	FS_FreeFile( bytes );

	if ( !module ) {
		Com_Printf( "Couldn't parse llvm file: %s: %s\n", filename, error.c_str() );
		return NULL;
	}

	PassManager p;
	p.add( new TargetData( module ) );
	p.add( createFunctionInliningPass() );
	p.run( *module );

	if ( !engine ) {
		InitializeNativeTarget();

		std::string str;
		engine = ExecutionEngine::create( module, false, &str );
		if ( !engine ) {
			Com_Printf("Couldn't create ExecutionEngine: %s\n", str.c_str());
			return NULL;
		}		
	} else {
		Com_Printf("Engine was non-null\n");
		engine->addModule( module );
	}

	Function *dllEntry_ptr = module->getFunction( std::string("dllEntry") );
	if ( !dllEntry_ptr ) {
		Com_Printf("Couldn't get function address of dllEntry\n");
		return NULL;
	}
	void  (*dllEntry)( intptr_t (*syscallptr)(intptr_t, ...) ) = (void (*)(intptr_t (*syscallptr)(intptr_t, ...)))engine->getPointerToFunction( dllEntry_ptr );
	dllEntry( systemcalls );

	Com_Printf("1: got here\n");
	Function *vmMain_ptr = module->getFunction( std::string("vmMain") );
	Com_Printf("2: got here\n");
	if ( !vmMain_ptr ) {
		Com_Printf("Couldn't get function address of vmMain\n");
		return NULL;
	}
	Com_Printf("3: got here\n");
	intptr_t(*fp)(int, ...) = (intptr_t(*)(int, ...))engine->getPointerToFunction( vmMain_ptr );
	Com_Printf("4: got here\n");

	vm->entryPoint = fp;

	if ( com_developer->integer ) {
		Com_Printf("Loaded LLVM %s with module==%p\n", name, module);
	}

	return module;
}

void VM_UnloadLLVM( void *llvmModule ) {
	if ( !llvmModule ) {
		Com_Printf( "VM_UnloadLLVM called with NULL pointer\n" );
		return;
	}

	if ( com_developer->integer ) {
		Com_Printf( "Unloading LLVM with module==%p\n", llvmModule );
	}

	if ( !engine->removeModule( (Module *)llvmModule ) ) {
		Com_Printf( "Couldn't remove llvm\n" );
		return;
	}
	delete (Module *)llvmModule;
}

#ifdef __cplusplus
}
#endif