Browse Source

Stack interface and implementation

cl-refactor
Paweł Bylica 10 years ago
parent
commit
26a952cd1d
  1. 23
      evmcc/Compiler.cpp
  2. 118
      evmcc/Stack.cpp
  3. 26
      evmcc/Stack.h
  4. 1
      windows/evmcc.vcxproj
  5. 1
      windows/evmcc.vcxproj.filters

23
evmcc/Compiler.cpp

@ -3,6 +3,8 @@
#include <llvm/IR/IRBuilder.h>
#include "Stack.h"
namespace evmcc
{
@ -49,7 +51,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto stack2 = new GlobalVariable(*module, Types.word256arr, false,
GlobalValue::LinkageTypes::PrivateLinkage,
ConstantAggregateZero::get(Types.word256arr), "stack");
auto stackTop = new GlobalVariable(*module, Types.size, false,
auto stackTop2 = new GlobalVariable(*module, Types.size, false,
GlobalValue::LinkageTypes::PrivateLinkage,
ConstantInt::get(Types.size, 0), "stackTop");
@ -57,13 +59,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false),
GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get());
// Create stack_create declaration
auto stackCreate = Function::Create(FunctionType::get(Types.word8ptr, false),
GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", module.get());
auto stackPush = Function::Create(FunctionType::get(Types.Void, std::vector<Type*>{ Types.word8ptr, Types.word256 }, false),
GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", module.get());
// Create main function
FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false);
Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get());
@ -77,14 +72,20 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
builder.CreateStore(mallocMemCall, memory);
builder.CreateStore(ConstantInt::get(Types.size, 100), memSize);
auto stack = builder.CreateCall(stackCreate, "stack");
auto stack = Stack(builder, module.get());
uint64_t words[] = { 1, 2, 3, 4 };
auto val = llvm::APInt(256, 4, words);
auto c = ConstantInt::get(Types.word256, val);
Value* args[] = { stack, c };
builder.CreateCall(stackPush, args);
stack.push(c);
stack.push(ConstantInt::get(Types.word256, 0x1122334455667788));
auto top = stack.top();
stack.push(top); // dup
stack.pop();
/*
std::vector<Value*> mallocStackArgs = { ConstantInt::get(sizeTy, 200) };

118
evmcc/Stack.cpp

@ -1,8 +1,13 @@
#include "Stack.h"
#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>
#include <llvm/IR/Function.h>
#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
@ -10,6 +15,9 @@
#define EXPORT
#endif
namespace evmcc
{
struct i256
{
uint64_t a;
@ -17,30 +25,114 @@ struct i256
uint64_t c;
uint64_t d;
};
static_assert(sizeof(i256) == 32, "Wrong i265 size");
using StackImpl = std::vector<i256>;
Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
: m_builder(_builder)
{
// TODO: Clean up LLVM types
auto stackPtrTy = m_builder.getInt8PtrTy();
auto i256Ty = m_builder.getIntNTy(256);
auto i256PtrTy = i256Ty->getPointerTo();
auto voidTy = m_builder.getVoidTy();
auto stackCreate = llvm::Function::Create(llvm::FunctionType::get(stackPtrTy, false),
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", _module);
llvm::Type* argsTypes[] = {stackPtrTy, i256PtrTy};
auto funcType = llvm::FunctionType::get(voidTy, argsTypes, false);
m_stackPush = llvm::Function::Create(funcType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module);
using Stack = std::vector<i256>;
m_stackTop = llvm::Function::Create(funcType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_top", _module);
m_stackPop = llvm::Function::Create(funcType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module);
m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr");
m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val");
}
void Stack::push(llvm::Value* _value)
{
m_builder.CreateStore(_value, m_args[1]); // copy value to memory
m_builder.CreateCall(m_stackPush, m_args);
}
llvm::Value* Stack::top()
{
m_builder.CreateCall(m_stackTop, m_args);
return m_builder.CreateLoad(m_args[1]);
}
llvm::Value* Stack::pop()
{
m_builder.CreateCall(m_stackPop, m_args);
return m_builder.CreateLoad(m_args[1]);
}
void debugStack(const char* op, const i256& word)
{
std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": "
<< std::dec << word.a
<< " HEX: " << std::hex << std::setfill('0');
if (word.b || word.c || word.d)
{
std::cerr << std::setw(16) << word.d << " "
<< std::setw(16) << word.c << " "
<< std::setw(16) << word.b << " ";
}
std::cerr << std::setw(16) << word.a << "\n";
}
}
extern "C"
{
using namespace evmcc;
EXPORT void* evmccrt_stack_create()
{
std::cerr << "STACK create: ";
auto stack = new Stack;
std::cerr << stack << "\n";
auto stack = new StackImpl;
std::cerr << "STACK create\n";
return stack;
}
EXPORT void evmccrt_stack_push(void* _stack, uint64_t _partA, uint64_t _partB, uint64_t _partC, uint64_t _partD)
EXPORT void evmccrt_stack_push(void* _stack, void* _pWord)
{
auto stack = static_cast<StackImpl*>(_stack);
auto word = static_cast<i256*>(_pWord);
debugStack("push", *word);
stack->push_back(*word);
}
EXPORT void evmccrt_stack_top(void* _stack, void* _pWord)
{
auto stack = static_cast<StackImpl*>(_stack);
assert(!stack->empty());
auto word = &stack->back();
debugStack("top", *word);
auto outWord = static_cast<i256*>(_pWord);
*outWord = *word;
}
EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord)
{
std::cerr << "STACK push: " << _partA << " (" << std::hex << std::setfill('0')
<< std::setw(16) << _partD << " "
<< std::setw(16) << _partC << " "
<< std::setw(16) << _partB << " "
<< std::setw(16) << _partA;
auto stack = static_cast<Stack*>(_stack);
stack->push_back({_partA, _partB, _partC, _partD});
std::cerr << ")\n";
auto stack = static_cast<StackImpl*>(_stack);
assert(!stack->empty());
auto word = &stack->back();
debugStack("pop", *word);
auto outWord = static_cast<i256*>(_pWord);
stack->pop_back();
*outWord = *word;
}
} // extern "C"

26
evmcc/Stack.h

@ -0,0 +1,26 @@
#pragma once
#include <llvm/IR/IRBuilder.h>
namespace evmcc
{
class Stack
{
public:
Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module);
void push(llvm::Value* _value);
llvm::Value* top();
llvm::Value* pop();
private:
llvm::IRBuilder<>& m_builder;
llvm::Value* m_args[2];
llvm::Function* m_stackPush;
llvm::Function* m_stackTop;
llvm::Function* m_stackPop;
};
}

1
windows/evmcc.vcxproj

@ -27,6 +27,7 @@
<ItemGroup>
<ClInclude Include="..\evmcc\Compiler.h" />
<ClInclude Include="..\evmcc\ExecutionEngine.h" />
<ClInclude Include="..\evmcc\Stack.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}</ProjectGuid>

1
windows/evmcc.vcxproj.filters

@ -9,5 +9,6 @@
<ItemGroup>
<ClInclude Include="..\evmcc\Compiler.h" />
<ClInclude Include="..\evmcc\ExecutionEngine.h" />
<ClInclude Include="..\evmcc\Stack.h" />
</ItemGroup>
</Project>
Loading…
Cancel
Save