Function * futamurize( const Function * orig_func, DenseMap<const Value*, Value*> &argmap, std::set<const unsigned char *> &constant_addresses_set )
{
	LLVMContext &context = getGlobalContext();
	
	
	// Make a copy of the function, removing constant arguments
	Function * specialized_func = CloneFunction( orig_func, argmap );
	specialized_func->setName( orig_func->getNameStr() + "_1" );
	
	// add it to our module
	LLVM_Module->getFunctionList().push_back( specialized_func );
	
	printf("\nspecialized_func = %p <%s>\n", specialized_func, specialized_func->getName().data());
	//~ specialized_func->dump();

	// Optimize it
	FunctionPassManager PM( LLVM_Module );
	createStandardFunctionPasses( &PM, 3 );
	
	PM.add(createScalarReplAggregatesPass());  // Break up aggregate allocas
	PM.add(createInstructionCombiningPass());  // Cleanup for scalarrepl.
	PM.add(createJumpThreadingPass());         // Thread jumps.
	PM.add(createCFGSimplificationPass());     // Merge & remove BBs
	PM.add(createInstructionCombiningPass());  // Combine silly seq's
	PM.add(createTailCallEliminationPass());   // Eliminate tail calls
	PM.add(createCFGSimplificationPass());     // Merge & remove BBs
	PM.add(createReassociatePass());           // Reassociate expressions
	PM.add(createLoopRotatePass());            // Rotate Loop
	PM.add(createLICMPass());                  // Hoist loop invariants
	PM.add(createLoopUnswitchPass( false ));
	PM.add(createInstructionCombiningPass());
	PM.add(createIndVarSimplifyPass());        // Canonicalize indvars
	PM.add(createLoopDeletionPass());          // Delete dead loops
	PM.add(createLoopUnroll2Pass());            // Unroll small loops
	PM.add(createInstructionCombiningPass());  // Clean up after the unroller
	PM.add(createGVNPass());                   // Remove redundancies
	PM.add(createMemCpyOptPass());             // Remove memcpy / form memset
	PM.add(createSCCPPass());                  // Constant prop with SCCP
	PM.add(createPromoteMemoryToRegisterPass()); 
	PM.add(createConstantPropagationPass());            
	PM.add(createDeadStoreEliminationPass());            
	PM.add(createAggressiveDCEPass());            
	PM.add(new MemoryDependenceAnalysis());            
	//~ PM.add(createAAEvalPass());              
	
	const PassInfo * pinfo = Pass::lookupPassInfo( "print-alias-sets" );
	if( !pinfo ) { printf( "print-alias-sets not found\n" ); exit(-1); }
	PM.add( pinfo->createPass() );
	
	FunctionPassManager PM_Inline( LLVM_Module );
	PM_Inline.add(createSingleFunctionInliningPass());            
	
	bool Changed = false;
	int iterations = 2;
	int inline_iterations = 6;
	
	do
	{
		Changed = false;
		
		// first do some optimizations
		PM.doInitialization();
		PM.run( *specialized_func );
		PM.doFinalization();
		
		// Load from Constant Memory detection
		const TargetData *TD = LLVM_EE->getTargetData();
		
		for (inst_iterator I = inst_begin(specialized_func), E = inst_end(specialized_func); I != E; ++I) 
		{
			Instruction * inst = (Instruction *) &*I;

			// get all Load instructions
			LoadInst * load = dyn_cast<LoadInst>( inst );
			if( !load ) continue;
			if( load->isVolatile() ) continue;

			if (load->use_empty()) continue;        // Don't muck with dead instructions...

			// get the address loaded by load instruction
			Value *ptr_value = load->getPointerOperand();
			
			// we're only interested in constant addresses
			ConstantExpr * ptr_constant_expr =  dyn_cast<ConstantExpr>( ptr_value );
			if( !ptr_constant_expr ) continue;			
			ptr_constant_expr->dump();
			
			// compute real address of constant pointer expression
			Constant * ptr_constant = ConstantFoldConstantExpression( ptr_constant_expr, TD );
			if( !ptr_constant ) continue;
			ptr_constant->dump();
			
			// convert to int constant
			ConstantInt *int_constant =  dyn_cast<ConstantInt>( ConstantExpr::getPtrToInt( ptr_constant, Type::getInt64Ty( context )));
			if( !int_constant ) continue;
			int_constant->dump();
			
			// get data size
			int data_length = TD->getTypeAllocSize( load->getType() );
			ptr_value->getType()->dump();
			
			// get real address (at last !)
			const unsigned char * c_ptr = (const unsigned char *) int_constant->getLimitedValue();
			
			printf( "%ld %d %d\n", c_ptr, constant_addresses_set.count( c_ptr ), data_length );
			
			// check what's in this address	
			int isconst = 1;
			for( int offset=0; offset<data_length; offset++ )
				isconst &= constant_addresses_set.count( c_ptr + offset );
			
			if( !isconst ) continue;
			printf( "It is constant.\n" );
			
			// make a LLVM const with the data
			Constant *new_constant = NULL;
			switch( data_length )
			{
				case 1:	new_constant = ConstantInt::get( Type::getInt8Ty( context ),  *(uint8_t*)c_ptr, false /* signed */ );	break;
				case 2:	new_constant = ConstantInt::get( Type::getInt16Ty( context ), *(uint16_t*)c_ptr, false /* signed */ );	break;
				case 4:	new_constant = ConstantInt::get( Type::getInt32Ty( context ), *(uint32_t*)c_ptr, false /* signed */ );	break;
				case 8:	new_constant = ConstantInt::get( Type::getInt64Ty( context ), *(uint64_t*)c_ptr, false /* signed */ );	break;
				default:
				{
					StringRef const_data ( (const char *) c_ptr, data_length );
					new_constant = ConstantArray::get( context, const_data, false /* dont add terminating null */ );
				}
			}
			
			if( !new_constant ) continue;
			
			new_constant->dump();
							
			//~ // get the type that is loaded
			const Type *Ty = load->getType();
			
			// do we need a cast ?
			if( load->getType() != new_constant->getType() )
			{
				new_constant = ConstantExpr::getBitCast( new_constant, Ty );
				new_constant->dump();
			}
			
			// zap the load and replace with constant address
			load->replaceAllUsesWith( new_constant );
			printf( "\nREPLACED :...\n" );
			load->dump();
			new_constant->dump();
			
			Changed = true;
		}	
		
		if( Changed )
			continue;	// re-optimize and do another pass of constant load elimination
		
		// if we can't do anything else, do an inlining pass
		if( inline_iterations > 0 )
		{
			inline_iterations --;
			
			PM_Inline.doInitialization();
			Changed |= PM_Inline.run( *specialized_func );
			PM_Inline.doFinalization();

			//~ for( int i=0; i<3; i++ )
			{
				PM.doInitialization();
				Changed |= PM.run( *specialized_func );
				PM.doFinalization();
			}
		}
		
		if( iterations>0 && !Changed ) 
			iterations--;
	} while( Changed || iterations>0 );
	
	return specialized_func;
}
示例#2
0
void CouchRunner::runIR( CouchWorkingMemory *wm ){
  /*
  Module *theM;
  theM = ParseBitcodeFile( MemoryBuffer::getFile("out.bc"), 
			   getGlobalContext(),
			   &error );
  */

  // Loads intermediate representation source
  std::string error;
  SMDiagnostic Err;
  std::auto_ptr<Module> theM(ParseAssemblyFile( fSourceFile, Err, getGlobalContext() ));
  std::cout << "KBVM v1.0 (experimental)\nIntermediate Representation Interpreter\n";  
  std::cout << "Parsing " << fSourceFile << "\n";
  // Verifies module
  try{
    std::string VerifErr;
    if (verifyModule( *theM.get(), ReturnStatusAction, &VerifErr)) {
      errs() << fSourceFile
	     << ": assembly parsed, but does not verify as correct!\n";
      errs() << VerifErr;
      return;
    }
  }
  catch(...){
    std::cerr << "Verification of module failed!\n";
    return;
  }
  // Prepares to execute
  S_wm = wm;

  IRBuilder<>  theBuilder( getGlobalContext() );
  // Create the JIT.
  S_TheExecutionEngine = ExecutionEngine::create(theM.get());

  //ExistingModuleProvider OurModuleProvider( M );
  FunctionPassManager OurFPM( theM.get() );
      
  // Set up the optimizer pipeline.  
  // Start with registering info about how the
  // target lays out data structures.
  OurFPM.add(new TargetData(*S_TheExecutionEngine->getTargetData()));
  // Promote allocas to registers.
  OurFPM.add(createPromoteMemoryToRegisterPass());
  // Do simple "peephole" optimizations and bit-twiddling optzns.
  OurFPM.add(createInstructionCombiningPass());
  // Reassociate expressions.
  OurFPM.add(createReassociatePass());
  // Eliminate Common SubExpressions.
  OurFPM.add(createGVNPass());
  // Simplify the control flow graph (deleting unreachable blocks, etc).
  OurFPM.add(createCFGSimplificationPass());

  // Set the global so the code gen can use this.
  S_TheFPM = &OurFPM;

  // Inital setup of the agenda
  unsigned int i;
  CouchRunner::S_Agenda->reset();

  // Initial setup of the working memory
  S_TheFPM->run( *theM->getFunction("ag_forward") );

  std::string sign, val;
  Function *FFwrd = S_TheExecutionEngine->FindFunctionNamed( "ag_forward" );
  void *FFwrdPtr = S_TheExecutionEngine->getPointerToFunction(FFwrd);
  void (*FFwrdP)(const char*) = (void (*)( const char*))FFwrdPtr;
  DOMElement *elt;

  DOMNodeList *domSuggests = 
    fDom->getElementsByTagName( XMLString::transcode("suggest") );
  for( i = 0; i < domSuggests->getLength(); i++ ){
    CouchRunner::S_Agenda->push( std::string(XMLString::transcode( ((DOMText *)(domSuggests->item(i)->getFirstChild()))->getData() )), S_wm );
  }

  DOMNodeList *domVolunteers = 
    fDom->getElementsByTagName( XMLString::transcode("volunteer") );
  for( i = 0; i < domVolunteers->getLength(); i++ ){
    elt = (DOMElement *)(domVolunteers->item(i));
    sign = std::string( XMLString::transcode( ((DOMText *)(elt->getElementsByTagName(XMLString::transcode("var"))->item(0)->getFirstChild()))->getData() ) );
    val = std::string( XMLString::transcode( ((DOMText *)(elt->getElementsByTagName(XMLString::transcode("const"))->item(0)->getFirstChild()))->getData() ) );
    // TODO: update with type information
    if( std::string("true") == val ){
      S_wm->set( sign.c_str(), (int)1 );
    }
    else if( std::string("false") == val ){
      S_wm->set( sign.c_str(), (int)0 );
    }
    else if( isalpha( *(val.c_str()) ) ){
      S_wm->set( sign.c_str(), val.c_str() );
    }
    else{
      double d = strtod( val.c_str(), NULL );
      S_wm->set( sign.c_str(), d );
    }
    // Update agenda as if forwarded from execution
    FFwrdP( sign.c_str() );
  }


  std::cout << "Session Started\n" << *S_wm << *CouchRunner::S_Agenda;

  {
    // Creates the `entry' function that sets up the Agenda, which
    // also serves as continuation for the postponed calls
    std::vector<Value *> args;
    Function *Main;


    while( !CouchRunner::S_Agenda->empty() ){

      // Erase previous entry function if present
      if( NULL != (Main = theM->getFunction("entry")) ){
	Main->eraseFromParent();
      }
      // Creates code block
      Main = cast<Function>(
			    theM->getOrInsertFunction( "entry", 
						       Type::getInt32Ty(getGlobalContext()), 
						       (Type *)0)
			    );
      BasicBlock *EB = BasicBlock::Create(getGlobalContext(), 
					  "EntryBlock", Main);
      theBuilder.SetInsertPoint(EB);
      // Loops through the current agenda
      Value *res = NULL, *call;
      std::string hypo;

      // Copies agenda to current Agenda
	
      while( !CouchRunner::S_Agenda->empty() ){
	hypo = CouchRunner::S_Agenda->pop();
	if( WorkingMemory::WM_UNKNOWN == S_wm->knownp( hypo.c_str() ) ){
	  call = theBuilder.CreateCall(theM->getFunction( hypo ),
				       args.begin(),
				       args.end(), "suggest");
	  res = 
	    theBuilder.CreateIntCast( call, 
				      Type::getInt32Ty(getGlobalContext()), 
				      false, "cast_tmp" );
	}
      }
      theBuilder.CreateRet( res == NULL ? 
			    ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 2) : 
			    res );
      // Check it
      S_TheFPM->run( *Main );
      // Run it
      Function *F = S_TheExecutionEngine->FindFunctionNamed( "entry" );
      void *FPtr = S_TheExecutionEngine->getPointerToFunction(F);
      typedef int (*PFN)();
      PFN FP = reinterpret_cast<PFN>( FPtr );
      //      int (*FP)() = (int (*)())FPtr;
      printf( "Result = %d\n", FP() );
      std::cout << *S_wm << std::endl;
      std::cout << *CouchRunner::S_Agenda << std::endl;
    }  
    S_wm = NULL;
  }
}
示例#3
0
FakeAudio::FakeAudio() : onendedCallback(getGlobalContext())
{
	readyState = 0;
	volume = 1.0f;
}
示例#4
0
static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_name, jl_codectx_t *ctx)
{
    // in pseudo-code, this function emits the following:
    //   global uv_lib_t **libptrgv
    //   global void **llvmgv
    //   if (*llvmgv == NULL) {
    //       *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv);
    //   }
    //   return (*llvmgv)
    Constant *initnul = ConstantPointerNull::get((PointerType*)T_pint8);

    uv_lib_t *libsym = NULL;
    bool runtime_lib = false;
    GlobalVariable *libptrgv;
#ifdef _OS_WINDOWS_
    if ((intptr_t)f_lib == 1) {
        libptrgv = prepare_global(jlexe_var);
        libsym = jl_exe_handle;
    }
    else if ((intptr_t)f_lib == 2) {
        libptrgv = prepare_global(jldll_var);
        libsym = jl_dl_handle;
    }
    else
#endif
    if (f_lib == NULL) {
        libptrgv = prepare_global(jlRTLD_DEFAULT_var);
        libsym = jl_RTLD_DEFAULT_handle;
    }
    else {
        runtime_lib = true;
        libptrgv = libMapGV[f_lib];
        if (libptrgv == NULL) {
            libptrgv = new GlobalVariable(*jl_Module, T_pint8,
               false, GlobalVariable::PrivateLinkage,
               initnul, f_lib);
            libMapGV[f_lib] = libptrgv;
            libsym = get_library(f_lib);
            assert(libsym != NULL);
#ifdef USE_MCJIT
            llvm_to_jl_value[libptrgv] = libsym;
#else
            *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym;
#endif
        }
    }
    if (libsym == NULL) {
#ifdef USE_MCJIT
        libsym = (uv_lib_t*)llvm_to_jl_value[libptrgv];
#else
        libsym = *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv));
