@ -33,7 +33,9 @@ namespace jit
{
{
Compiler : : Compiler ( ) :
Compiler : : Compiler ( ) :
m_builder ( llvm : : getGlobalContext ( ) )
m_builder ( llvm : : getGlobalContext ( ) ) ,
m_jumpTableBlock ( ) ,
m_badJumpBlock ( )
{
{
Type : : init ( m_builder . getContext ( ) ) ;
Type : : init ( m_builder . getContext ( ) ) ;
}
}
@ -137,8 +139,8 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode)
}
}
m_stopBB = llvm : : BasicBlock : : Create ( m_mainFunc - > getContext ( ) , " Stop " , m_mainFunc ) ;
m_stopBB = llvm : : BasicBlock : : Create ( m_mainFunc - > getContext ( ) , " Stop " , m_mainFunc ) ;
m_badJumpBlock = std : : make_ unique< BasicBlock > ( " BadJumpBlock " , m_mainFunc , m_builder ) ;
m_badJumpBlock = std : : unique_ptr < BasicBlock > ( new BasicBlock ( " BadJumpBlock " , m_mainFunc , m_builder ) ) ;
m_jumpTableBlock = std : : make_ unique< BasicBlock > ( " JumpTableBlock " , m_mainFunc , m_builder ) ;
m_jumpTableBlock = std : : unique_ptr < BasicBlock > ( new BasicBlock ( " JumpTableBlock " , m_mainFunc , m_builder ) ) ;
for ( auto it = directJumpTargets . cbegin ( ) ; it ! = directJumpTargets . cend ( ) ; + + it )
for ( auto it = directJumpTargets . cbegin ( ) ; it ! = directJumpTargets . cend ( ) ; + + it )
{
{
@ -170,7 +172,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode)
std : : unique_ptr < llvm : : Module > Compiler : : compile ( bytesConstRef bytecode )
std : : unique_ptr < llvm : : Module > Compiler : : compile ( bytesConstRef bytecode )
{
{
auto module = std : : make_ unique< llvm : : Module > ( " main " , m_builder . getContext ( ) ) ;
auto module = std : : unique_ptr < llvm : : Module > ( new llvm : : Module ( " main " , m_builder . getContext ( ) ) ) ;
// Create main function
// Create main function
llvm : : Type * mainFuncArgTypes [ ] = { m_builder . getInt32Ty ( ) , Type : : RuntimePtr } ; // There must be int in first place because LLVM does not support other signatures
llvm : : Type * mainFuncArgTypes [ ] = { m_builder . getInt32Ty ( ) , Type : : RuntimePtr } ; // There must be int in first place because LLVM does not support other signatures
@ -372,14 +374,13 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
break ;
break ;
}
}
/*case Instruction::NEG:
case Instruction : : BNOT :
{
{
auto top = stack . pop ( ) ;
auto value = stack . pop ( ) ;
auto zero = Constant : : get ( 0 ) ;
auto ret = m_builder . CreateXor ( value , llvm : : APInt ( 256 , - 1 , true ) , " bnot " ) ;
auto res = m_builder . CreateSub ( zero , top ) ;
stack . push ( ret ) ;
stack . push ( res ) ;
break ;
break ;
} */
}
case Instruction : : LT :
case Instruction : : LT :
{
{
@ -505,6 +506,36 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
break ;
break ;
}
}
case Instruction : : SIGNEXTEND :
{
auto idx = stack . pop ( ) ;
auto word = stack . pop ( ) ;
auto k32_ = m_builder . CreateTrunc ( idx , m_builder . getIntNTy ( 5 ) , " k_32 " ) ;
auto k32 = m_builder . CreateZExt ( k32_ , Type : : i256 ) ;
auto k32x8 = m_builder . CreateMul ( k32 , Constant : : get ( 8 ) , " kx8 " ) ;
// test for word >> (k * 8 + 7)
auto bitpos = m_builder . CreateAdd ( k32x8 , Constant : : get ( 7 ) , " bitpos " ) ;
auto bitval = m_builder . CreateLShr ( word , bitpos , " bitval " ) ;
auto bittest = m_builder . CreateTrunc ( bitval , m_builder . getInt1Ty ( ) , " bittest " ) ;
auto mask_ = m_builder . CreateShl ( Constant : : get ( 1 ) , bitpos ) ;
auto mask = m_builder . CreateSub ( mask_ , Constant : : get ( 1 ) , " mask " ) ;
auto negmask = m_builder . CreateXor ( mask , llvm : : ConstantInt : : getAllOnesValue ( Type : : i256 ) , " negmask " ) ;
auto val1 = m_builder . CreateOr ( word , negmask ) ;
auto val0 = m_builder . CreateAnd ( word , mask ) ;
auto kInRange = m_builder . CreateICmpULE ( idx , llvm : : ConstantInt : : get ( Type : : i256 , 30 ) ) ;
auto result = m_builder . CreateSelect ( kInRange ,
m_builder . CreateSelect ( bittest , val1 , val0 ) ,
word ) ;
stack . push ( result ) ;
break ;
}
case Instruction : : SHA3 :
case Instruction : : SHA3 :
{
{
auto inOff = stack . pop ( ) ;
auto inOff = stack . pop ( ) ;
@ -523,16 +554,15 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
case Instruction : : ANY_PUSH :
case Instruction : : ANY_PUSH :
{
{
auto numBytes = static_cast < size_t > ( inst ) - static_cast < size_t > ( Instruction : : PUSH1 ) + 1 ;
const auto numBytes = static_cast < size_t > ( inst ) - static_cast < size_t > ( Instruction : : PUSH1 ) + 1 ;
auto value = llvm : : APInt ( 256 , 0 ) ;
auto value = llvm : : APInt ( 256 , 0 ) ;
for ( decltype ( numBytes ) i = 0 ; i < numBytes ; + + i ) // TODO: Use pc as iterator
for ( auto lastPC = currentPC + numBytes ; currentPC < lastPC ; )
{
{
+ + currentPC ;
value < < = 8 ;
value < < = 8 ;
value | = bytecode [ currentPC ] ;
value | = bytecode [ + + currentPC ] ;
}
}
auto c = m_builder . getInt ( value ) ;
stack . push ( c ) ;
stack . push ( m_builder . getInt ( value ) ) ;
break ;
break ;
}
}
@ -610,10 +640,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
{
{
auto pairIter = m_directJumpTargets . find ( currentPC ) ;
auto pairIter = m_directJumpTargets . find ( currentPC ) ;
if ( pairIter ! = m_directJumpTargets . end ( ) )
if ( pairIter ! = m_directJumpTargets . end ( ) )
{
targetBlock = pairIter - > second ;
targetBlock = pairIter - > second ;
}
}
}
if ( inst = = Instruction : : JUMP )
if ( inst = = Instruction : : JUMP )
{
{
@ -625,10 +653,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
m_builder . CreateBr ( targetBlock ) ;
m_builder . CreateBr ( targetBlock ) ;
}
}
else
else
{
m_builder . CreateBr ( m_jumpTableBlock - > llvm ( ) ) ;
m_builder . CreateBr ( m_jumpTableBlock - > llvm ( ) ) ;
}
}
}
else // JUMPI
else // JUMPI
{
{
stack . swap ( 1 ) ;
stack . swap ( 1 ) ;
@ -636,8 +662,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
auto zero = Constant : : get ( 0 ) ;
auto zero = Constant : : get ( 0 ) ;
auto cond = m_builder . CreateICmpNE ( val , zero , " nonzero " ) ;
auto cond = m_builder . CreateICmpNE ( val , zero , " nonzero " ) ;
// Assume the basic blocks are properly ordered:
assert ( nextBasicBlock ) ; // FIXME: JUMPI can be last instruction
if ( ! nextBasicBlock ) // In case JUMPI is the last instruction
nextBasicBlock = m_stopBB ;
if ( targetBlock )
if ( targetBlock )
{
{
@ -645,10 +672,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
m_builder . CreateCondBr ( cond , targetBlock , nextBasicBlock ) ;
m_builder . CreateCondBr ( cond , targetBlock , nextBasicBlock ) ;
}
}
else
else
{
m_builder . CreateCondBr ( cond , m_jumpTableBlock - > llvm ( ) , nextBasicBlock ) ;
m_builder . CreateCondBr ( cond , m_jumpTableBlock - > llvm ( ) , nextBasicBlock ) ;
}
}
}
break ;
break ;
}
}