Exemple #1
0
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) :
	CompilerHelper(_builder),
	m_runtimeManager(_runtimeManager)
{
	llvm::Type* gasCheckArgs[] = {Type::Gas->getPointerTo(), Type::Gas, Type::BytePtr};
	m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, gasCheckArgs, false), llvm::Function::PrivateLinkage, "gas.check", getModule());
	m_gasCheckFunc->setDoesNotThrow();
	m_gasCheckFunc->setDoesNotCapture(1);

	auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc);
	auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc);
	auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc);

	auto gasPtr = &m_gasCheckFunc->getArgumentList().front();
	gasPtr->setName("gasPtr");
	auto cost = gasPtr->getNextNode();
	cost->setName("cost");
	auto jmpBuf = cost->getNextNode();
	jmpBuf->setName("jmpBuf");

	InsertPointGuard guard(m_builder);
	m_builder.SetInsertPoint(checkBB);
	auto gas = m_builder.CreateLoad(gasPtr, "gas");
	auto gasUpdated = m_builder.CreateNSWSub(gas, cost, "gasUpdated");
	auto gasOk = m_builder.CreateICmpSGE(gasUpdated, m_builder.getInt64(0), "gasOk"); // gas >= 0, with gas == 0 we can still do 0 cost instructions
	m_builder.CreateCondBr(gasOk, updateBB, outOfGasBB, Type::expectTrue);

	m_builder.SetInsertPoint(updateBB);
	m_builder.CreateStore(gasUpdated, gasPtr);
	m_builder.CreateRetVoid();

	m_builder.SetInsertPoint(outOfGasBB);
	m_runtimeManager.abort(jmpBuf);
	m_builder.CreateUnreachable();
}
Exemple #2
0
void ASTInfo::code_gen(llvm::Module *M, llvm::IRBuilder<> &B)
{
    llvm::LLVMContext &context = M->getContext();

    if (!__brain_index_ptr) {
        // Create global variable |brain.index|
        llvm::Type *Ty = llvm::Type::getInt32Ty(context);
        const llvm::APInt Zero = llvm::APInt(32, 0); // int32 0
        llvm::Constant *InitV = llvm::Constant::getIntegerValue(Ty, Zero);
        ASTInfo::__brain_index_ptr = new llvm::GlobalVariable(*M, Ty, false,
                                          // Keep one copy when linking (weak)
                                          llvm::GlobalValue::WeakAnyLinkage,
                                          InitV,
                                          "brain.index");
    }

    if (!__brain_cells_ptr) {
        // Create |brain.cells|
        auto *ArrTy = llvm::ArrayType::get(llvm::Type::getInt32Ty(context),
                                           ArgsOptions::instance()->get_cells_size());
        // Create a vector of _k_cells_size items equal to 0
        std::vector<llvm::Constant *> constants(ArgsOptions::instance()->get_cells_size(),
                                                B.getInt32(0));
        llvm::ArrayRef<llvm::Constant *> Constants = llvm::ArrayRef<llvm::Constant *>(constants);
        llvm::Constant *InitPtr = llvm::ConstantArray::get(ArrTy, Constants);
        ASTInfo::__brain_cells_ptr = new llvm::GlobalVariable(*M, ArrTy, false,
                                          // Keep one copy when linking (weak)
                                          llvm::GlobalValue::WeakAnyLinkage,
                                          InitPtr,
                                          "brain.cells");
    }
}
void RestartOperation::EmitCompiledCode(llvm::IRBuilder<>& irb, llvm::Value * statePointer, llvm::Module * module)
{
	std::vector<llvm::Value*> argVector;
	argVector.push_back(statePointer);
	llvm::ArrayRef<llvm::Value*> argArrayRef(argVector);

	llvm::Function* callee = module->getFunction(metadata_.GetFunctionName());

	irb.CreateCall(callee, argArrayRef);
}
Exemple #4
0
void LLVMIRGen::setCurrentDebugLocation(llvm::IRBuilder<> &builder,
                                        glow::Instruction *I) {
  if (!emitDebugInfo)
    return;
  auto instrNum = instrNumbering_->getInstrNumber(I);
  auto DILoc = llvm::DILocation::get(
      ctx_, dbgInfo_.mainFileFirstInstrLineNo_ + instrNum, 0, dbgInfo_.mainF_);
  llvm::DebugLoc loc(DILoc);
  builder.SetCurrentDebugLocation(loc);
}
void WordOperandOperation::EmitCompiledCode(llvm::IRBuilder<>& irb, llvm::Value * statePointer, llvm::Module * module)
{
	llvm::ConstantInt* operandArgument = llvm::ConstantInt::get(module->getContext(), llvm::APInt(16, operand_));

	std::vector<llvm::Value*> argVector;
	argVector.push_back(statePointer);
	argVector.push_back(operandArgument);
	llvm::ArrayRef<llvm::Value*> argArrayRef(argVector);

	llvm::Function* callee = module->getFunction(metadata_.GetFunctionName());

	irb.CreateCall(callee, argArrayRef);
}
std::string SwitchExpression::HandleExpressionCase(ExpressionCaseDefinition* expr,
        std::map<llvm::BasicBlock*, llvm::Value*>& values,
        std::map<std::string, llvm::BasicBlock*>& association,
        WasmFunction* fct, llvm::IRBuilder<>& builder) {
    // Create a CaseExpression and generate the code like that.
    //  First step: find an unused name.
    std::string name = "anonymous_case";
    int idx = 0;
    std::string final_name;

    while (1) {
        std::ostringstream oss;
        oss << name << "_" << idx;
        final_name = oss.str();

        if (association.find(final_name) == association.end()) {
            break;
        }

        idx++;
    }

    // Create and generate the CaseExpression.
    std::list<Expression*> list;
    list.push_back(expr->GetExpression());
    CaseExpression case_expr(final_name.c_str(), &list);
    llvm::Value* value = case_expr.Codegen(nullptr, this, fct, builder, true);

    // Register it.
    llvm::BasicBlock* bb = builder.GetInsertBlock();
    std::string res = bb->getName();
    association[res] = bb;

    // And the value.
    values[bb] = value;

    return res;
}
Exemple #7
0
 llvm::Value* Load(llvm::Value* val)
 {
   if(val && isa<llvm::AllocaInst>(val))
     return builder.CreateLoad(val);
   return val;
 }