#endif
    }

    assert(libsym != NULL);

    GlobalVariable *llvmgv = symMapGV[f_name];
    if (llvmgv == NULL) {
        // MCJIT forces this to have external linkage eventually, so we would clobber
        // the symbol of the actual function.
        std::string name = f_name;
        name = "ccall_" + name;
        llvmgv = new GlobalVariable(*jl_Module, T_pint8,
           false, GlobalVariable::PrivateLinkage,
           initnul, name);
        symMapGV[f_name] = llvmgv;
#ifdef USE_MCJIT
        llvm_to_jl_value[llvmgv] = jl_dlsym_e(libsym, f_name);
#else
        *((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name);
#endif
    }

    BasicBlock *dlsym_lookup = BasicBlock::Create(getGlobalContext(), "dlsym"),
               *ccall_bb = BasicBlock::Create(getGlobalContext(), "ccall");
    builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup);

    ctx->f->getBasicBlockList().push_back(dlsym_lookup);
    builder.SetInsertPoint(dlsym_lookup);
    Value *libname;
    if (runtime_lib) {
        libname = builder.CreateGlobalStringPtr(f_lib);
    }
    else {
        libname = literal_static_pointer_val(f_lib, T_pint8);
    }
    Value *llvmf = builder.CreateCall3(prepare_call(jldlsym_func), libname, builder.CreateGlobalStringPtr(f_name), libptrgv);
    builder.CreateStore(llvmf, llvmgv);
    builder.CreateBr(ccall_bb);

    ctx->f->getBasicBlockList().push_back(ccall_bb);
    builder.SetInsertPoint(ccall_bb);
    llvmf = builder.CreateLoad(llvmgv);
    return builder.CreatePointerCast(llvmf,funcptype);
}
示例#5
0
文件: ccall.cpp 项目: etrain/julia
// ccall(pointer, rettype, (argtypes...), args...)
static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
{
    JL_NARGSV(ccall, 3);
    jl_value_t *ptr=NULL, *rt=NULL, *at=NULL;
    Value *jl_ptr=NULL;
    JL_GC_PUSH(&ptr, &rt, &at);
    ptr = static_eval(args[1], ctx, true);
    if (ptr == NULL) {
        jl_value_t *ptr_ty = expr_type(args[1], ctx);
        Value *arg1 = emit_unboxed(args[1], ctx);
        if (!jl_is_cpointer_type(ptr_ty)) {
            emit_typecheck(arg1, (jl_value_t*)jl_voidpointer_type,
                           "ccall: function argument not a pointer or valid constant", ctx);
        }
        jl_ptr = emit_unbox(T_size, T_psize, arg1);
    }
    rt  = jl_interpret_toplevel_expr_in(ctx->module, args[2],
                                        &jl_tupleref(ctx->sp,0),
                                        jl_tuple_len(ctx->sp)/2);
    if (jl_is_tuple(rt)) {
        std::string msg = "in " + ctx->funcName +
            ": ccall: missing return type";
        jl_error(msg.c_str());
    }
    at  = jl_interpret_toplevel_expr_in(ctx->module, args[3],
                                        &jl_tupleref(ctx->sp,0),
                                        jl_tuple_len(ctx->sp)/2);
    void *fptr=NULL;
    char *f_name=NULL, *f_lib=NULL;
    if (ptr != NULL) {
        if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) {
            ptr = jl_tupleref(ptr,0);
        }
        if (jl_is_symbol(ptr))
            f_name = ((jl_sym_t*)ptr)->name;
        else if (jl_is_byte_string(ptr))
            f_name = jl_string_data(ptr);
        if (f_name != NULL) {
            // just symbol, default to JuliaDLHandle
#ifdef __WIN32__
         //TODO: store the f_lib name instead of fptr
        fptr = jl_dlsym_win32(f_name);
#else
            // will look in process symbol table
#endif
        }
        else if (jl_is_cpointer_type(jl_typeof(ptr))) {
            fptr = *(void**)jl_bits_data(ptr);
        }
        else if (jl_is_tuple(ptr) && jl_tuple_len(ptr)>1) {
            jl_value_t *t0 = jl_tupleref(ptr,0);
            jl_value_t *t1 = jl_tupleref(ptr,1);
            if (jl_is_symbol(t0))
                f_name = ((jl_sym_t*)t0)->name;
            else if (jl_is_byte_string(t0))
                f_name = jl_string_data(t0);
            else
                JL_TYPECHK(ccall, symbol, t0);
            if (jl_is_symbol(t1))
                f_lib = ((jl_sym_t*)t1)->name;
            else if (jl_is_byte_string(t1))
                f_lib = jl_string_data(t1);
            else
                JL_TYPECHK(ccall, symbol, t1);
        }
        else {
            JL_TYPECHK(ccall, pointer, ptr);
        }
    }
    if (f_name == NULL && fptr == NULL && jl_ptr == NULL) {
        JL_GC_POP();
        emit_error("ccall: null function pointer", ctx);
        return literal_pointer_val(jl_nothing);
    }

    JL_TYPECHK(ccall, type, rt);
    JL_TYPECHK(ccall, tuple, at);
    JL_TYPECHK(ccall, type, at);
    jl_tuple_t *tt = (jl_tuple_t*)at;
    std::vector<Type *> fargt(0);
    std::vector<Type *> fargt_sig(0);
    Type *lrt = julia_type_to_llvm(rt);
    if (lrt == NULL) {
        JL_GC_POP();
        return literal_pointer_val(jl_nothing);
    }
    size_t i;
    bool haspointers = false;
    bool isVa = false;
    size_t nargt = jl_tuple_len(tt);
    std::vector<AttributeWithIndex> attrs;

    for(i=0; i < nargt; i++) {
        jl_value_t *tti = jl_tupleref(tt,i);
        if (jl_is_vararg_type(tti)) {
            isVa = true;
            tti = jl_tparam0(tti);
        }
        if (jl_is_bits_type(tti)) {
            // see pull req #978. need to annotate signext/zeroext for
            // small integer arguments.
            jl_bits_type_t *bt = (jl_bits_type_t*)tti;
            if (bt->nbits < 32) {
                if (jl_signed_type == NULL) {
                    jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed"));
                }
#ifdef LLVM32
                Attributes::AttrVal av;
                if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0))
                    av = Attributes::SExt;
                else
                    av = Attributes::ZExt;
                attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1,
                                                        ArrayRef<Attributes::AttrVal>(&av, 1)));
#else
                Attribute::AttrConst av;
                if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0))
                    av = Attribute::SExt;
                else
                    av = Attribute::ZExt;
                attrs.push_back(AttributeWithIndex::get(i+1, av));
#endif
            }
        }
        Type *t = julia_type_to_llvm(tti);
        if (t == NULL) {
            JL_GC_POP();
            return literal_pointer_val(jl_nothing);
        }
        fargt.push_back(t);
        if (!isVa)
            fargt_sig.push_back(t);
    }
    // check for calling convention specifier
    CallingConv::ID cc = CallingConv::C;
    jl_value_t *last = args[nargs];
    if (jl_is_expr(last)) {
        jl_sym_t *lhd = ((jl_expr_t*)last)->head;
        if (lhd == jl_symbol("stdcall")) {
            cc = CallingConv::X86_StdCall;
            nargs--;
        }
        else if (lhd == jl_symbol("cdecl")) {
            cc = CallingConv::C;
            nargs--;
        }
        else if (lhd == jl_symbol("fastcall")) {
            cc = CallingConv::X86_FastCall;
            nargs--;
        }
        else if (lhd == jl_symbol("thiscall")) {
            cc = CallingConv::X86_ThisCall;
            nargs--;
        }
    }
    
    if ((!isVa && jl_tuple_len(tt)  != (nargs-2)/2) ||
        ( isVa && jl_tuple_len(tt)-1 > (nargs-2)/2))
        jl_error("ccall: wrong number of arguments to C function");

    // some special functions
    if (fptr == &jl_array_ptr) {
        Value *ary = emit_expr(args[4], ctx);
        JL_GC_POP();
        return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt),
                               rt);
    }

    // see if there are & arguments
    for(i=4; i < nargs+1; i+=2) {
        jl_value_t *argi = args[i];
        if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) {
            haspointers = true;
            break;
        }
    }

    // make LLVM function object for the target
    Value *llvmf;
    FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa);
    
    if (jl_ptr != NULL) {
        null_pointer_check(jl_ptr,ctx);
        Type *funcptype = PointerType::get(functype,0);
        llvmf = builder.CreateIntToPtr(jl_ptr, funcptype);
    } else if (fptr != NULL) {
        Type *funcptype = PointerType::get(functype,0);
        llvmf = literal_pointer_val(fptr, funcptype);
    }
    else {
        void *symaddr;
        if (f_lib != NULL)
            symaddr = add_library_sym(f_name, f_lib);
        else
            symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name);
        if (symaddr == NULL) {
            JL_GC_POP();
            std::stringstream msg;
            msg << "ccall: could not find function ";
            msg << f_name;
            if (f_lib != NULL) {
                msg << " in library ";
                msg << f_lib;
            }
            emit_error(msg.str(), ctx);
            return literal_pointer_val(jl_nothing);
        }
        llvmf = jl_Module->getOrInsertFunction(f_name, functype);
    }

    // save temp argument area stack pointer
    Value *saveloc=NULL;
    Value *stacksave=NULL;
    if (haspointers) {
        // TODO: inline this
        saveloc = builder.CreateCall(save_arg_area_loc_func);
        stacksave =
            builder.CreateCall(Intrinsic::getDeclaration(jl_Module,
                                                         Intrinsic::stacksave));
    }

    // emit arguments
    Value *argvals[(nargs-3)/2];
    int last_depth = ctx->argDepth;
    int nargty = jl_tuple_len(tt);
    for(i=4; i < nargs+1; i+=2) {
        int ai = (i-4)/2;
        jl_value_t *argi = args[i];
        bool addressOf = false;
        if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) {
            addressOf = true;
            argi = jl_exprarg(argi,0);
        }
        Type *largty;
        jl_value_t *jargty;
        if (isVa && ai >= nargty-1) {
            largty = fargt[nargty-1];
            jargty = jl_tparam0(jl_tupleref(tt,nargty-1));
        }
        else {
            largty = fargt[ai];
            jargty = jl_tupleref(tt,ai);
        }
        Value *arg;
        if (largty == jl_pvalue_llvmt) {
            arg = emit_expr(argi, ctx, true);
        }
        else {
            arg = emit_unboxed(argi, ctx);
            if (jl_is_bits_type(expr_type(argi, ctx))) {
                if (addressOf)
                    arg = emit_unbox(largty->getContainedType(0), largty, arg);
                else
                    arg = emit_unbox(largty, PointerType::get(largty,0), arg);
            }
        }
        /*
#ifdef JL_GC_MARKSWEEP
        // make sure args are rooted
        if (largty->isPointerTy() &&
            (largty == jl_pvalue_llvmt ||
             !jl_is_bits_type(expr_type(args[i], ctx)))) {
            make_gcroot(boxed(arg), ctx);
        }
#endif
        */
        argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf,
                                      ai+1, ctx);
    }
    // the actual call
    Value *result = builder.CreateCall(llvmf,
                                       ArrayRef<Value*>(&argvals[0],(nargs-3)/2));
    if (cc != CallingConv::C)
        ((CallInst*)result)->setCallingConv(cc);

