Browse Source

Introducing BasicBlock class.

It is a wrapper for llvm::BasicBlock to provide additional information needed by EVM compiler. For now the order of basic blocks might not match bytecode.
[#80113672]
cl-refactor
Paweł Bylica 10 years ago
parent
commit
5bf462e03d
  1. 13
      evmcc/BasicBlock.cpp
  2. 22
      evmcc/BasicBlock.h
  3. 39
      evmcc/Compiler.cpp
  4. 13
      evmcc/Compiler.h
  5. 2
      windows/evmcc.vcxproj
  6. 2
      windows/evmcc.vcxproj.filters

13
evmcc/BasicBlock.cpp

@ -0,0 +1,13 @@
#include "BasicBlock.h"
#include <llvm/IR/Function.h>
namespace evmcc
{
BasicBlock::BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc)
: m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_instIdx)}, _mainFunc))
{}
}

22
evmcc/BasicBlock.h

@ -0,0 +1,22 @@
#include <llvm/IR/BasicBlock.h>
namespace evmcc
{
using ProgramCounter = uint64_t;
class BasicBlock
{
public:
explicit BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc);
BasicBlock(const BasicBlock&) = delete;
void operator=(const BasicBlock&) = delete;
operator llvm::BasicBlock*() { return m_llvmBB; }
private:
llvm::BasicBlock* m_llvmBB;
};
}

39
evmcc/Compiler.cpp

@ -39,23 +39,15 @@ Compiler::Compiler()
Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64);
} }
llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) BasicBlock& Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc)
{ {
llvm::BasicBlock* block = nullptr;
auto blockIter = basicBlocks.find(pc); auto blockIter = basicBlocks.find(pc);
if (blockIter == basicBlocks.cend()) if (blockIter == basicBlocks.end())
{ {
// Create a basic block at targetPC. // Create a basic block at target pc directly in collection
std::ostringstream oss; blockIter = basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(pc), std::forward_as_tuple(pc, m_mainFunc)).first;
oss << "instr." << pc;
block = llvm::BasicBlock::Create(llvm::getGlobalContext(), oss.str());
basicBlocks[pc] = block;
} }
else return blockIter->second;
{
block = blockIter->second;
}
return block;
} }
void Compiler::createBasicBlocks(const dev::bytes& bytecode) void Compiler::createBasicBlocks(const dev::bytes& bytecode)
@ -122,7 +114,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
// 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); auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC);
ProgramCounter jumpPC = (next - bytecode.cbegin()); ProgramCounter jumpPC = (next - bytecode.cbegin());
jumpTargets[jumpPC] = targetBlock; jumpTargets[jumpPC] = targetBlock;
@ -177,13 +169,12 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
// Create main function // Create main function
const auto i32Ty = builder.getInt32Ty(); const auto i32Ty = builder.getInt32Ty();
Type* retTypeElems[] = {i32Ty, i32Ty}; //Type* retTypeElems[] = {i32Ty, i32Ty};
auto retType = StructType::create(retTypeElems, "MemRef", true); //auto retType = StructType::create(retTypeElems, "MemRef", true);
auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false); m_mainFunc = Function::Create(FunctionType::get(builder.getInt64Ty(), false), Function::ExternalLinkage, "main", module.get());
auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get());
// Create the basic blocks. // Create the basic blocks.
auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc);
builder.SetInsertPoint(entryBlock); builder.SetInsertPoint(entryBlock);
createBasicBlocks(bytecode); createBasicBlocks(bytecode);
@ -192,7 +183,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto memory = Memory(builder, module.get()); auto memory = Memory(builder, module.get());
auto ext = Ext(builder, module.get()); auto ext = Ext(builder, module.get());
BasicBlock* currentBlock = entryBlock; llvm::BasicBlock* currentBlock = entryBlock;
BBStack stack(extStack); // Stack for current block BBStack stack(extStack); // Stack for current block
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
@ -204,12 +195,11 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto blockIter = basicBlocks.find(currentPC); auto blockIter = basicBlocks.find(currentPC);
if (blockIter != basicBlocks.end()) if (blockIter != basicBlocks.end())
{ {
auto nextBlock = blockIter->second; auto& nextBlock = blockIter->second;
// Terminate the current block by jumping to the next one. // Terminate the current block by jumping to the next one.
if (currentBlock != nullptr) if (currentBlock != nullptr)
builder.CreateBr(nextBlock); builder.CreateBr(nextBlock);
// Insert the next block into the main function. // Insert the next block into the main function.
mainFunc->getBasicBlockList().push_back(nextBlock);
builder.SetInsertPoint(nextBlock); builder.SetInsertPoint(nextBlock);
currentBlock = nextBlock; currentBlock = nextBlock;
assert(stack.empty()); // Stack should be empty assert(stack.empty()); // Stack should be empty
@ -601,7 +591,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto cond = builder.CreateICmpNE(top, zero, "nonzero");
stack.reset(); stack.reset();
auto targetBlock = jumpTargets[currentPC]; auto targetBlock = jumpTargets[currentPC];
auto followBlock = basicBlocks[currentPC + 1]; auto& followBlock = basicBlocks.find(currentPC + 1)->second;
builder.CreateCondBr(cond, targetBlock, followBlock); builder.CreateCondBr(cond, targetBlock, followBlock);
currentBlock = nullptr; currentBlock = nullptr;
@ -792,12 +782,11 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto finalPC = bytecode.size(); auto finalPC = bytecode.size();
auto it = basicBlocks.find(finalPC); auto it = basicBlocks.find(finalPC);
assert(it != basicBlocks.end()); assert(it != basicBlocks.end());
auto finalBlock = it->second; auto& finalBlock = it->second;
if (currentBlock != nullptr) if (currentBlock != nullptr)
builder.CreateBr(finalBlock); builder.CreateBr(finalBlock);
mainFunc->getBasicBlockList().push_back(finalBlock);
builder.SetInsertPoint(finalBlock); builder.SetInsertPoint(finalBlock);
builder.CreateRet(builder.getInt64(0)); builder.CreateRet(builder.getInt64(0));

13
evmcc/Compiler.h

@ -5,6 +5,8 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include "BasicBlock.h"
namespace evmcc namespace evmcc
{ {
@ -20,18 +22,25 @@ public:
private: private:
llvm::BasicBlock* getOrCreateBasicBlockAtPC(ProgramCounter pc); BasicBlock& getOrCreateBasicBlockAtPC(ProgramCounter pc);
void createBasicBlocks(const dev::bytes& bytecode); void createBasicBlocks(const dev::bytes& bytecode);
/** /**
* Maps a program counter pc to a basic block which starts at pc (if any). * Maps a program counter pc to a basic block which starts at pc (if any).
*/ */
std::map<ProgramCounter, llvm::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 block of the jump.
*/ */
std::map<ProgramCounter, llvm::BasicBlock*> jumpTargets; std::map<ProgramCounter, llvm::BasicBlock*> jumpTargets;
private:
/// Collection of basic blocks in program
//std::vector<BasicBlock> m_basicBlocks;
/// Main program function
llvm::Function* m_mainFunc;
}; };
} }