Exemple #8
0
void Simulator::Simulate()
{
  llvm::SMDiagnostic error;
  //std::unique_ptr<llvm::Module> M = llvm::ParseIRFile("Behavior.bc", error, context);
  //MyModule = M.get();
  MyModule = llvm::ParseIRFile("Behavior.bc", error, context);
  string err_str;
/*
    OwningPtr<MemoryBuffer> result;
    MemoryBuffer *mb;
    llvm::error_code ec = MemoryBuffer::getFile("Behavior.bc", result);
    mb = result.take();
    err_str = ec.message();
    if (!mb) {
      error() <<"Cannot open \"" <<bitcode_file() <<"\": " <<err_str <<endl;
      exit(1);
    }
    MyModule = llvm::ParseBitcodeFile(mb,context,&err_str);
    if (!MyModule) {
      error() <<"Failed to load module from bitcode file: " <<err_str <<endl;
      exit(1);
    }
    delete mb;
*/
/*
    for (llvm::Module::iterator f = MyModule->begin(), ef = MyModule->end(); f!=ef; ++f) 
    {
      f->addFnAttr(Attributes::AlwaysInline);
    }
*/
    for (int32_t i = 0; i < (int32_t)OPCODE::INVALID; i++) {
      OPCODE op = (OPCODE) i;
      llvm::Function *func = MyModule->getFunction(GetFuncName(op));
      func->addFnAttr(llvm::Attribute::AlwaysInline);
      OpFunctionMap[op] = func; 
    }
    test_type = MyModule->getFunction("test")->getFunctionType();


    std::string ErrStr;
    passManager = new llvm::PassManager();
    passManager->add(llvm::createAlwaysInlinerPass());
    fPassManager = new llvm::FunctionPassManager(MyModule);
    //fPassManager->add(new DataLayout(*EE->getDataLayout()));
    //fPassManager->add(new DataLayout(*EE->getDataLayout()));
    fPassManager->add(llvm::createGVNPass());
    fPassManager->add(llvm::createInstructionCombiningPass());
    fPassManager->add(llvm::createCFGSimplificationPass());
    fPassManager->add(llvm::createDeadStoreEliminationPass());

/*
    llvm::EngineBuilder builder(MyModule);
    builder.setErrorStr(&ErrStr);
    builder.setEngineKind(llvm::EngineKind::JIT);
    builder.setOptLevel(llvm::CodeGenOpt::Default); // None/Less/Default/Aggressive
    //llvm::TargetOptions options;
    //options.JITExceptionHandling = 1;
    //builder.setTargetOptions(options);
    EE = builder.create();
*/
  //StringRef MCPU = llvm::sys::getHostCPUName()
  EE = llvm::EngineBuilder(MyModule).create(); 
/*
    EE =
      llvm::EngineBuilder(std::move(M))
          .setErrorStr(&ErrStr)
          .setMCJITMemoryManager(llvm::make_unique<llvm::SectionMemoryManager>())
          .create();
*/
/*
    EE = llvm::EngineBuilder(M)
                .setErrorStr(&ErrStr)
                .setMCJITMemoryManager(llvm::SectionMemoryManager())
                .create();
    EE = llvm::EngineBuilder(std::move(M)).setErrorStr(&ErrStr).create();

*/
    if (!EE) {
      fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
      exit(1);
    }
    EE->DisableLazyCompilation(true);


/*
    //atexit(llvm_shutdown);  // Call llvm_shutdown() on exit.
    //llvm::EngineBuilder builder(MyModule);
    llvm::EngineBuilder builder(std::move(M));
    //llvm::EngineBuilder builder(MyModule);
    builder.setErrorStr(&err_str);
    builder.setEngineKind(llvm::EngineKind::JIT);
    builder.setOptLevel(llvm::CodeGenOpt::Default); // None/Less/Default/Aggressive
    //TargetOptions options;
    //options.JITExceptionHandling = 1;
    //builder.setTargetOptions(options);
    EE = builder.create();
    if (!EE) {
      std::cout <<"failed to create execution engine: " <<err_str <<"\n";
      exit(1);
    }
*/
/*
    //MyModule->dump();
    EE = llvm::EngineBuilder(std::move(M)).create();
*/
    //string ErrStr;
    //EE = llvm::EngineBuilder(std::move(M)).setErrorStr(&ErrStr).setMCPU("i386").create();


  //context = llvm::getGlobalContext();
  int32_t index = 0;
  Blocks = new HostBlock[1000];
  int32_t block_index = 0;
  while(index < total_inst) {

    Blocks[block_index].pc = index;  
    ostringstream f_name;
    f_name << "func";
    f_name << block_index;
    //string f_name = string("func");// + string(index);
/*
    llvm::Function *func =
      llvm::cast<llvm::Function>(MyModule->getOrInsertFunction(f_name.str(), 
            llvm::Type::getVoidTy(context), (llvm::Type *)0));
*/
  // Make the function type:  double(double,double) etc.
    //std::vector<Type*> Doubles(Args.size(),
    //                         Type::getDoubleTy(getGlobalContext()));
    llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), false);
    llvm::Function *func = llvm::Function::Create(FT, 
                                                  llvm::Function::ExternalLinkage,
                                                  f_name.str(),
                                                  MyModule);

//Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M);
    // Add a basic block to the function. As before, it automatically inserts
    // because of the last argument.
    llvm::BasicBlock *BB = llvm::BasicBlock::Create(context, "EntryBlock", func);

    // Create a basic block builder with default parameters.  The builder will
    // automatically append instructions to the basic block `BB'.
    IRB.SetInsertPoint(BB);
    llvm::Function *sim_func; 
    CInst *inst; 
    int b_size = 0;
    do {
        inst = &instructions[index];
        llvm::Value *dst = IRB.getInt32(inst->dst_reg);
        llvm::Value *src0 = IRB.getInt32(inst->src0_reg);
        llvm::Value *src1 = IRB.getInt32(inst->src1_reg);
        sim_func = OpFunctionMap[inst->opcode];
        llvm::Value *oprnds[] = {dst, src0, src1};
        llvm::ArrayRef <llvm::Value *> ref(oprnds, 3);
        IRB.CreateCall(sim_func, ref);
        index++;
        b_size++;
        //cout << "Index " << index << endl;
    //} while(b_size < 10 || inst->opcode != OPCODE::JMP);
    } while(b_size < 10  && index < total_inst);
    IRB.CreateRetVoid();  
    passManager->run(*MyModule); 
    fPassManager->run(*func);
    EE->finalizeObject();
    //std::vector<llvm::GenericValue> noargs;
    //std::cout << "calling " << f_name.str() << endl;
    //EE->runFunction(func, noargs);
    //Blocks[block_index].func_ptr = reinterpret_cast<HostFunction>(EE->getPointerToFunction(func));
    Blocks[block_index].func_ptr = (void *)(EE->getPointerToFunction(func));
    //Blocks[block_index].func_ptr = reinterpret_cast<decltype(HostFunction())>(EE->getPointerToNamedFunction(f_name.str()));
    //(Blocks[block_index].func_ptr)(); 
    block_index++;
    //cout << "BlockIndex " << block_index << endl;
  }
  total_blocks = block_index;
  MyModule->dump();