#ifdef LLVM32
    ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef<AttributeWithIndex>(attrs)));
#else
    ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size()));
#endif
    // restore temp argument area stack pointer
    if (haspointers) {
        assert(saveloc != NULL);
        builder.CreateCall(restore_arg_area_loc_func, saveloc);
        assert(stacksave != NULL);
        builder.CreateCall(Intrinsic::getDeclaration(jl_Module,
                                                     Intrinsic::stackrestore),
                           stacksave);
    }
    ctx->argDepth = last_depth;
    if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall
#ifdef LLVM32        
        ctx->f->addFnAttr(Attributes::StackProtectReq);
#else
        ctx->f->addFnAttr(Attribute::StackProtectReq);
#endif
    }

    JL_GC_POP();
    if (lrt == T_void)
        return literal_pointer_val((jl_value_t*)jl_nothing);
    return mark_julia_type(result, rt);
}
示例#6
0
Value *CodeGen::generateNumber(int value){
	return ConstantInt::get(
			Type::getInt32Ty(getGlobalContext()),
			value);
}
示例#7
0
static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_name, jl_codectx_t *ctx)
{
    // in pseudo-code, this function emits the following:
    //   global uv_lib_t **libptrgv
    //   global void **llvmgv
    //   if (*llvmgv == NULL) {
    //       *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv);
    //   }
    //   return (*llvmgv)
    Constant *initnul = ConstantPointerNull::get((PointerType*)T_pint8);

    uv_lib_t *libsym = NULL;
    bool runtime_lib = false;
    GlobalVariable *libptrgv;
#ifdef _OS_WINDOWS_
    if ((intptr_t)f_lib == 1)
        libptrgv = jlexe_var;
    else if ((intptr_t)f_lib == 2)
        libptrgv = jldll_var;
    else
#endif
    if (f_lib == NULL) {
        libptrgv = jlRTLD_DEFAULT_var;
    }
    else {
        runtime_lib = true;
        libptrgv = libMapGV[f_lib];
        if (libptrgv == NULL) {
            libptrgv = new GlobalVariable(*jl_Module, T_pint8,
               false, GlobalVariable::PrivateLinkage,
               initnul, f_lib);
            libMapGV[f_lib] = libptrgv;
            libsym = get_library(f_lib);
            *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym;
        }
    }
    if (libsym == NULL) {
        libsym = *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv));
    }

    GlobalVariable *llvmgv = symMapGV[f_name];
    if (llvmgv == NULL) {
        llvmgv = new GlobalVariable(*jl_Module, T_pint8,
           false, GlobalVariable::PrivateLinkage,
           initnul, f_name);
        symMapGV[f_name] = llvmgv;
        *((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name);
    }

    BasicBlock *dlsym_lookup = BasicBlock::Create(getGlobalContext(), "dlsym"),
               *ccall_bb = BasicBlock::Create(getGlobalContext(), "ccall");
    builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup);

    ctx->f->getBasicBlockList().push_back(dlsym_lookup);
    builder.SetInsertPoint(dlsym_lookup);
    Value *libname;
    if (runtime_lib) {
        libname = builder.CreateGlobalStringPtr(f_lib);
    }
    else {
        libname = literal_static_pointer_val(f_lib, T_pint8);
    }
    Value *llvmf = builder.CreateCall3(jldlsym_func, libname, builder.CreateGlobalStringPtr(f_name), libptrgv);
    builder.CreateStore(llvmf, llvmgv);
    builder.CreateBr(ccall_bb);

    ctx->f->getBasicBlockList().push_back(ccall_bb);
    builder.SetInsertPoint(ccall_bb);
    llvmf = builder.CreateLoad(llvmgv);
    return builder.CreatePointerCast(llvmf,funcptype);
}
示例#8
0
/// HandleArgument - This is invoked by the target-independent code for each
/// argument type passed into the function.  It potentially breaks down the
/// argument and invokes methods on the client that indicate how its pieces
/// should be handled.  This handles things like decimating structures into
/// their fields.
void DefaultABI::HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
				Attributes *Attributes) {
  unsigned Size = 0;
  bool DontCheckAlignment = false;
  const Type *Ty = ConvertType(type);
  // Figure out if this field is zero bits wide, e.g. {} or [0 x int].  Do
  // not include variable sized fields here.
  std::vector<const Type*> Elts;
  if (Ty->isVoidTy()) {
    // Handle void explicitly as an opaque type.
    const Type *OpTy = OpaqueType::get(getGlobalContext());
    C.HandleScalarArgument(OpTy, type);
    ScalarElts.push_back(OpTy);
  } else if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
    const Type *PtrTy = Ty->getPointerTo();
    C.HandleByInvisibleReferenceArgument(PtrTy, type);
    ScalarElts.push_back(PtrTy);
  } else if (Ty->isVectorTy()) {
    if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
      PassInIntegerRegisters(type, ScalarElts, 0, false);
    } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) {
      C.HandleByValArgument(Ty, type);
      if (Attributes) {
	*Attributes |= Attribute::ByVal;
	*Attributes |= 
	  Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
      }
    } else {
      C.HandleScalarArgument(Ty, type);
      ScalarElts.push_back(Ty);
    }
  } else if (LLVM_TRY_PASS_AGGREGATE_CUSTOM(type, ScalarElts,
					    C.getCallingConv(), &C)) {
    // Nothing to do.
  } else if (Ty->isSingleValueType()) {
    C.HandleScalarArgument(Ty, type);
    ScalarElts.push_back(Ty);
  } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, Ty)) {
    C.HandleFCAArgument(Ty, type);
  } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,
						      C.getCallingConv(),
						      Elts)) {
    if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts,
						 C.isShadowReturn(),
						 C.getCallingConv()))
      PassInMixedRegisters(Ty, Elts, ScalarElts);
    else {
      C.HandleByValArgument(Ty, type);
      if (Attributes) {
	*Attributes |= Attribute::ByVal;
	*Attributes |= 
	  Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
      }
    }
  } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
    C.HandleByValArgument(Ty, type);
    if (Attributes) {
      *Attributes |= Attribute::ByVal;
      *Attributes |= 
	Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
    }
  } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size,
							&DontCheckAlignment)) {
    PassInIntegerRegisters(type, ScalarElts, Size, DontCheckAlignment);
  } else if (isZeroSizedStructOrUnion(type)) {
    // Zero sized struct or union, just drop it!
    ;
  } else if (TREE_CODE(type) == RECORD_TYPE) {
    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
      if (TREE_CODE(Field) == FIELD_DECL) {
	const tree Ftype = getDeclaredType(Field);
	const Type *FTy = ConvertType(Ftype);
	unsigned FNo = GET_LLVM_FIELD_INDEX(Field);
	assert(FNo != ~0U && "Case not handled yet!");

	// Currently, a bvyal type inside a non-byval struct is a zero-length
	// object inside a bigger object on x86-64.  This type should be
	// skipped (but only when it is inside a bigger object).
	// (We know there currently are no other such cases active because
	// they would hit the assert in FunctionPrologArgumentConversion::
	// HandleByValArgument.)
	if (!LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(Ftype, FTy)) {
	  C.EnterField(FNo, Ty);
	  HandleArgument(getDeclaredType(Field), ScalarElts);
	  C.ExitField();
	}
      }
  } else if (TREE_CODE(type) == COMPLEX_TYPE) {
    C.EnterField(0, Ty);
    HandleArgument(TREE_TYPE(type), ScalarElts);
    C.ExitField();
    C.EnterField(1, Ty);
    HandleArgument(TREE_TYPE(type), ScalarElts);
    C.ExitField();
  } else if ((TREE_CODE(type) == UNION_TYPE) ||
	     (TREE_CODE(type) == QUAL_UNION_TYPE)) {
    HandleUnion(type, ScalarElts);
  } else if (TREE_CODE(type) == ARRAY_TYPE) {
    const ArrayType *ATy = cast<ArrayType>(Ty);
    for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
      C.EnterField(i, Ty);
      HandleArgument(TREE_TYPE(type), ScalarElts);
      C.ExitField();
    }
  } else {
    assert(0 && "unknown aggregate type!");
    abort();
  }
}
示例#9
0
void *LLVMFormula::emit (NumberExprAST *expr)
{
	return ConstantFP::get (getGlobalContext (), APFloat (expr->val));
}
示例#10
0
void Executor::callUnmodelledFunction(ExecutionState &state,
                            KInstruction *target,
                            llvm::Function *function,
                            std::vector<ref<Expr> > &arguments) {

  if (NoExternals && !okExternals.count(function->getName())) {
    std::cerr << "KLEE:ERROR: Calling not-OK external function : "
               << function->getName().str() << "\n";
    terminateStateOnError(state, "externals disallowed", "user.err");
    return;
  }

  // normal external function handling path
  // allocate 128 bits for each argument (+return value) to support fp80's;
  // we could iterate through all the arguments first and determine the exact
  // size we need, but this is faster, and the memory usage isn't significant.
  uint64_t *args = (uint64_t*) alloca(2*sizeof(*args) * (arguments.size() + 1));
  memset(args, 0, 2 * sizeof(*args) * (arguments.size() + 1));
  unsigned wordIndex = 2;
  for (std::vector<ref<Expr> >::iterator ai = arguments.begin(),
      ae = arguments.end(); ai!=ae; ++ai) {
    if (AllowExternalSymCalls) { // don't bother checking uniqueness
      ref<ConstantExpr> ce;
      bool success = solver->getValue(data::EXTERNAL_CALL_CONCRETIZATION, state, *ai, ce);
      assert(success && "FIXME: Unhandled solver failure");
      (void) success;
      ce->toMemory(&args[wordIndex]);
      wordIndex += (ce->getWidth()+63)/64;
    } else {
      ref<Expr> arg = toUnique(state, *ai);
      if (ConstantExpr *ce = dyn_cast<ConstantExpr>(arg)) {
        // XXX kick toMemory functions from here
        ce->toMemory(&args[wordIndex]);
        wordIndex += (ce->getWidth()+63)/64;
      } else {
        terminateStateOnExecError(state,
                                  "external call with symbolic argument: " +
                                  function->getName());
        return;
      }
    }
  }

  state.addressSpace().copyOutConcretes(&state.addressPool);

  if (!SuppressExternalWarnings) {
    std::ostringstream os;
    os << state <<
        " Calling external: " << function->getName().str() << "(";
    for (unsigned i=0; i<arguments.size(); i++) {
      os << arguments[i];
      if (i != arguments.size()-1)
    os << ", ";
    }
    os << ")";

    VLOG(1) << os.str().c_str();
  }

  bool success = externalDispatcher->executeCall(function, target->inst, args);
  if (!success) {
    terminateStateOnError(state, "failed external call: " + function->getName(),
                          "external.err");
    return;
  }

  if (!state.addressSpace().copyInConcretes(&state.addressPool)) {
    terminateStateOnError(state, "external modified read-only object",
                          "external.err");
    return;
  }

  Type *resultType = target->inst->getType();
  if (resultType != Type::getVoidTy(getGlobalContext())) {
    ref<Expr> e = ConstantExpr::fromMemory((void*) args,
                                           getWidthForLLVMType(resultType));
    bindLocal(target, state, e);
  }
}
示例#11
0
/// PassInIntegerRegisters - Given an aggregate value that should be passed in
/// integer registers, convert it to a structure containing ints and pass all
/// of the struct elements in.  If Size is set we pass only that many bytes.
void DefaultABI::PassInIntegerRegisters(tree type,
					std::vector<const Type*> &ScalarElts,
					unsigned origSize,
					bool DontCheckAlignment) {
  unsigned Size;
  if (origSize)
    Size = origSize;
  else
    Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;

  // FIXME: We should preserve all aggregate value alignment information.
  // Work around to preserve some aggregate value alignment information:
  // don't bitcast aggregate value to Int64 if its alignment is different
  // from Int64 alignment. ARM backend needs this.
  unsigned Align = TYPE_ALIGN(type)/8;
  unsigned Int64Align =
    getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext()));
  bool UseInt64 = (DontCheckAlignment || Align >= Int64Align);

  unsigned ElementSize = UseInt64 ? 8:4;
  unsigned ArraySize = Size / ElementSize;

  // Put as much of the aggregate as possible into an array.
  const Type *ATy = NULL;
  const Type *ArrayElementType = NULL;
  if (ArraySize) {
    Size = Size % ElementSize;
    ArrayElementType = (UseInt64 ?
			Type::getInt64Ty(getGlobalContext()) :
			Type::getInt32Ty(getGlobalContext()));
    ATy = ArrayType::get(ArrayElementType, ArraySize);
  }

  // Pass any leftover bytes as a separate element following the array.
  unsigned LastEltRealSize = 0;
  const llvm::Type *LastEltTy = 0;
  if (Size > 4) {
    LastEltTy = Type::getInt64Ty(getGlobalContext());
  } else if (Size > 2) {
    LastEltTy = Type::getInt32Ty(getGlobalContext());
  } else if (Size > 1) {
    LastEltTy = Type::getInt16Ty(getGlobalContext());
  } else if (Size > 0) {
    LastEltTy = Type::getInt8Ty(getGlobalContext());
  }
  if (LastEltTy) {
    if (Size != getTargetData().getTypeAllocSize(LastEltTy))
      LastEltRealSize = Size;
  }

  std::vector<const Type*> Elts;
  if (ATy)
    Elts.push_back(ATy);
  if (LastEltTy)
    Elts.push_back(LastEltTy);
  const StructType *STy = StructType::get(getGlobalContext(), Elts, false);

  unsigned i = 0;
  if (ArraySize) {
    C.EnterField(0, STy);
    for (unsigned j = 0; j < ArraySize; ++j) {
      C.EnterField(j, ATy);
      C.HandleScalarArgument(ArrayElementType, 0);
      ScalarElts.push_back(ArrayElementType);
      C.ExitField();
    }
    C.ExitField();
    ++i;
  }
  if (LastEltTy) {
    C.EnterField(i, STy);
    C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize);
    ScalarElts.push_back(LastEltTy);
    C.ExitField();
  }
}
示例#12
0
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

//===----------------------------------------------------------------------===//
// This is a C++ source file that implements specific llvm mips ABI.
//===----------------------------------------------------------------------===//

#include "llvm-abi.h"
#include "llvm-mips-target.h"

static LLVMContext &Context = getGlobalContext();

/* Target hook for llvm-abi.h. It returns true if an aggregate of the
   specified type should be passed in memory. In mips EABI this is 
   true for aggregates with size > 32-bits. */
bool llvm_mips_should_pass_aggregate_in_memory(tree TreeType, Type *Ty) {
  if (mips_abi == ABI_EABI)
  {
    enum machine_mode mode = TYPE_MODE(TreeType);
    int size;

    if (mode == DImode || mode == DFmode)
      return false;

    size = TreeType ? int_size_in_bytes (TreeType) : GET_MODE_SIZE (mode);
    return size == -1 || size > UNITS_PER_WORD;
示例#13
0
Parser::Parser(const std::shared_ptr<Module> &module) : _inputTag(nullptr),
    _builder(getGlobalContext()) {

    _lastChar = ' ';
    _module = module;
}
示例#14
0
bool CompiledCondition::compile(){
	InitializeNativeTarget();
	// Assume we're on main thread...
	LLVMContext &context = getGlobalContext();

	// Initialize module
	Module* module = new Module("Compiled function", context);

	// Create exection engine
	ExecutionEngine* engine = EngineBuilder(module).create();

	/********** Generate code **********/

	//Get a type for representing an integer pointer
	//Maybe this should be unsigned integer pointer type...
	PointerType* integerPointerType = PointerType::get(IntegerType::get(module->getContext(), 32), 0);

	//Create function type, for our function, int*, int* -> bool
	vector<const Type*> paramType;
	paramType.push_back(integerPointerType);
	paramType.push_back(integerPointerType);
	FunctionType* functionType = FunctionType::get(IntegerType::get(module->getContext(), 8), paramType, false);

	//Declare new function
	Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "evaluate", module);
	//Use C calling convention
	function->setCallingConv(CallingConv::C);	//TODO: Read documentation and reconsider this

	//Get arguments from function
	Function::arg_iterator args = function->arg_begin();
	Value* marking = args++;
	Value* valuation = args++;
	marking->setName("marking");
	valuation->setName("valuation");

	//Create function block
	BasicBlock* functionBlock = BasicBlock::Create(module->getContext(), "functionBlock", function, 0);

	//Generate code
	CodeGenerationContext codeGenContext(marking, valuation, functionBlock, context);
	Value* result = _cond->codegen(codeGenContext);

	//Zero extend the result, e.g. make it a 8 bit bool
	CastInst* retval = new ZExtInst(result, IntegerType::get(module->getContext(), 8), "retval", functionBlock);

	//Create a return instruction
	ReturnInst::Create(module->getContext(), retval, functionBlock);

	/********** Optimize and Compile **********/

	// Create function pass manager, to optimize query
	FunctionPassManager optimizer(module);
	optimizer.add(new TargetData(*engine->getTargetData()));
	optimizer.add(createBasicAliasAnalysisPass());
	optimizer.add(createInstructionCombiningPass());
	optimizer.add(createReassociatePass());
	optimizer.add(createGVNPass());
	optimizer.add(createCFGSimplificationPass());
	optimizer.doInitialization();

	// Verify function, errors written to stderr
	if(verifyFunction(*function))
		return false;

	// Optimize function
	optimizer.run(*function);

	// Compile the function
	_nativeFunction = (bool(*)(const MarkVal*, const VarVal*))engine->getPointerToFunction(function);

	return _nativeFunction != NULL;
}
示例#15
0
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv,
                              jl_value_t *aty, bool addressOf,
                              bool byRef, bool inReg,
                              bool needCopy,
                              int argn, jl_codectx_t *ctx,
                              bool *needStackRestore)
{
    Type *vt = jv->getType();

    // We're passing any
    if (ty == jl_pvalue_llvmt) {
        return boxed(jv,ctx);
    }
    if (ty == vt && !addressOf && !byRef) {
        return jv;
    }
    if (vt != jl_pvalue_llvmt) {
        // argument value is unboxed
        if (addressOf || (byRef && inReg)) {
            if (ty->isPointerTy() && ty->getContainedType(0)==vt) {
                // pass the address of an alloca'd thing, not a box
                // since those are immutable.
                *needStackRestore = true;
                Value *slot = builder.CreateAlloca(vt);
                builder.CreateStore(jv, slot);
                return builder.CreateBitCast(slot, ty);
            }
        }
        else if ((vt->isIntegerTy() && ty->isIntegerTy()) ||
                 (vt->isFloatingPointTy() && ty->isFloatingPointTy()) ||
                 (vt->isPointerTy() && ty->isPointerTy())) {
            if (vt->getPrimitiveSizeInBits() ==
                ty->getPrimitiveSizeInBits()) {
                if (!byRef) {
                    return builder.CreateBitCast(jv, ty);
                }
                else {
                    *needStackRestore = true;
                    Value *mem = builder.CreateAlloca(ty);
                    builder.CreateStore(jv,builder.CreateBitCast(mem,vt->getPointerTo()));
                    return mem;
                }
            }
        }
        else if (vt->isStructTy()) {
            if (!byRef) {
                return jv;
            }
            else {
                *needStackRestore = true;
                Value *mem = builder.CreateAlloca(vt);
                builder.CreateStore(jv,mem);
                return mem;
            }
        }

        emit_error("ccall: argument type did not match declaration", ctx);
    }
    if (jl_is_tuple(jt)) {
        return emit_unbox(ty,jv,jt);
    }
    if (jl_is_cpointer_type(jt) && addressOf) {
        assert(ty->isPointerTy());
        jl_value_t *ety = jl_tparam0(jt);
        if (aty != ety && ety != (jl_value_t*)jl_any_type && jt != (jl_value_t*)jl_voidpointer_type) {
            std::stringstream msg;
            msg << "ccall argument ";
            msg << argn;
            emit_typecheck(jv, ety, msg.str(), ctx);
        }
        if (jl_is_mutable_datatype(ety)) {
            // no copy, just reference the data field
            return builder.CreateBitCast(jv, ty);
        }
        else if (jl_is_immutable_datatype(ety) && jt != (jl_value_t*)jl_voidpointer_type) {
            // yes copy
            Value *nbytes;
            if (jl_is_leaf_type(ety))
                nbytes = ConstantInt::get(T_int32, jl_datatype_size(ety));
            else
                nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad(
                                builder.CreateGEP(builder.CreatePointerCast(emit_typeof(jv), T_pint32),
                                    ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))),
                                false));
            *needStackRestore = true;
            AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes);
            ai->setAlignment(16);
            builder.CreateMemCpy(ai, builder.CreateBitCast(jv, T_pint8), nbytes, 1);
            return builder.CreateBitCast(ai, ty);
        }
        // emit maybe copy
        *needStackRestore = true;
        Value *jvt = emit_typeof(jv);
        BasicBlock *mutableBB = BasicBlock::Create(getGlobalContext(),"is-mutable",ctx->f);
        BasicBlock *immutableBB = BasicBlock::Create(getGlobalContext(),"is-immutable",ctx->f);
        BasicBlock *afterBB = BasicBlock::Create(getGlobalContext(),"after",ctx->f);
        Value *ismutable = builder.CreateTrunc(
                tbaa_decorate(tbaa_datatype, builder.CreateLoad(
                        builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint8),
                            ConstantInt::get(T_size, offsetof(jl_datatype_t,mutabl))),
                        false)),
                T_int1);
        builder.CreateCondBr(ismutable, mutableBB, immutableBB);
        builder.SetInsertPoint(mutableBB);
        Value *p1 = builder.CreatePointerCast(jv, ty);
        builder.CreateBr(afterBB);
        builder.SetInsertPoint(immutableBB);
        Value *nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad(
                    builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint32),
                        ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))),
                    false));
        AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes);
        ai->setAlignment(16);
        builder.CreateMemCpy(ai, builder.CreatePointerCast(jv, T_pint8), nbytes, 1);
        Value *p2 = builder.CreatePointerCast(ai, ty);
        builder.CreateBr(afterBB);
        builder.SetInsertPoint(afterBB);
        PHINode *p = builder.CreatePHI(ty, 2);
        p->addIncoming(p1, mutableBB);
        p->addIncoming(p2, immutableBB);
        return p;
    }
    if (addressOf)
        jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct
    assert(jl_is_datatype(jt));
    if (aty != jt) {
        std::stringstream msg;
        msg << "ccall argument ";
        msg << argn;
        emit_typecheck(jv, jt, msg.str(), ctx);
    }
    Value *p = data_pointer(jv);
    Value *pjv = builder.CreatePointerCast(p, PointerType::get(ty,0));
    if (byRef) {
        if (!needCopy) {
            return pjv;
        }
        else {
            *needStackRestore = true;
            Value *mem = builder.CreateAlloca(ty);
            builder.CreateMemCpy(mem,pjv,(uint64_t)jl_datatype_size(jt),(uint64_t)((jl_datatype_t*)jt)->alignment);
            return mem;
        }
    }
    else {
        return builder.CreateLoad(pjv,false);
    }
}
示例#16
0
void *LLVMFormula::emit (BinaryExprAST *expr)
{
	if (expr->op == "=")
	{
		// The assign function has to be dealt with specially, we *do not*
		// want to emit the LHS code (the load-from-memory instruction)!
		VariableExprAST *var = dynamic_cast<VariableExprAST *>(expr->LHS);
		if (!var) return NULL;
				
		Value *val = (Value *)expr->RHS->generate (this);
		if (!val) return NULL;
		
		// Emit a store-to-pointer instruction
		builder->CreateStore (val, getGlobalVariableFor (var->pointer), "storetmp");
		return val;
	}

	// The rest of the operators function normally
	Value *L = (Value *)expr->LHS->generate (this);
	Value *R = (Value *)expr->RHS->generate (this);
	if (L == NULL || R == NULL) return NULL;

	if (expr->op == "<=")
	{
		L = builder->CreateFCmpULE (L, R, "letmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == ">=")
	{
		L = builder->CreateFCmpUGE (L, R, "getmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == "!=")
	{
		L = builder->CreateFCmpUNE (L, R, "neqtmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == "==")
	{
		L = builder->CreateFCmpUEQ (L, R, "eqtmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == "<")
	{
		L = builder->CreateFCmpULT (L, R, "lttmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == ">")
	{
		L = builder->CreateFCmpUGT (L, R, "gttmp");
		return builder->CreateUIToFP (L, Type::getDoubleTy (getGlobalContext ()),
		                              "booltmp");
	}
	else if (expr->op == "+")
		return builder->CreateFAdd (L, R, "addtmp");
	else if (expr->op == "-")
		return builder->CreateFSub (L, R, "subtmp");
	else if (expr->op == "*")
		return builder->CreateFMul (L, R, "multmp");
	else if (expr->op == "/")
		return builder->CreateFDiv (L, R, "divtmp");
	else if (expr->op == "^")
	{
		// The floating-point intrinsics are overloaded for multiple types
		Type *types[1] = { Type::getDoubleTy (getGlobalContext ()) };
        ArrayRef<Type *> type_array(types, 1);
		
		Value *func = Intrinsic::getDeclaration (module, Intrinsic::pow, type_array);
		return builder->CreateCall2 (func, L, R, "pow");
	}
	else
		return NULL;
}
示例#17
0
/**
  * Module取得
  */
Module &CodeGen::getModule(){
	if(Mod)
		return *Mod;
	else
		return *(new Module("null", getGlobalContext()));
}
示例#18
0
void *LLVMFormula::emit (CallExprAST *expr)
{
	// Deal with the if-instruction first, specially
	if (expr->function == "if")
	{
		Value *cond = (Value *)expr->args[0]->generate (this);
		Value *t = (Value *)expr->args[1]->generate (this);
		Value *f = (Value *)expr->args[2]->generate (this);
		if (cond == NULL || t == NULL || f == NULL) return NULL;
		
		Value *one = ConstantFP::get (getGlobalContext (), APFloat (1.0));
		Value *cmp = builder->CreateFCmpOEQ (cond, one, "ifcmptmp");

		return builder->CreateSelect (cmp, t, f, "ifelsetmp");
	}

	// Sign isn't a standard-library function, implement it with a compare
	if (expr->function == "sign")
	{
		Value *v = (Value *)expr->args[0]->generate (this);
		if (!v) return NULL;
		
		Value *zero = ConstantFP::get (getGlobalContext (), APFloat (0.0));
		Value *one = ConstantFP::get (getGlobalContext (), APFloat (1.0));
		Value *none = ConstantFP::get (getGlobalContext (), APFloat (-1.0));

		Value *cmpgzero = builder->CreateFCmpOGT (v, zero, "sgncmpgzero");
		Value *cmplzero = builder->CreateFCmpOLT (v, zero, "sgncmplzero");

		Value *fselect = builder->CreateSelect (cmplzero, none, zero, "sgnsellzero");
		return builder->CreateSelect (cmpgzero, one, fselect, "sgnselgzero");
	}

	//
	// Map our function names to standard libm names
	//
	
	// If we're calling "log", we want "log10"
	if (expr->function == "log")
		expr->function = "log10";
	// If we're calling "ln", we want "log"
	if (expr->function == "ln")
		expr->function = "log";
	// If we're calling "abs", we want "fabs"
	if (expr->function == "abs")
		expr->function = "fabs";
	
	// The following are available as LLVM intrinsics, and we should emit them
	// specially without calling out to libm:
	Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
		
	if (expr->function == "cos")
		intrinsicID = Intrinsic::cos;
	else if (expr->function == "exp")
		intrinsicID = Intrinsic::exp;
	else if (expr->function == "log")
		intrinsicID = Intrinsic::log;
	else if (expr->function == "log10")
		intrinsicID = Intrinsic::log10;
	else if (expr->function == "sin")
		intrinsicID = Intrinsic::sin;
	else if (expr->function == "sqrt")
		intrinsicID = Intrinsic::sqrt;

	if (intrinsicID != Intrinsic::not_intrinsic)
	{
		// Most of the floating-point intrinsics are overloaded for multiple types
		Type *types[1] = { Type::getDoubleTy (getGlobalContext ()) };
        ArrayRef<Type *> type_array(types, 1);
		
		Value *arg = (Value *)expr->args[0]->generate (this);
		if (!arg) return NULL;

		Value *func = Intrinsic::getDeclaration (module, intrinsicID, type_array);
		return builder->CreateCall (func, arg, expr->function);
	}
	
	// The rest of these are calls to stdlib floating point math
	// functions.
	
	// atan2 is special, because it has two arguments
	if (expr->function == "atan2")
	{
        Value *arg1 = (Value *)expr->args[0]->generate (this);
        Value *arg2 = (Value *)expr->args[1]->generate (this);
        if (!arg1 || !arg2) return NULL;
        
        Module *M = builder->GetInsertBlock ()->getParent ()->getParent ();
        Value *Callee = M->getOrInsertFunction (expr->function,
                                                Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
                                                NULL);
        return builder->CreateCall2 (Callee, arg1, arg2, expr->function);
	}
	else
	{
    	// Emit a call to function (arg)
    	Value *arg = (Value *)expr->args[0]->generate (this);
    	if (!arg) return NULL;
	
    	Module *M = builder->GetInsertBlock ()->getParent ()->getParent ();
    	Value *Callee = M->getOrInsertFunction (expr->function,
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        NULL);
    	return builder->CreateCall (Callee, arg, expr->function);
    }
}
示例#19
0
/**
  * コンストラクタ
  */
CodeGen::CodeGen(){
	Builder = new IRBuilder<>(getGlobalContext());
}
// =============================================================================
// replaceCallsInProcess
// 
// Replace indirect calls to write() or read() by direct calls 
// in the given process.
// =============================================================================
void TLMBasicPassImpl::replaceCallsInProcess(sc_core::sc_module *initiatorMod,
                                         sc_core::sc_process_b *proc) {
    
    // Get associate function
    std::string fctName = proc->func_process;
	std::string modType = typeid(*initiatorMod).name();
	std::string mainFctName = "_ZN" + modType + 
    utostr(fctName.size()) + fctName + "Ev";
	Function *oldProcf = this->llvmMod->getFunction(mainFctName);
    if (oldProcf==NULL)
        return;
    
    // We do not modifie the original function
    // Instead, we create a clone.
    Function *procf = createProcess(oldProcf, initiatorMod);
    void *funPtr = this->engine->getPointerToFunction(procf); 
    sc_core::SC_ENTRY_FUNC_OPT scfun = 
    reinterpret_cast<sc_core::SC_ENTRY_FUNC_OPT>(funPtr);
    proc->m_semantics_p = scfun;
    std::string procfName = procf->getName();
    MSG("      Replace in the process's function : "+procfName+"\n");
    
    std::ostringstream oss;
    sc_core::sc_module *targetMod;
    std::vector<CallInfo*> *work = new std::vector<CallInfo*>;
    
    inst_iterator ii;
    for (ii = inst_begin(procf); ii!=inst_end(procf); ii++) {
        Instruction &i = *ii;
        CallSite cs(&i);
        if (cs.getInstruction()) {
            // Candidate for a replacement
            Function *oldfun = cs.getCalledFunction();
            if (oldfun!=NULL && !oldfun->isDeclaration()) {
                std::string name = oldfun->getName();
                // === Write ===
                if (!strcmp(name.c_str(), wFunName.c_str())) {
                    
                    CallInfo *info = new CallInfo();
                    info->oldcall = dyn_cast<CallInst>(cs.getInstruction());
                    MSG("       Checking adress : ");
                    // Retrieve the adress argument by executing 
                    // the appropriated piece of code
                    SCJit *scjit = new SCJit(this->llvmMod, this->elab);
                    Process *irProc = this->elab->getProcess(proc);
                    scjit->setCurrentProcess(irProc);                    
                    bool jitErr = false;
                    info->addrArg = cs.getArgument(1);
                    int value = 
                    scjit->jitInt(procf, info->oldcall, info->addrArg, &jitErr);
                    if(jitErr) {
                        std::cout << "       cannot get the address value!" 
                          << std::endl;
                    } else {
                    oss.str("");  oss << std::hex << value;
                    MSG("0x"+oss.str()+"\n");
                    basic::addr_t a = static_cast<basic::addr_t>(value);            
                    
                    // Checking address alignment
                    if(value % sizeof(basic::data_t)) {
                        std::cerr << "  unaligned write : " <<
                        std::hex << value << std::endl;
                        abort();
                    }

                    // Retreive the target module using the address
                    targetMod =  getTargetModule(initiatorMod, a);
                                    
                    // Save informations to build a new call later
                    FunctionType *writeFunType = 
                        this->basicWriteFun->getFunctionType();  
                    info->targetType = writeFunType->getParamType(0);
                    LLVMContext &context = getGlobalContext();
                    IntegerType *intType;
                    if (this->is64Bit) {
                        intType = Type::getInt64Ty(context);
                    } else {
                        intType = Type::getInt32Ty(context);
                    }
                    info->targetModVal = ConstantInt::getSigned(intType,
                                        reinterpret_cast<intptr_t>(targetMod));
                    info->dataArg = cs.getArgument(2);
                    work->push_back(info);
                    }
   
                } else
                    
                // === Read ===
                if (!strcmp(name.c_str(), rFunName.c_str())) {
                    
                    // Not yet supported
                                        
                }
            }  
        }
    
    }
        
    // Before
    //procf->dump();
    
    // Replace calls
    std::vector<CallInfo*>::iterator it;
    for (it = work->begin(); it!=work->end(); ++it) {
        CallInfo *i = *it;
        
        LLVMContext &context = getGlobalContext();
        FunctionType *writeFunType = 
        this->writeFun->getFunctionType();
        IntegerType *i64 = Type::getInt64Ty(context);
        // Get a pointer to the target module
        basic::target_module_base *tmb = 
        dynamic_cast<basic::target_module_base*>(targetMod);
        Value *ptr = 
        ConstantInt::getSigned(i64, reinterpret_cast<intptr_t>(tmb));
        IntToPtrInst *modPtr = new IntToPtrInst(ptr, 
                                                writeFunType->getParamType(0),
                                                "myitp", i->oldcall);
        // Get a the address value
        LoadInst *addr = new LoadInst(i->addrArg, "", i->oldcall);
        
        // Create the new call
        Value *args[] = {modPtr, addr, i->dataArg};
        i->newcall = CallInst::Create(this->writeFun, ArrayRef<Value*>(args, 3));
        
        // Replace the old call
        BasicBlock::iterator it(i->oldcall);
        ReplaceInstWithInst(i->oldcall->getParent()->getInstList(), it, i->newcall);
        i->oldcall->replaceAllUsesWith(i->newcall);
        
        // Inline the new call
        DataLayout *td = new DataLayout(this->llvmMod);
        InlineFunctionInfo ifi(NULL, td);
        bool success = InlineFunction(i->newcall, ifi);
        if(!success) {
            MSG("       The call cannot be inlined (it's not an error :D)");
        }
        
        MSG("       Call optimized (^_-)\n");
        callOptCounter++;
    }
    
    //std::cout << "==================================\n";
    // Run preloaded passes on the function to propagate constants
    funPassManager->run(*procf);
    // After
    //procf->dump();        
    // Check if the function is corrupt
    verifyFunction(*procf);
    this->engine->recompileAndRelinkFunction(procf);
}
示例#21
0
文件: ccall.cpp 项目: Hanwendi/julia
// ccall(pointer, rettype, (argtypes...), args...)
static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
{
    JL_NARGSV(ccall, 3);
    jl_value_t *rt=NULL, *at=NULL;
    JL_GC_PUSH2(&rt, &at);

    native_sym_arg_t symarg = interpret_symbol_arg(args[1], ctx, "ccall");
    Value *jl_ptr=NULL;
    void *fptr = NULL;
    char *f_name = NULL, *f_lib = NULL;
    jl_ptr = symarg.jl_ptr;
    fptr = symarg.fptr;
    f_name = symarg.f_name;
    f_lib = symarg.f_lib;
    if (f_name == NULL && fptr == NULL && jl_ptr == NULL) {
        JL_GC_POP();
        emit_error("ccall: null function pointer", ctx);
        return literal_pointer_val(jl_nothing);
    }

    rt  = jl_interpret_toplevel_expr_in(ctx->module, args[2],
                                        &jl_tupleref(ctx->sp,0),
                                        jl_tuple_len(ctx->sp)/2);
    if (jl_is_tuple(rt)) {
        std::string msg = "in " + ctx->funcName +
            ": ccall: missing return type";
        jl_error(msg.c_str());
    }
    if (rt == (jl_value_t*)jl_pointer_type)
        jl_error("ccall: return type Ptr should have an element type, Ptr{T}");
    at  = jl_interpret_toplevel_expr_in(ctx->module, args[3],
                                        &jl_tupleref(ctx->sp,0),
                                        jl_tuple_len(ctx->sp)/2);

    JL_TYPECHK(ccall, type, rt);
    JL_TYPECHK(ccall, tuple, at);
    JL_TYPECHK(ccall, type, at);
    jl_tuple_t *tt = (jl_tuple_t*)at;
    std::vector<Type *> fargt(0);
    std::vector<Type *> fargt_sig(0);
    Type *lrt = julia_struct_to_llvm(rt);
    if (lrt == NULL) {
        JL_GC_POP();
        emit_error("ccall: return type doesn't correspond to a C type", ctx);
        return literal_pointer_val(jl_nothing);
    }
    size_t i;
    bool isVa = false;
    size_t nargt = jl_tuple_len(tt);
    std::vector<AttributeWithIndex> attrs;

    for(i=0; i < nargt; i++) {
        jl_value_t *tti = jl_tupleref(tt,i);
        if (tti == (jl_value_t*)jl_pointer_type)
            jl_error("ccall: argument type Ptr should have an element type, Ptr{T}");
        if (jl_is_vararg_type(tti)) {
            isVa = true;
            tti = jl_tparam0(tti);
        }
        if (jl_is_bitstype(tti)) {
            // see pull req #978. need to annotate signext/zeroext for
            // small integer arguments.
            jl_datatype_t *bt = (jl_datatype_t*)tti;
            if (bt->size < 4) {
                if (jl_signed_type == NULL) {
                    jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed"));
                }
#ifdef LLVM32
                Attributes::AttrVal av;
                if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0))
                    av = Attributes::SExt;
                else
                    av = Attributes::ZExt;
                attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1,
                                                        ArrayRef<Attributes::AttrVal>(&av, 1)));
#else
                Attribute::AttrConst av;
                if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0))
                    av = Attribute::SExt;
                else
                    av = Attribute::ZExt;
                attrs.push_back(AttributeWithIndex::get(i+1, av));
#endif
            }
        }
        Type *t = julia_struct_to_llvm(tti);
        if (t == NULL) {
            JL_GC_POP();
            std::stringstream msg;
            msg << "ccall: the type of argument ";
            msg << i+1;
            msg << " doesn't correspond to a C type";
            emit_error(msg.str(), ctx);
            return literal_pointer_val(jl_nothing);
        }
        fargt.push_back(t);
        if (!isVa)
            fargt_sig.push_back(t);
    }
    // check for calling convention specifier
    CallingConv::ID cc = CallingConv::C;
    jl_value_t *last = args[nargs];
    if (jl_is_expr(last)) {
        jl_sym_t *lhd = ((jl_expr_t*)last)->head;
        if (lhd == jl_symbol("stdcall")) {
            cc = CallingConv::X86_StdCall;
            nargs--;
        }
        else if (lhd == jl_symbol("cdecl")) {
            cc = CallingConv::C;
            nargs--;
        }
        else if (lhd == jl_symbol("fastcall")) {
            cc = CallingConv::X86_FastCall;
            nargs--;
        }
        else if (lhd == jl_symbol("thiscall")) {
            cc = CallingConv::X86_ThisCall;
            nargs--;
        }
    }
    
    if ((!isVa && jl_tuple_len(tt)  != (nargs-2)/2) ||
        ( isVa && jl_tuple_len(tt)-1 > (nargs-2)/2))
        jl_error("ccall: wrong number of arguments to C function");

    // some special functions
    if (fptr == &jl_array_ptr) {
        assert(lrt->isPointerTy());
        Value *ary = emit_expr(args[4], ctx);
        JL_GC_POP();
        return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt),
                               rt);
    }
    if (fptr == &jl_value_ptr) {
        assert(lrt->isPointerTy());
        jl_value_t *argi = args[4];
        bool addressOf = false;
        if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) {
            addressOf = true;
            argi = jl_exprarg(argi,0);
        }
        Value *ary = boxed(emit_expr(argi, ctx));
        JL_GC_POP();
        return mark_julia_type(
                builder.CreateBitCast(emit_nthptr_addr(ary, addressOf?1:0),lrt),
                rt);
    }

    // make LLVM function object for the target
    Value *llvmf;
    FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa);
    
    if (jl_ptr != NULL) {
        null_pointer_check(jl_ptr,ctx);
        Type *funcptype = PointerType::get(functype,0);
        llvmf = builder.CreateIntToPtr(jl_ptr, funcptype);
    }
    else if (fptr != NULL) {
        Type *funcptype = PointerType::get(functype,0);
        llvmf = literal_pointer_val(fptr, funcptype);
    }
    else {
        void *symaddr;
        if (f_lib != NULL)
            symaddr = add_library_sym(f_name, f_lib);
        else
            symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name);
        if (symaddr == NULL) {
            JL_GC_POP();
            std::stringstream msg;
            msg << "ccall: could not find function ";
            msg << f_name;
            if (f_lib != NULL) {
                msg << " in library ";
                msg << f_lib;
            }
            emit_error(msg.str(), ctx);
            return literal_pointer_val(jl_nothing);
        }
        llvmf = jl_Module->getOrInsertFunction(f_name, functype);
    }

    // save place before arguments, for possible insertion of temp arg
    // area saving code.
    Value *saveloc=NULL;
    Value *stacksave=NULL;
    BasicBlock::InstListType &instList = builder.GetInsertBlock()->getInstList();
    Instruction *savespot;
    if (instList.empty()) {
        savespot = NULL;
    }
    else {
        // hey C++, there's this thing called pointers...
        Instruction &_savespot = builder.GetInsertBlock()->back();
        savespot = &_savespot;
    }

    // emit arguments
    Value *argvals[(nargs-3)/2];
    int last_depth = ctx->argDepth;
    int nargty = jl_tuple_len(tt);
    bool needTempSpace = false;
    for(i=4; i < nargs+1; i+=2) {
        int ai = (i-4)/2;
        jl_value_t *argi = args[i];
        bool addressOf = false;
        if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) {
            addressOf = true;
            argi = jl_exprarg(argi,0);
        }
        Type *largty;
        jl_value_t *jargty;
        if (isVa && ai >= nargty-1) {
            largty = fargt[nargty-1];
            jargty = jl_tparam0(jl_tupleref(tt,nargty-1));
        }
        else {
            largty = fargt[ai];
            jargty = jl_tupleref(tt,ai);
        }
        Value *arg;
        if (largty == jl_pvalue_llvmt ||
                largty->isStructTy()) {
            arg = emit_expr(argi, ctx, true);
        }
        else {
            arg = emit_unboxed(argi, ctx);
            if (jl_is_bitstype(expr_type(argi, ctx))) {
                if (addressOf)
                    arg = emit_unbox(largty->getContainedType(0), largty, arg);
                else
                    arg = emit_unbox(largty, PointerType::get(largty,0), arg);
            }
        }
        /*
#ifdef JL_GC_MARKSWEEP
        // make sure args are rooted
        if (largty->isPointerTy() &&
            (largty == jl_pvalue_llvmt ||
             !jl_is_bits_type(expr_type(args[i], ctx)))) {
            make_gcroot(boxed(arg), ctx);
        }
#endif
        */
        bool mightNeed=false;
        argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf,
                                      ai+1, ctx, &mightNeed);
        needTempSpace |= mightNeed;
    }
    if (needTempSpace) {
        // save temp argument area stack pointer
        // TODO: inline this
        saveloc = CallInst::Create(save_arg_area_loc_func);
        stacksave = CallInst::Create(Intrinsic::getDeclaration(jl_Module,
                                                               Intrinsic::stacksave));
        if (savespot)
            instList.insertAfter(savespot, (Instruction*)saveloc);
        else
            instList.push_front((Instruction*)saveloc);
        instList.insertAfter((Instruction*)saveloc, (Instruction*)stacksave);
    }
    // the actual call
    Value *result = builder.CreateCall(llvmf,
                                       ArrayRef<Value*>(&argvals[0],(nargs-3)/2));
    if (cc != CallingConv::C)
        ((CallInst*)result)->setCallingConv(cc);

