mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 19:30:44 +00:00
Stack interface and implementation
This commit is contained in:
parent
bbc3aa4f99
commit
e8ff67cb48
3 changed files with 143 additions and 24 deletions
|
|
@ -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
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 Stack = std::vector<i256>;
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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
Normal file
26
evmcc/Stack.h
Normal file
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue