Browse Source

Provide end instruction to basic block

cl-refactor
Paweł Bylica 11 years ago
parent
commit
b273b863b1
  1. 3
      evmcc/BasicBlock.cpp
  2. 5
      evmcc/BasicBlock.h
  3. 41
      evmcc/Compiler.cpp
  4. 7
      evmcc/Compiler.h
  5. 1
      evmcc/Stack.h

3
evmcc/BasicBlock.cpp

@ -8,8 +8,9 @@ namespace evmcc
const char* BasicBlock::NamePrefix = "Instr."; const char* BasicBlock::NamePrefix = "Instr.";
BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc): BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) :
m_beginInstIdx(_beginInstIdx), m_beginInstIdx(_beginInstIdx),
m_endInstIdx(_endInstIdx),
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)) m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc))
{} {}

5
evmcc/BasicBlock.h

@ -15,7 +15,7 @@ public:
static const char* NamePrefix; static const char* NamePrefix;
explicit BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc); explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc);
BasicBlock(const BasicBlock&) = delete; BasicBlock(const BasicBlock&) = delete;
void operator=(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete;
@ -25,8 +25,11 @@ public:
State& getState() { return m_state; } State& getState() { return m_state; }
void setEnd(ProgramCounter _endInstIdx) { m_endInstIdx = _endInstIdx; }
private: private:
ProgramCounter m_beginInstIdx; ProgramCounter m_beginInstIdx;
ProgramCounter m_endInstIdx;
llvm::BasicBlock* m_llvmBB; llvm::BasicBlock* m_llvmBB;
/// Basic black state vector - current/end values and their positions /// Basic black state vector - current/end values and their positions

41
evmcc/Compiler.cpp

@ -40,20 +40,10 @@ Compiler::Compiler()
Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64);
} }
BasicBlock& Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc)
{
auto blockIter = basicBlocks.find(pc);
if (blockIter == basicBlocks.end())
{
// Create a basic block at target pc directly in collection
blockIter = basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(pc), std::forward_as_tuple(pc, m_mainFunc)).first;
}
return blockIter->second;
}
void Compiler::createBasicBlocks(const dev::bytes& bytecode) void Compiler::createBasicBlocks(const dev::bytes& bytecode)
{ {
getOrCreateBasicBlockAtPC(0); // First basic block std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indecies where basic blocks start/end
splitPoints.insert(0); // First basic block
for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr)
{ {
@ -116,15 +106,15 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
if (next + 1 < bytecode.cend()) if (next + 1 < bytecode.cend())
{ {
ProgramCounter nextPC = (next + 1 - bytecode.cbegin()); ProgramCounter nextPC = (next + 1 - bytecode.cbegin());
getOrCreateBasicBlockAtPC(nextPC); splitPoints.insert(nextPC);
} }
// Create a block for the JUMP target. // Create a block for the JUMP target.
ProgramCounter targetPC = val.convert_to<ProgramCounter>(); ProgramCounter targetPC = val.convert_to<ProgramCounter>();
auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC); splitPoints.insert(targetPC);
ProgramCounter jumpPC = (next - bytecode.cbegin()); ProgramCounter jumpPC = (next - bytecode.cbegin());
jumpTargets[jumpPC] = targetBlock; jumpTargets[jumpPC] = targetPC;
curr += 1; // skip over JUMP curr += 1; // skip over JUMP
} }
@ -148,7 +138,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
if (curr + 1 < bytecode.cend()) if (curr + 1 < bytecode.cend())
{ {
ProgramCounter nextPC = (curr + 1 - bytecode.cbegin()); ProgramCounter nextPC = (curr + 1 - bytecode.cbegin());
getOrCreateBasicBlockAtPC(nextPC); splitPoints.insert(nextPC);
} }
break; break;
} }
@ -158,7 +148,14 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
} }
} }
getOrCreateBasicBlockAtPC(bytecode.size()); // Final basic block splitPoints.insert(bytecode.size()); // For final block
for (auto it = splitPoints.cbegin(); it != splitPoints.cend();)
{
auto beginInstIdx = *it;
++it;
auto endInstIdx = it != splitPoints.cend() ? *it : beginInstIdx; // For final block
basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc));
}
} }
std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode) std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
@ -572,7 +569,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
// just pop it without looking... // just pop it without looking...
stack.pop(); stack.pop();
auto targetBlock = jumpTargets[currentPC]; auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second;
builder.CreateBr(targetBlock); builder.CreateBr(targetBlock);
currentBlock = nullptr; currentBlock = nullptr;
@ -590,7 +587,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto top = stack.pop(); auto top = stack.pop();
auto zero = ConstantInt::get(Types.word256, 0); auto zero = ConstantInt::get(Types.word256, 0);
auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto cond = builder.CreateICmpNE(top, zero, "nonzero");
auto targetBlock = jumpTargets[currentPC]; auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second;
auto& followBlock = basicBlocks.find(currentPC + 1)->second; auto& followBlock = basicBlocks.find(currentPC + 1)->second;
builder.CreateCondBr(cond, targetBlock, followBlock); builder.CreateCondBr(cond, targetBlock, followBlock);
@ -743,12 +740,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto index = stack.pop(); auto index = stack.pop();
auto size = stack.pop(); auto size = stack.pop();
// MCJIT does not support returning structs
//auto index32 = builder.CreateTrunc(index, i32Ty, "index32");
//auto size32 = builder.CreateTrunc(size, i32Ty, "size32");
//auto ret = builder.CreateInsertValue(UndefValue::get(retType), index32, 0, "ret");
//ret = builder.CreateInsertValue(ret, size32, 1, "ret");
auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); auto ret = builder.CreateTrunc(index, builder.getInt64Ty());
ret = builder.CreateShl(ret, 32); ret = builder.CreateShl(ret, 32);
size = builder.CreateTrunc(size, i32Ty); size = builder.CreateTrunc(size, i32Ty);

7
evmcc/Compiler.h

@ -22,7 +22,6 @@ public:
private: private:
BasicBlock& getOrCreateBasicBlockAtPC(ProgramCounter pc);
void createBasicBlocks(const dev::bytes& bytecode); void createBasicBlocks(const dev::bytes& bytecode);
void linkBasicBlocks(); void linkBasicBlocks();
@ -33,16 +32,16 @@ private:
std::map<ProgramCounter, BasicBlock> basicBlocks; std::map<ProgramCounter, BasicBlock> basicBlocks;
/** /**
* Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. * Maps a pc at which there is a JUMP or JUMPI to the target pc of the jump.
*/ */
std::map<ProgramCounter, llvm::BasicBlock*> jumpTargets; std::map<ProgramCounter, ProgramCounter> jumpTargets;
private: private:
/// Collection of basic blocks in program /// Collection of basic blocks in program
//std::vector<BasicBlock> m_basicBlocks; //std::vector<BasicBlock> m_basicBlocks;
/// Main program function /// Main program function
llvm::Function* m_mainFunc; llvm::Function* m_mainFunc = nullptr;
}; };
} }

1
evmcc/Stack.h

@ -11,6 +11,7 @@ class BasicBlock;
Stack adapter for Basic Block Stack adapter for Basic Block
Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block. Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block.
TODO: Integrate into BasicBlock class
*/ */
class BBStack class BBStack
{ {

Loading…
Cancel
Save