#ifdef LLVM32
    ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef<AttributeWithIndex>(attrs)));
#else
    ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size()));
#endif
    if (needTempSpace) {
        // restore temp argument area stack pointer
        assert(saveloc != NULL);
        builder.CreateCall(restore_arg_area_loc_func, saveloc);
        assert(stacksave != NULL);
        builder.CreateCall(Intrinsic::getDeclaration(jl_Module,
                                                     Intrinsic::stackrestore),
                           stacksave);
    }
    ctx->argDepth = last_depth;
    if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall
#ifdef LLVM32        
        ctx->f->addFnAttr(Attributes::StackProtectReq);
#else
        ctx->f->addFnAttr(Attribute::StackProtectReq);
#endif
    }

    JL_GC_POP();
    if (lrt == T_void)
        return literal_pointer_val((jl_value_t*)jl_nothing);
    if (lrt->isStructTy()) {
        //fprintf(stderr, "ccall rt: %s -> %s\n", f_name, ((jl_tag_type_t*)rt)->name->name->name);
        assert(jl_is_structtype(rt));
        Value *strct =
            builder.CreateCall(jlallocobj_func,
                               ConstantInt::get(T_size,
                                    sizeof(void*)+((jl_datatype_t*)rt)->size));
        builder.CreateStore(literal_pointer_val((jl_value_t*)rt),
                            emit_nthptr_addr(strct, (size_t)0));
        builder.CreateStore(result,
                            builder.CreateBitCast(
                                emit_nthptr_addr(strct, (size_t)1),
                                PointerType::get(lrt,0)));
        return mark_julia_type(strct, rt);
    }
    return mark_julia_type(result, rt);
}
// =============================================================================
// createProcess
// 
// Create a new function that contains a call to the old function.
// We inline the call in order to clone the old function's implementation.
// =============================================================================
Function *TLMBasicPassImpl::createProcess(Function *oldProc, 
                                      sc_core::sc_module *initiatorMod) {
    
    LLVMContext &context = getGlobalContext();
    IntegerType *intType;
    if (this->is64Bit) {
        intType = Type::getInt64Ty(context);
    } else {
        intType = Type::getInt32Ty(context);
    }
    
    // Retrieve a pointer to the initiator module 
    ConstantInt *initiatorModVal = 
    ConstantInt::getSigned(intType,reinterpret_cast<intptr_t>(initiatorMod));
    FunctionType *funType = oldProc->getFunctionType();  
    Type *type = funType->getParamType(0);
    IntToPtrInst *thisAddr = 
    new IntToPtrInst(initiatorModVal, type, "");
    
    // Compute the type of the new function
    FunctionType *oldProcType = oldProc->getFunctionType();
    Value **argsBegin = new Value*[1];
    Value **argsEnd = argsBegin;
    *argsEnd++ = thisAddr;
    const unsigned argsSize = argsEnd-argsBegin;
    Value **args = argsBegin;
    assert(oldProcType->getNumParams()==argsSize);
    assert(!oldProc->isDeclaration());
    std::vector<Type*> argTypes;
    for (unsigned i = 0; i!=argsSize; ++i)
            argTypes.push_back(oldProcType->getParamType(i));
    FunctionType *newProcType =
    FunctionType::get(oldProc->getReturnType(), ArrayRef<Type*>(argTypes), false);
    
    // Create the new function
    std::ostringstream id;
    id << proc_counter++;
    std::string name = oldProc->getName().str()+std::string("_clone_")+id.str();
    Function *newProc = 
    Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod);
    assert(newProc->empty());
    newProc->addFnAttr(Attributes::InlineHint);
    
    { // Set name of newfunc arguments and complete args
        Function::arg_iterator nai = newProc->arg_begin();
        Function::arg_iterator oai = oldProc->arg_begin();
        for (unsigned i = 0; i!=argsSize; ++i, ++oai) {
                nai->setName(oai->getName());
                args[i] = nai;
                ++nai;
        }
        assert(nai==newProc->arg_end());
        assert(oai==oldProc->arg_end());
    }
    
    // Create call to old function
    BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
    IRBuilder<> *irb = new IRBuilder<>(context);
    irb->SetInsertPoint(bb);
    CallInst *ci = irb->CreateCall(oldProc, ArrayRef<Value*>(argsBegin, argsEnd));
    bb->getInstList().insert(ci, thisAddr);
    if (ci->getType()->isVoidTy())
        irb->CreateRetVoid();
    else
        irb->CreateRet(ci);

    // The function should be valid now
    verifyFunction(*newProc);
    
    { // Inline the call
        DataLayout *td = new DataLayout(this->llvmMod);
        InlineFunctionInfo i(NULL, td);
        bool success = InlineFunction(ci, i);
        assert(success);
        verifyFunction(*newProc);
    }    
    
    //newProc->dump();
    return newProc;
}
示例#23
0
文件: test.cpp 项目: DragonL/YAC6xSim
int main(int argc, char** argv){
  // verif M unit
#ifdef CORE_DBG
  verif_m_unit();
#endif

  if(argc < 2)
  {
    return 0;
  }

  Core *pCore = Core::start();
  pCore->init();
  COFF_parser parser(argv[1]);
  pCore->set_mode(BK_AT_MAIN);

  if(argc >= 3)
  {
    core_mode_t mode = (core_mode_t)strtoul(argv[2],NULL,10);
    pCore->set_mode(mode);
  }

  if(argc >= 4)
  {
    word_t thres = strtoul(argv[3],NULL,10);
    Profiler::set_jit_threshold_times(thres);
  }

  if(argc >= 5)
  {
    word_t thres = strtoul(argv[4],NULL,10);
    Profiler::set_jit_threshold_len(thres);
  }

  parser.connect(pCore);
  parser.set_reverse(false);
  parser.parse();
  
  pCore->init();
#if 0
  pCore->reg_write(0,0,2); // A0 = 2
  pCore->reg_write(1,0,3); // B0 = 3

  llvm::Function *func = llvm::cast<llvm::Function>(Core::get_llvm_module().getOrInsertFunction("func",
    Type::getInt32Ty(getGlobalContext()),(Type*)0));
  llvm::BasicBlock* bb = llvm::BasicBlock::Create(getGlobalContext(),"entry",func);
  Core::get_llvm_builder().SetInsertPoint(bb);
  llvm::Constant* a_side_addr = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getGlobalContext())
    ,(uint64_t)pCore->get_reg_a());
  llvm::Constant* b_side_addr = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getGlobalContext())
    ,(uint64_t)pCore->get_reg_b());
  llvm::Constant* dst_addr = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getGlobalContext())
    ,(uint64_t)(pCore->get_reg_b()+1)); // B1
  llvm::Value* a_side = llvm::ConstantExpr::getIntToPtr(a_side_addr,
    llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(getGlobalContext())));
  llvm::Value* b_side = llvm::ConstantExpr::getIntToPtr(b_side_addr,
    llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(getGlobalContext())));

  llvm::Value* b1 = llvm::ConstantExpr::getIntToPtr(dst_addr,
    llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(getGlobalContext())));

  llvm::Value* left = Core::get_llvm_builder().CreateLoad(a_side);
  llvm::Value* right = Core::get_llvm_builder().CreateLoad(b_side);
  llvm::Value* re = Core::get_llvm_builder().CreateAdd(left,right);
  Core::get_llvm_builder().CreateStore(re,b1,true);

  Core::get_llvm_builder().CreateRet(re);

  ExecutionEngine* EE = EngineBuilder(&Core::get_llvm_module()).create();

  // Call the `foo' function with no arguments:
  //std::vector<GenericValue> noargs;
  //GenericValue gv = EE->runFunction(func, noargs);
  void* FPtr = EE->getPointerToFunction(func);
  int (*FP)() = (int (*)())(intptr_t)FPtr;
  FP();

  // Import result of execution:
  std::cout << "Result: " << pCore->reg_read(B_SIDE,1) << "\n";
  //outs() << "re: " << gv.IntVal << "\n";