2
windows/evmcc.vcxproj

@ -19,6 +19,7 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\evmcc\BasicBlock.cpp" />
<ClCompile Include="..\evmcc\Compiler.cpp" /> <ClCompile Include="..\evmcc\Compiler.cpp" />
<ClCompile Include="..\evmcc\evmcc.cpp" /> <ClCompile Include="..\evmcc\evmcc.cpp" />
<ClCompile Include="..\evmcc\ExecutionEngine.cpp" /> <ClCompile Include="..\evmcc\ExecutionEngine.cpp" />
@ -29,6 +30,7 @@
<ClCompile Include="..\evmcc\Utils.cpp" /> <ClCompile Include="..\evmcc\Utils.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\evmcc\BasicBlock.h" />
<ClInclude Include="..\evmcc\Compiler.h" /> <ClInclude Include="..\evmcc\Compiler.h" />
<ClInclude Include="..\evmcc\ExecutionEngine.h" /> <ClInclude Include="..\evmcc\ExecutionEngine.h" />
<ClInclude Include="..\evmcc\Ext.h" /> <ClInclude Include="..\evmcc\Ext.h" />

2
windows/evmcc.vcxproj.filters

@ -9,6 +9,7 @@
<ClCompile Include="..\evmcc\Memory.cpp" /> <ClCompile Include="..\evmcc\Memory.cpp" />
<ClCompile Include="..\evmcc\Utils.cpp" /> <ClCompile Include="..\evmcc\Utils.cpp" />
<ClCompile Include="..\evmcc\Runtime.cpp" /> <ClCompile Include="..\evmcc\Runtime.cpp" />
<ClCompile Include="..\evmcc\BasicBlock.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\evmcc\Compiler.h" /> <ClInclude Include="..\evmcc\Compiler.h" />
@ -18,5 +19,6 @@
<ClInclude Include="..\evmcc\Memory.h" /> <ClInclude Include="..\evmcc\Memory.h" />
<ClInclude Include="..\evmcc\Utils.h" /> <ClInclude Include="..\evmcc\Utils.h" />
<ClInclude Include="..\evmcc\Runtime.h" /> <ClInclude Include="..\evmcc\Runtime.h" />
<ClInclude Include="..\evmcc\BasicBlock.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>
Loading…
Cancel
Save