Browse Source

Placing IRBuilder in Compiler class (for future refactoring)

cl-refactor
Paweł Bylica 10 years ago
parent
commit
08c7dcc3d2
  1. 177
      evmcc/Compiler.cpp
  2. 4
      evmcc/Compiler.h

177
evmcc/Compiler.cpp

@ -3,7 +3,7 @@
#include <boost/dynamic_bitset.hpp>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/CFG.h>
#include <llvm/ADT/PostOrderIterator.h>
#include <llvm/IR/IntrinsicInst.h>
@ -23,10 +23,10 @@ namespace eth
namespace jit
{
Compiler::Compiler()
: m_badJumpBlock(nullptr)
Compiler::Compiler():
m_builder(llvm::getGlobalContext())
{
Type::init(llvm::getGlobalContext());
Type::init(m_builder.getContext());
}
void Compiler::createBasicBlocks(const bytes& bytecode)
@ -151,31 +151,29 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto& context = llvm::getGlobalContext();
auto module = std::make_unique<llvm::Module>("main", context);
llvm::IRBuilder<> builder(context);
auto module = std::make_unique<llvm::Module>("main", m_builder.getContext());
// Create main function
m_mainFunc = llvm::Function::Create(llvm::FunctionType::get(Type::MainReturn, false), llvm::Function::ExternalLinkage, "main", module.get());
// Create the basic blocks.
auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc);
builder.SetInsertPoint(entryBlock);
auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc);
m_builder.SetInsertPoint(entryBlock);
createBasicBlocks(bytecode);
// Init runtime structures.
GasMeter gasMeter(builder, module.get());
Memory memory(builder, module.get(), gasMeter);
Ext ext(builder, module.get());
GasMeter gasMeter(m_builder, module.get());
Memory memory(m_builder, module.get(), gasMeter);
Ext ext(m_builder, module.get());
builder.CreateBr(basicBlocks.begin()->second);
m_builder.CreateBr(basicBlocks.begin()->second);
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
{
auto& basicBlock = basicBlockPairIt->second;
auto& stack = basicBlock.getStack();
builder.SetInsertPoint(basicBlock);
m_builder.SetInsertPoint(basicBlock);
for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC)
{
@ -190,7 +188,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto result = builder.CreateAdd(lhs, rhs);
auto result = m_builder.CreateAdd(lhs, rhs);
stack.push(result);
break;
}
@ -199,7 +197,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto result = builder.CreateSub(lhs, rhs);
auto result = m_builder.CreateSub(lhs, rhs);
stack.push(result);
break;
}
@ -208,10 +206,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = builder.CreateMul(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Type::i256);
auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = m_builder.CreateMul(lhs128, rhs128);
auto res256 = m_builder.CreateZExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -220,10 +218,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = builder.CreateUDiv(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Type::i256);
auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = m_builder.CreateUDiv(lhs128, rhs128);
auto res256 = m_builder.CreateZExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -232,10 +230,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = builder.CreateSDiv(lhs128, rhs128);
auto res256 = builder.CreateSExt(res128, Type::i256);
auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = m_builder.CreateSDiv(lhs128, rhs128);
auto res256 = m_builder.CreateSExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -244,10 +242,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = builder.CreateURem(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Type::i256);
auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = m_builder.CreateURem(lhs128, rhs128);
auto res256 = m_builder.CreateZExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -256,10 +254,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = builder.CreateSRem(lhs128, rhs128);
auto res256 = builder.CreateSExt(res128, Type::i256);
auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision);
auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision);
auto res128 = m_builder.CreateSRem(lhs128, rhs128);
auto res256 = m_builder.CreateSExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -277,7 +275,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto top = stack.pop();
auto zero = Constant::get(0);
auto res = builder.CreateSub(zero, top);
auto res = m_builder.CreateSub(zero, top);
stack.push(res);
break;
}
@ -286,8 +284,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res1 = builder.CreateICmpULT(lhs, rhs);
auto res256 = builder.CreateZExt(res1, Type::i256);
auto res1 = m_builder.CreateICmpULT(lhs, rhs);
auto res256 = m_builder.CreateZExt(res1, Type::i256);
stack.push(res256);
break;
}
@ -296,8 +294,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res1 = builder.CreateICmpUGT(lhs, rhs);
auto res256 = builder.CreateZExt(res1, Type::i256);
auto res1 = m_builder.CreateICmpUGT(lhs, rhs);
auto res256 = m_builder.CreateZExt(res1, Type::i256);
stack.push(res256);
break;
}
@ -306,8 +304,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res1 = builder.CreateICmpSLT(lhs, rhs);
auto res256 = builder.CreateZExt(res1, Type::i256);
auto res1 = m_builder.CreateICmpSLT(lhs, rhs);
auto res256 = m_builder.CreateZExt(res1, Type::i256);
stack.push(res256);
break;
}
@ -316,8 +314,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res1 = builder.CreateICmpSGT(lhs, rhs);
auto res256 = builder.CreateZExt(res1, Type::i256);
auto res1 = m_builder.CreateICmpSGT(lhs, rhs);
auto res256 = m_builder.CreateZExt(res1, Type::i256);
stack.push(res256);
break;
}
@ -326,8 +324,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res1 = builder.CreateICmpEQ(lhs, rhs);
auto res256 = builder.CreateZExt(res1, Type::i256);
auto res1 = m_builder.CreateICmpEQ(lhs, rhs);
auto res256 = m_builder.CreateZExt(res1, Type::i256);
stack.push(res256);
break;
}
@ -335,9 +333,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
case Instruction::NOT:
{
auto top = stack.pop();
auto zero = Constant::get(0);
auto iszero = builder.CreateICmpEQ(top, zero, "iszero");
auto result = builder.CreateZExt(iszero, Type::i256);
auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero");
auto result = m_builder.CreateZExt(iszero, Type::i256);
stack.push(result);
break;
}
@ -346,7 +343,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res = builder.CreateAnd(lhs, rhs);
auto res = m_builder.CreateAnd(lhs, rhs);
stack.push(res);
break;
}
@ -355,7 +352,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res = builder.CreateOr(lhs, rhs);
auto res = m_builder.CreateOr(lhs, rhs);
stack.push(res);
break;
}
@ -364,7 +361,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto res = builder.CreateXor(lhs, rhs);
auto res = m_builder.CreateXor(lhs, rhs);
stack.push(res);
break;
}
@ -386,12 +383,12 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
// TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439
auto shbits = builder.CreateShl(byteNum, Constant::get(3));
value = builder.CreateShl(value, shbits);
value = builder.CreateLShr(value, Constant::get(31 * 8));
auto shbits = m_builder.CreateShl(byteNum, Constant::get(3));
value = m_builder.CreateShl(value, shbits);
value = m_builder.CreateLShr(value, Constant::get(31 * 8));
auto byteNumValid = builder.CreateICmpULT(byteNum, Constant::get(32));
value = builder.CreateSelect(byteNumValid, value, Constant::get(0));
auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32));
value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0));
stack.push(value);
break;
@ -401,13 +398,13 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto val1 = stack.pop();
auto val2 = stack.pop();
auto sum = builder.CreateAdd(val1, val2);
auto sum = m_builder.CreateAdd(val1, val2);
auto mod = stack.pop();
auto sum128 = builder.CreateTrunc(sum, Type::lowPrecision);
auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision);
auto res128 = builder.CreateURem(sum128, mod128);
auto res256 = builder.CreateZExt(res128, Type::i256);
auto sum128 = m_builder.CreateTrunc(sum, Type::lowPrecision);
auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision);
auto res128 = m_builder.CreateURem(sum128, mod128);
auto res256 = m_builder.CreateZExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -416,13 +413,13 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
{
auto val1 = stack.pop();
auto val2 = stack.pop();
auto prod = builder.CreateMul(val1, val2);
auto prod = m_builder.CreateMul(val1, val2);
auto mod = stack.pop();
auto prod128 = builder.CreateTrunc(prod, Type::lowPrecision);
auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision);
auto res128 = builder.CreateURem(prod128, mod128);
auto res256 = builder.CreateZExt(res128, Type::i256);
auto prod128 = m_builder.CreateTrunc(prod, Type::lowPrecision);
auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision);
auto res128 = m_builder.CreateURem(prod128, mod128);
auto res256 = m_builder.CreateZExt(res128, Type::i256);
stack.push(res256);
break;
}
@ -452,7 +449,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
value <<= 8;
value |= bytecode[currentPC];
}
auto c = builder.getInt(value);
auto c = m_builder.getInt(value);
stack.push(c);
break;
}
@ -543,13 +540,13 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
// The target address is computed at compile time,
// just pop it without looking...
stack.pop();
builder.CreateBr(targetBlock->llvm());
m_builder.CreateBr(targetBlock->llvm());
}
else
{
// FIXME: this get(0) is a temporary workaround to get some of the jump tests running.
stack.get(0);
builder.CreateBr(m_jumpTableBlock->llvm());
m_builder.CreateBr(m_jumpTableBlock->llvm());
}
}
else // JUMPI
@ -557,7 +554,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
stack.swap(1);
auto val = stack.pop();
auto zero = Constant::get(0);
auto cond = builder.CreateICmpNE(val, zero, "nonzero");
auto cond = m_builder.CreateICmpNE(val, zero, "nonzero");
// Assume the basic blocks are properly ordered:
auto nextBBIter = basicBlockPairIt;
@ -568,11 +565,11 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
if (targetBlock)
{
stack.pop();
builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm());
m_builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm());
}
else
{
builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm());
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm());
}
}
@ -780,10 +777,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
gasMeter.commitCostBlock(gas);
// Require memory for the max of in and out buffers
auto inSizeReq = builder.CreateAdd(inOff, inSize, "inSizeReq");
auto outSizeReq = builder.CreateAdd(outOff, outSize, "outSizeReq");
auto cmp = builder.CreateICmpUGT(inSizeReq, outSizeReq);
auto sizeReq = builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq");
auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq");
auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq");
auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq);
auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq");
memory.require(sizeReq);
auto receiveAddress = codeAddress;
@ -803,7 +800,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
memory.registerReturnData(index, size);
builder.CreateRet(Constant::get(ReturnCode::Return));
m_builder.CreateRet(Constant::get(ReturnCode::Return));
break;
}
@ -815,7 +812,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
}
case Instruction::STOP:
{
builder.CreateRet(Constant::get(ReturnCode::Stop));
m_builder.CreateRet(Constant::get(ReturnCode::Stop));
break;
}
@ -824,12 +821,12 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
gasMeter.commitCostBlock();
if (!builder.GetInsertBlock()->getTerminator()) // If block not terminated
if (!m_builder.GetInsertBlock()->getTerminator()) // If block not terminated
{
if (basicBlock.end() == bytecode.size())
{
// Return STOP code
builder.CreateRet(Constant::get(ReturnCode::Stop));
m_builder.CreateRet(Constant::get(ReturnCode::Stop));
}
else
{
@ -837,7 +834,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
auto iterCopy = basicBlockPairIt;
++iterCopy;
auto& next = iterCopy->second;
builder.CreateBr(next);
m_builder.CreateBr(next);
}
}
}
@ -846,19 +843,19 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
// TODO: move to separate function.
// Note: Right now the codegen for special blocks depends only on createBasicBlock(),
// not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks().
builder.SetInsertPoint(m_stopBB);
builder.CreateRet(Constant::get(ReturnCode::Stop));
m_builder.SetInsertPoint(m_stopBB);
m_builder.CreateRet(Constant::get(ReturnCode::Stop));
builder.SetInsertPoint(m_badJumpBlock->llvm());
builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
builder.SetInsertPoint(m_jumpTableBlock->llvm());
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
if (m_indirectJumpTargets.size() > 0)
{
auto& stack = m_jumpTableBlock->getStack();
auto dest = stack.pop();
auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(),
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(),
m_indirectJumpTargets.size());
for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it)
{
@ -869,7 +866,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
}
else
{
builder.CreateBr(m_badJumpBlock->llvm());
m_builder.CreateBr(m_badJumpBlock->llvm());
}
linkBasicBlocks();

4
evmcc/Compiler.h

@ -1,7 +1,7 @@
#pragma once
#include <llvm/IR/Module.h>
#include <llvm/IR/IRBuilder.h>
#include <libdevcore/Common.h>
@ -30,6 +30,8 @@ private:
void linkBasicBlocks();
llvm::IRBuilder<> m_builder;
/**
* Maps a program counter pc to a basic block that starts at pc (if any).
*/

Loading…
Cancel
Save