#endif

#if 0
  pCore->reg_write(A_SIDE,3,0xFF);
  de_func_t de_func = JIT::gen_su_de_32bit_1or2_src_shl_f2_nc(pCore,0x018d0ca0);

  c6x::Instruction inst;

  pCore->reg_ch_num = 1;
  de_func(pCore,&inst);
  pCore->step();

  std::cout << to_hex_str(pCore->reg_read(A_SIDE,3)) << "\n";

  system("pause");
#endif
  pCore->run();

  return 0;
} 
示例#24
0
RCntxt globalContext()
{
   return RCntxt(getGlobalContext());
}
示例#25
0
 emscripten::val ContextWebAudio::getRawContext()
 {
   return getGlobalContext();
 }
示例#26
0
 CodeGenContext::CodeGenContext()
 {
     module = new Module("main", getGlobalContext());
     blocks = new stack<CodeGenBlock *>();
 }
void WasmScript::GenerateGeneralScriptCalls(WasmFile* file) {
  // Now generate this function prototype: execute_script:
    // Returns a integer is the result of all script.
    //  If successful, returns -1.
    //  It will fail otherwise and return the line number of the failure.

  // This method has no parameters.
  std::vector<llvm::Type*> params;

  // Then get the result: integer.
  llvm::Type* result_type = llvm::Type::getInt32Ty(llvm::getGlobalContext());
  WasmModule* wasm_module = file->GetAssertModule();
  llvm::Module* module = wasm_module->GetModule();

  // Finally, create the function type.
  llvm::FunctionType* fct_type = llvm::FunctionType::get(result_type, params, false);
  const char* name = "execute_script";
  llvm::Function* fct = llvm::Function::Create(fct_type, Function::ExternalLinkage, name, module);

  // Now create the first bb.
  llvm::BasicBlock* bb = llvm::BasicBlock::Create(getGlobalContext(), "entry", fct);
  llvm::IRBuilder<> builder(getGlobalContext());
  builder.SetInsertPoint(bb);

  WasmFunction* wasm_fct = new WasmFunction(nullptr, name, fct, wasm_module, INT_32);
  const char* result_name = "result";
  Variable* result = new Variable(result_name);
  wasm_fct->Allocate(result_name,
                         llvm::Type::getInt32Ty(llvm::getGlobalContext()),
                         builder);

  // Now generate our IR and then use our codegen for it.
  for (auto elem : script_elems_) {
    Expression* expr = nullptr;

    if (dynamic_cast<WasmInvoke*>(elem) != nullptr) {
      expr = HandleInvoke(elem);
    } else {
      CallExpression* call = HandleAssert(wasm_module, elem);

      // Set the value in a local.
      SetLocal* set = new SetLocal(result, call);

      // In the assert_return case, we want to compare this to -1.
      Const* minus_one = new Const(INT_32, new ValueHolder(-1));
      Operation* op = new Operation(NE_OPER, INT_32);
      Binop* cmp = new Binop(op, set, minus_one);

      // Now we can generate the return 0;
      GetLocal* get = new GetLocal(result);
      ReturnExpression* return_expr = new ReturnExpression(get);

      // Finally, generate the AST for this assert.
      IfExpression* inst = new IfExpression(cmp, return_expr);

      expr = inst;
    }

    // Now we can generate it.
    expr->Codegen(wasm_fct, builder);

    delete expr, expr = nullptr;
  }

  Const* one = new Const(INT_32,
      new ValueHolder(-1));
  ReturnExpression* return_expr = new ReturnExpression(one);

  return_expr->Codegen(wasm_fct, builder);

  delete return_expr, return_expr = nullptr;
}
示例#28
0
Value *FuncDef::compile(CodeGen &gen) const {
  log.debug("Compiling function '%s'", ident->getName()->c_str());
  LLVMContext *context = &gen.getBuilder()->getContext();
  IRBuilder<> &b = *gen.getBuilder();

  // TODO map types
  std::vector<llvm::Type *> fn_args;

  for (unsigned int i = 0; i < args->size(); i++) {
    llvm::Type *argType = llvm::Type::getInt32Ty(*context);
    fn_args.push_back(argType);
  }

  FunctionType *ft =
      FunctionType::get(llvm::Type::getInt32Ty(*context), fn_args, false);

  Function *fn = Function::Create(ft, Function::ExternalLinkage,
                                  *ident->getName(), gen.getModule());
  gen.registerFunction(fn);

  BasicBlock *bb =
      BasicBlock::Create(getGlobalContext(), *ident->getName(), fn);
  BasicBlock *last_block = gen.getBuilder()->GetInsertBlock();
  gen.getBuilder()->SetInsertPoint(bb);

  // store each arg in memory so that it can be retreived
  // by the Ident node
  unsigned int i = 0;

  for (Function::arg_iterator it = fn->arg_begin(); i != args->size();
       ++it, ++i) {
    it->setName(*args->getIdent(i).getName());

    log.debug("Saving arg '%s' into memory",
              args->getIdent(i).getName()->c_str());
    llvm::Type *mem_type = llvm::Type::getInt32Ty(*context);
    ConstantInt *mem_count = b.getInt32(1);
    AllocaInst *mem = b.CreateAlloca(mem_type, mem_count, "arg_ptr");

    b.CreateStore(it, mem);  // just returns a void Value
    gen.registerValue(*args->getIdent(i).getName(), mem);
  }

  // generate function termintaor
  Value *terminator = NULL;

  if (block != NULL) {
    const Node *current = block;

    while (current != NULL) {
      log.debug("Compiling node in block");
      terminator = current->compile(gen);
      current = current->getNext();

      if (current == NULL) {
        log.debug("Next node in block is NULL");
      }
    }
  } else {
    terminator = ConstantInt::get(*context, APInt(32, 0, false));
  }

  gen.getBuilder()->CreateRet(terminator);

  gen.getBuilder()->SetInsertPoint(last_block);

  return fn;
}
示例#29
0
  bool
  LoopBarriers::ProcessLoop(Loop *L, LPPassManager &LPM)
  {
    bool isBLoop = false;
    bool changed = false;
  
    for (Loop::block_iterator i = L->block_begin(), e = L->block_end();
         i != e && !isBLoop; ++i) {
      for (BasicBlock::iterator j = (*i)->begin(), e = (*i)->end();
           j != e; ++j) {
        if (isa<BarrierInst>(j)) {
            isBLoop = true;
            break;
        }
      }
    }

    LLVMContext &LC = getGlobalContext();
    IntegerType * IntTy = IntegerType::get(LC, 32);
    Value *Args = ConstantInt::get(IntTy, 0);
  
    for (Loop::block_iterator i = L->block_begin(), e = L->block_end();
         i != e && isBLoop; ++i) {
      for (BasicBlock::iterator j = (*i)->begin(), e = (*i)->end();
           j != e; ++j) {
        if (isa<BarrierInst>(j)) {
          BasicBlock *preheader = L->getLoopPreheader();
          assert((preheader != NULL) && "Non-canonicalized loop found!\n");
          Instruction *PhdrBarrierInst = 
            BarrierInst::createBarrier(Args, preheader->getTerminator());
          MDNode* PhdrAuxBarrierInfo = 
            MDNode::get(LC, MDString::get(LC, "auxiliary phdr barrier"));
          PhdrBarrierInst->setMetadata("aux.phdr.barrier", PhdrAuxBarrierInfo);
          preheader->setName(preheader->getName() + ".loopbarrier");
  
          BasicBlock *header = L->getHeader();
          if (header->getFirstNonPHI() != &header->front()) {
            Instruction *HdrBarrierInst = 
              BarrierInst::createBarrier(Args, header->getFirstNonPHI());
            MDNode* HdrAuxBarrierInfo = 
              MDNode::get(LC, MDString::get(LC,  "auxiliary phihdr barrier"));
            HdrBarrierInst->setMetadata("aux.phihdr.barrier", HdrAuxBarrierInfo);
            header->setName(header->getName() + ".phibarrier");
          }
 
          /*
          SmallVector<BasicBlock*, 8> ExitingBlocks;
          L->getExitingBlocks(ExitingBlocks);
          */
          BasicBlock *brexit = L->getExitingBlock();
          if (brexit != NULL) {
            Instruction *ExitingBarrierInst = 
              BarrierInst::createBarrier(Args, brexit->getTerminator());
            MDNode* ExitingAuxBarrierInfo =
              MDNode::get(LC, MDString::get(LC, "auxiliary exiting barrier"));
            ExitingBarrierInst->setMetadata("aux.exiting.barrier", 
                                            ExitingAuxBarrierInfo);
            brexit->setName(brexit->getName() + ".brexitbarrier");
          }
  
          BasicBlock *latch = L->getLoopLatch();
          if (latch != NULL && brexit != latch) {
            Instruction *LatchBarrierInst =
              BarrierInst::createBarrier(Args, latch->getTerminator());
            MDNode* LatchAuxBarrierInfo =
              MDNode::get(LC, MDString::get(LC, "auxiliary latch barrier"));
            LatchBarrierInst->setMetadata("aux.latch.barrier", 
                                          LatchAuxBarrierInfo);
            latch->setName(latch->getName() + ".latchbarrier");
            return changed;
          }
  
          BasicBlock *Header = L->getHeader();
          typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
          InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(Header);
          InvBlockTraits::ChildIteratorType PE = InvBlockTraits::child_end(Header);
          BasicBlock *Latch = NULL;
          for (; PI != PE; ++PI) {
            InvBlockTraits::NodeType *N = *PI;
            if (L->contains(N)) {
              Latch = N;
              if (DT->dominates(j->getParent(), Latch)) {
                BarrierInst::createBarrier(Args, Latch->getTerminator());
                Latch->setName(Latch->getName() + ".latchbarrier");
              }
            }
          }
          return true;
        }
      }
    }
  
    BasicBlock *preheader = L->getLoopPreheader();
    assert((preheader != NULL) && "Non-canonicalized loop found!\n");
    TerminatorInst *t = preheader->getTerminator();
    Instruction *prev = NULL;
    if (&preheader->front() != t) {
      // If t is not the first/only instruction in the block, get the previous
      // instruction.
      prev = t->getPrevNode();
    }

    if (prev && isa<BarrierInst>(prev)) {
        BasicBlock *new_b = SplitBlock(preheader, t, this);
        new_b->setName(preheader->getName() + ".postbarrier_dummy");
        return true;
    }
  
    return changed;
  }