/*
  cout << "calling add32" << endl;
  void (*add32)(int32_t, int32_t, int32_t) = 
    reinterpret_cast<void (*)(int32_t, int32_t, int32_t)>(EE->getFunctionAddress("add32")); 
  add32(0, 2, 3);
*/
/*
  void (*func0)() = 
    reinterpret_cast<void (*)()>(EE->getFunctionAddress("func1")); 
  func0();
*/
/*
  struct timeval tp;
  gettimeofday(&tp, NULL);
  long int start = tp.tv_sec * 1000 + tp.tv_usec / 1000;
  for (int32_t i = 0; i < 100; i++) {
    for (int32_t j = 0 ; j < total_blocks; j++) {
      ((HostFunction)(Blocks[j].func_ptr))();
    }
  }
  gettimeofday(&tp, NULL);
  long int end = tp.tv_sec * 1000 + tp.tv_usec / 1000;
  cout << "Time = " << end - start << endl; 
*/
}
Exemple #9
0
void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
	struct BBInfo
	{
		BasicBlock& bblock;
		std::vector<BBInfo*> predecessors;
		size_t inputItems;
		size_t outputItems;
		std::vector<llvm::PHINode*> phisToRewrite;

		BBInfo(BasicBlock& _bblock) :
			bblock(_bblock),
			predecessors(),
			inputItems(0),
			outputItems(0)
		{
			auto& initialStack = bblock.m_initialStack;
			for (auto it = initialStack.begin();
				 it != initialStack.end() && *it != nullptr;
				 ++it, ++inputItems);

			//if (bblock.localStack().m_tosOffset > 0)
			//	outputItems = bblock.localStack().m_tosOffset;
			auto& exitStack = bblock.m_currentStack;
			for (auto it = exitStack.rbegin();
				 it != exitStack.rend() && *it != nullptr;
				 ++it, ++outputItems);
		}
	};

	std::map<llvm::BasicBlock*, BBInfo> cfg;

	// Create nodes in cfg
	for (auto bb : basicBlocks)
		cfg.emplace(bb->llvm(), *bb);

	// Create edges in cfg: for each bb info fill the list
	// of predecessor infos.
	for (auto& pair : cfg)
	{
		auto bb = pair.first;
		auto& info = pair.second;

		for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
		{
			auto predInfoEntry = cfg.find(*predIt);
			if (predInfoEntry != cfg.end())
				info.predecessors.push_back(&predInfoEntry->second);
		}
	}

	// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
	bool valuesChanged = true;
	while (valuesChanged)
	{
		for (auto& pair : cfg)
		{
			DLOG(bb) << pair.second.bblock.llvm()->getName().str()
				<< ": in " << pair.second.inputItems
				<< ", out " << pair.second.outputItems
				<< "\n";
		}

		valuesChanged = false;
		for (auto& pair : cfg)
		{
			auto& info = pair.second;

			if (info.predecessors.empty())
				info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false

			for (auto predInfo : info.predecessors)
			{
				if (predInfo->outputItems < info.inputItems)
				{
					info.inputItems = predInfo->outputItems;
					valuesChanged = true;
				}
				else if (predInfo->outputItems > info.inputItems)
				{
					predInfo->outputItems = info.inputItems;
					valuesChanged = true;
				}
			}
		}
	}

	// Propagate values between blocks.
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
		auto phiIter = bblock.m_initialStack.begin();
		for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
		{
			assert(llvm::isa<llvm::PHINode>(*phiIter));
			auto phi = llvm::cast<llvm::PHINode>(*phiIter);

			for (auto predIt : info.predecessors)
			{
				auto& predExitStack = predIt->bblock.m_currentStack;
				auto value = *(predExitStack.end() - 1 - index);
				phi->addIncoming(value, predIt->bblock.llvm());
			}

			// Move phi to the front
			if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
			{
				phi->removeFromParent();
				_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
				_builder.Insert(phi);
			}
		}

		// The items pulled directly from predecessors block must be removed
		// from the list of items that has to be popped from the initial stack.
		auto& initialStack = bblock.m_initialStack;
		initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
		// Initial stack shrinks, so the size difference grows:
		bblock.m_tosOffset += (int)info.inputItems;
	}

	// We must account for the items that were pushed directly to successor
	// blocks and thus should not be on the list of items to be pushed onto
	// to EVM stack
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		auto& exitStack = bblock.m_currentStack;
		exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
		bblock.m_tosOffset -= (int)info.outputItems; // FIXME: Fix types
	}
}