Browse Source

Basic arithmetic, limited precision for MUL, DIV and MOD.

cl-refactor
Paweł Bylica 10 years ago
parent
commit
58e03d5165
  1. 83
      evmcc/Compiler.cpp
  2. 1
      evmcc/bytecode/arithmetic_test.evm
  3. 1
      evmcc/bytecode/fib1.evm
  4. 29
      evmcc/lll/arithmetic_test.lll
  5. 57
      evmcc/lll/fib1.lll

83
evmcc/Compiler.cpp

@ -19,6 +19,7 @@ struct
llvm::Type* word256arr;
llvm::Type* size;
llvm::Type* Void;
llvm::Type* WordLowPrecision;
} Types;
Compiler::Compiler()
@ -31,6 +32,9 @@ Compiler::Compiler()
Types.word256arr = llvm::ArrayType::get(Types.word256, 100);
Types.size = llvm::Type::getInt64Ty(context);
Types.Void = llvm::Type::getVoidTy(context);
// TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required
Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64);
}
@ -59,6 +63,85 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto inst = static_cast<Instruction>(*pc);
switch (inst)
{
case Instruction::ADD:
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto result = builder.CreateAdd(lhs, rhs);
stack.push(result);
break;
}
case Instruction::SUB:
{
auto lhs = stack.pop();
auto rhs = stack.pop();
auto result = builder.CreateSub(lhs, rhs);
stack.push(result);
break;
}
case Instruction::MUL:
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision);
auto res128 = builder.CreateMul(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Types.word256);
stack.push(res256);
break;
}
case Instruction::DIV:
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision);
auto res128 = builder.CreateUDiv(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Types.word256);
stack.push(res256);
break;
}
case Instruction::SDIV:
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision);
auto res128 = builder.CreateSDiv(lhs128, rhs128);
auto res256 = builder.CreateSExt(res128, Types.word256);
stack.push(res256);
break;
}
case Instruction::MOD:
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision);
auto res128 = builder.CreateURem(lhs128, rhs128);
auto res256 = builder.CreateZExt(res128, Types.word256);
stack.push(res256);
break;
}
case Instruction::SMOD:
{
auto lhs256 = stack.pop();
auto rhs256 = stack.pop();
auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision);
auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision);
auto res128 = builder.CreateSRem(lhs128, rhs128);
auto res256 = builder.CreateSExt(res128, Types.word256);
stack.push(res256);
break;
}
case Instruction::POP:
{
stack.pop();

1
evmcc/bytecode/arithmetic_test.evm

@ -0,0 +1 @@
60016001900160070260050160029004600490066021900560150160030260059007600303

1
evmcc/bytecode/fib1.evm

@ -0,0 +1 @@
60016001818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101

29
evmcc/lll/arithmetic_test.lll

@ -0,0 +1,29 @@
(asm
1
1
SWAP1
ADD ;; 2
7
MUL ;; 14
5
ADD ;; 19
2
SWAP1
DIV ;; 9
4
SWAP1
MOD ;; 1
33
SWAP1
SDIV;; 0
21
ADD ;; 21
3
MUL ;; 63
5
SWAP1
SMOD;; 3
3
SUB ;; 0
)

57
evmcc/lll/fib1.lll

@ -0,0 +1,57 @@
;; Fibbonacci unrolled
(asm
1
1
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
DUP2
DUP2
ADD
)
Loading…
Cancel
Save