示例#30
0
namespace nqp {

static IRBuilder<> Builder(getGlobalContext());
static const PointerType *GenericPointerType = Type::getInt8PtrTy(getGlobalContext(), 0);

CodeGenContext::CodeGenContext(LLVMContext &context) : context(context) { 
  module = new Module(StringRef("main"), context);

  vector<const Type*> Args = vector<const Type*>(1, Type::getInt64Ty(getGlobalContext()));
  FunctionType *FT = FunctionType::get(GenericPointerType, Args, false);
  Function::Create(FT, Function::ExternalLinkage, "construct_int", module);

  Args = vector<const Type*>(1, Type::getDoubleTy(getGlobalContext()));
  FT = FunctionType::get(GenericPointerType, Args, false);
  Function::Create(FT, Function::ExternalLinkage, "construct_num", module);

  FT = FunctionType::get(GenericPointerType, false);
  Function::Create(FT, Function::ExternalLinkage, "construct_array", module);

  Args = vector<const Type*>();
  Args.push_back(GenericPointerType);
  Args.push_back(GenericPointerType);
  FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), Args, false);
  Function::Create(FT, Function::ExternalLinkage, "array_push", module);

  Args = vector<const Type*>();
  Args.push_back(Type::getInt8PtrTy(getGlobalContext()));
  Args.push_back(Type::getInt64Ty(getGlobalContext()));
  FT = FunctionType::get(GenericPointerType, Args, false);
  Function::Create(FT, Function::ExternalLinkage, "construct_str", module);

  Args = vector<const Type*>();
  Args.push_back(Type::getInt8PtrTy(getGlobalContext()));
  Args.push_back(Type::getInt64Ty(getGlobalContext()));
  FT = FunctionType::get(GenericPointerType, Args, false);
  Function::Create(FT, Function::ExternalLinkage, "construct_str", module);

  FT = FunctionType::get(GenericPointerType, true);
  Function::Create(FT, Function::ExternalLinkage, "vm_dispatch", module);
}

/* Compile the AST into a module */
void CodeGenContext::generateCode(Block& root)
{
  std::cout << "Generating code...\n";
  std::cout << "Nodes: " << root.statements.size() << "\n";

  /* Create the top level interpreter function to call as entry */
  vector<const Type*> argTypes;
  FunctionType *ftype = FunctionType::get(Type::getVoidTy(getGlobalContext()), argTypes, false);
  mainFunction = Function::Create(ftype, GlobalValue::InternalLinkage, "main", module);
  BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", mainFunction, 0);
  
  /* Push a new variable/block context */
  pushBlock(bblock);
  root.codeGen(*this); /* emit bytecode for the toplevel block */
  ReturnInst::Create(getGlobalContext(), bblock);
  popBlock();
  
  /* Print the bytecode in a human-readable format 
     to see if our program compiled properly
   */
  std::cout << "Code is generated.\n";
  PassManager pm;
  pm.add(createPrintModulePass(&outs()));
  pm.run(*module);
}

/* Executes the AST by running the main function */
GenericValue CodeGenContext::runCode() {
  std::cout << "Running code...\n";
  //ExistingModuleProvider *mp = new ExistingModuleProvider(module);
  ExecutionEngine *ee = ExecutionEngine::create(module, false);
  vector<GenericValue> noargs;
  GenericValue v = ee->runFunction(mainFunction, noargs);
  std::cout << "Code was run.\n";
  return v;
}

/* Returns an LLVM type based on the identifier */
static const Type *typeOf(const Identifier& type) 
{
  cout << "typeOf.? " << endl;
  if (type.name.compare("int") == 0) {
    return  Type::getInt64Ty(getGlobalContext());
  }
  else if (type.name.compare("double") == 0) {
    return Type::getDoubleTy(getGlobalContext());
  }
  return Type::getVoidTy(getGlobalContext());
}

/* -- Code Generation -- */

Value* IntegerConstant::codeGen(CodeGenContext& context) {
  std::cout << "Creating integer: " << value << endl;
  Function *construct_int = context.module->getFunction("construct_int");
  if (construct_int == NULL) {
    std::cerr << "Bad construct int" << endl;
  }
  std::vector<Value*> ArgsV;
  ArgsV.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), value, true));

  return CallInst::Create(construct_int, ArgsV.begin(), ArgsV.end(), "", context.currentBlock());
}

Value* DoubleConstant::codeGen(CodeGenContext& context) {
  std::cout << "Creating double: " << value << endl;
  Function *construct_num = context.module->getFunction("construct_num");
  if (construct_num == NULL) {
    std::cerr << "Bad construct int" << endl;
  }
  std::vector<Value*> ArgsV;
  ArgsV.push_back(ConstantFP::get(Type::getDoubleTy(getGlobalContext()), value));

  return CallInst::Create(construct_num, ArgsV.begin(), ArgsV.end(), "", context.currentBlock());
}

Value* StringConstant::codeGen(CodeGenContext& context) {
  std::cout << "Construing String: " << value << endl;

  Function *construct_str = context.module->getFunction("construct_str");
  if (construct_str == NULL) {
    std::cerr << "Bad construct int" << endl;
  }

  cout << "Value is: " << value << endl;
  
  GlobalVariable *val;
  StringMap<GlobalVariable*>::iterator iter = context.globals.find(value);
  if (iter == context.globals.end()) {
    const ArrayType *str_type = ArrayType::get(Type::getInt8Ty(getGlobalContext()),  value.length() + 1);

    std::vector<Constant *> ary_elements;
    for (unsigned int i = 1; i < value.length() - 1; i++) {
      ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), value[i]));
    }
    ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), 0));

    val = new GlobalVariable(*context.module, str_type, true, GlobalValue::InternalLinkage, ConstantArray::get(str_type, ary_elements), "");

    context.globals[value] = val;
  }
  else {
    val = iter->second;
  }

  std::vector<Value*> ArgsV;
  ArgsV.push_back(val);
  ArgsV.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), value.length() - 2));

  return CallInst::Create(construct_str, ArgsV.begin(), ArgsV.end(), "", context.currentBlock());
}

Value* Identifier::codeGen(CodeGenContext& context) {
  std::cout << "Creating identifier reference: " << name << endl;
  if (context.locals().find(name) == context.locals().end()) {
    std::cerr << "undeclared variable " << name << endl;
    return NULL;
  }
  return new LoadInst(context.locals()[name], "", false, context.currentBlock());
}

Value* BlockReturn::codeGen(CodeGenContext& context) {
  std::cout << "Creating return instruciton" << endl;

  ReturnInst *ret = ReturnInst::Create(getGlobalContext(), expression.codeGen(context));

  return ret;
}

Value* MethodCall::codeGen(CodeGenContext& context) {
  GlobalVariable *val;
  StringMap<GlobalVariable*>::iterator iter = context.globals.find(id.name);
    if (iter == context.globals.end()) {
    const ArrayType *str_type = ArrayType::get(Type::getInt8Ty(getGlobalContext()),  id.name.length() + 1);

    std::vector<Constant *> ary_elements;
    for (unsigned int i = 0; i < id.name.length(); i++) {
      ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), id.name[i]));
    }
    ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), 0));

    val = new GlobalVariable(*context.module, str_type, true, GlobalValue::InternalLinkage, ConstantArray::get(str_type, ary_elements), "");

    context.globals[id.name] = val;
  }
  else {
    val = iter->second;
  }
  
  Function *function = context.module->getFunction("vm_dispatch");

  std::vector<Value*> args;
  ExpressionList::const_iterator it;

  args.push_back(val);
  args.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), arguments->size(), true));
  for (it = arguments->begin(); it != arguments->end(); it++) {
    args.push_back((*it)->codeGen(context));
  }
  CallInst *call = CallInst::Create(function, args.begin(), args.end(), "", context.currentBlock());
  std::cout << "Creating method call: " << id.name << endl;
  return call;
}

Value* PrefixOp::codeGen(CodeGenContext& context) {
  string name;
  switch (op) {
    case token::T_PLUS:
      // Call prefix:<+> 
      name = "&prefix:<+>";
      break;
    case token::T_BAR:
      // Call infix:<|>
      name = "&prefix:<|>";
      break;
    case token::T_STITCH:
      // Call prefix:<~>
      name = "&prefix:<~>";
      break;
    default: { 
      /* not implemented */
      return NULL;
    }
  }

  Function *function = context.module->getFunction("vm_dispatch");

 	const ArrayType *str_type = ArrayType::get(Type::getInt8Ty(getGlobalContext()),  name.length() + 1);

	std::vector<Constant *> ary_elements;
	for (unsigned int i = 0; i < name.length(); i++) {
	  ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), name[i]));
	}
	ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), 0));

  GlobalVariable *method_name = new GlobalVariable(*context.module, str_type, true,
		  GlobalValue::InternalLinkage,
		  ConstantArray::get(str_type, ary_elements), "");

  std::vector<Value*> args;
  args.push_back(method_name);
  args.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 1, true));
  args.push_back(val.codeGen(context));

  return CallInst::Create(function, args.begin(), args.end(), "", context.currentBlock());
}

Value* BinaryOp::codeGen(CodeGenContext& context) {
  std::cout << "Creating infix operation " << op << endl;
  string name;
  switch (op) {
    case token::T_PLUS:
      // Call infix:<+> 
      name = "&infix:<+>";
      break;
    case token::T_MINUS:
      // Call infix:<->
      name = "&infix:<->";
      break;
    case token::T_MUL:
      // Call infix:<*>
      name = "&infix:<*>";
      break;
    case token::T_DIV:
      // Call infix:</>
      name = "&infix:</>";
      break;
    case token::T_STITCH:
      // Call infix:<~>
      name = "&infix:<~>";
      break;
    /* TODO comparison */
    default: { 
      /* not implemented */
      return NULL;
    }
  }

  Function *function = context.module->getFunction("vm_dispatch");

 	const ArrayType *str_type = ArrayType::get(Type::getInt8Ty(getGlobalContext()),  name.length() + 1);

	std::vector<Constant *> ary_elements;
	for (unsigned int i = 0; i < name.length(); i++) {
	  ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), name[i]));
	}
	ary_elements.push_back(ConstantInt::get(Type::getInt8Ty(getGlobalContext()), 0));

  GlobalVariable *val = new GlobalVariable(*context.module, str_type, true,
		GlobalValue::InternalLinkage,
		ConstantArray::get(str_type, ary_elements), "");

  std::vector<Value*> args;
  args.push_back(val);
  args.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 2, true));
  args.push_back(lhs.codeGen(context));
  args.push_back(rhs.codeGen(context));

  return CallInst::Create(function, args.begin(), args.end(), "", context.currentBlock());
}

Value* Assignment::codeGen(CodeGenContext& context) {
  if (context.locals().find(lhs.name) == context.locals().end()) {
    std::cerr << "undeclared variable " << lhs.name << endl;
    return NULL;
  }
  return new StoreInst(rhs.codeGen(context), context.locals()[lhs.name], false, context.currentBlock());
}

Value* Block::codeGen(CodeGenContext& context) {
  StatementList::const_iterator it;
  Value *last = NULL;
  // create
  unsigned int count = 0;
  for (it = statements.begin(); it != statements.end(); it++) {
    std::cout << "Generating code for " << typeid(**it).name() << endl;
    last = (**it).codeGen(context);
    count++;
    std::cout << "Generatoring code for " << count << endl;
  }
  std::cout << "Creating block" << endl;
  return last;
}

Value* ExpressionStatement::codeGen(CodeGenContext& context) {
  std::cout << "Generating code for " << typeid(expression).name() << endl;
  return expression.codeGen(context);
}

Value* VariableDeclaration::codeGen(CodeGenContext& context) {
  std::cout << "Creating variable declaration " << id.name << endl;
  AllocaInst *alloc = new AllocaInst(GenericPointerType, id.name.c_str(), context.currentBlock());
  context.locals()[id.name] = alloc;
  if (assignmentExpr != NULL) {
    Assignment assn(id, assignment, *assignmentExpr);
    assn.codeGen(context);
  }
  return alloc; 
}

Value* ListDeclaration::codeGen(CodeGenContext& context) {
  std::cout << "Constructing new Array of length: " << list_values->size() << endl;
  
  Function *function = context.module->getFunction("construct_array");

  Value* new_array = CallInst::Create(function, "", context.currentBlock());

  for (ExpressionList::iterator it = list_values->begin(); it != list_values->end(); ++it) {
    function = context.module->getFunction("array_push");
    
    std::vector<Value*> args;
    args.push_back(new_array);
    args.push_back((*it)->codeGen(context));
    
    CallInst::Create(function, args.begin(), args.end(), "", context.currentBlock());
  }

  return new_array;
}

Value* ParameterDeclaration::codeGen(CodeGenContext& context) {
  AllocaInst *alloc;
  return alloc;
}

Value* FunctionDeclaration::codeGen(CodeGenContext& context) {
  vector<const Type*> argTypes;
  ParameterList::const_iterator it;
  for (it = arguments.begin(); it != arguments.end(); it++) {
    //argTypes.push_back(typeOf((**it).type));
  }
  FunctionType *ftype = FunctionType::get(Type::getInt64Ty(getGlobalContext()), argTypes, false);
  Function *function = Function::Create(ftype, GlobalValue::InternalLinkage, id.name.c_str(), context.module);
  BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", function, 0);

  context.pushBlock(bblock);

  for (it = arguments.begin(); it != arguments.end(); it++) {
    (**it).codeGen(context);
  }
  
  block.codeGen(context);
  ReturnInst::Create(getGlobalContext(), bblock);

  context.popBlock();
  std::cout << "Creating function: " << id.name << endl;
  return function;
}

Value* IfBlock::codeGen(CodeGenContext& context) {
  return NULL;
}


} /* end namespace nqp */