{-| Module : Assembler Description : Assembler for EVM opcodes used in the HEVM symbolic checker -} {-# LANGUAGE DataKinds #-} module EVM.Assembler where import EVM.Op import EVM.Types import qualified EVM.Expr as Expr import qualified Data.Vector as V import Data.Vector (Vector) assemble :: [Op] -> Vector (Expr Byte) assemble os = V.fromList $ concatMap go os where go :: Op -> [Expr Byte] go = \case OpStop -> [LitByte 0x00] OpAdd -> [LitByte 0x01] OpMul -> [LitByte 0x02] OpSub -> [LitByte 0x03] OpDiv -> [LitByte 0x04] OpSdiv -> [LitByte 0x05] OpMod -> [LitByte 0x06] OpSmod -> [LitByte 0x07] OpAddmod -> [LitByte 0x08] OpMulmod -> [LitByte 0x09] OpExp -> [LitByte 0x0A] OpSignextend -> [LitByte 0x0B] OpLt -> [LitByte 0x10] OpGt -> [LitByte 0x11] OpSlt -> [LitByte 0x12] OpSgt -> [LitByte 0x13] OpEq -> [LitByte 0x14] OpIszero -> [LitByte 0x15] OpAnd -> [LitByte 0x16] OpOr -> [LitByte 0x17] OpXor -> [LitByte 0x18] OpNot -> [LitByte 0x19] OpByte -> [LitByte 0x1A] OpShl -> [LitByte 0x1B] OpShr -> [LitByte 0x1C] OpSar -> [LitByte 0x1D] OpSha3 -> [LitByte 0x20] OpAddress -> [LitByte 0x30] OpBalance -> [LitByte 0x31] OpOrigin -> [LitByte 0x32] OpCaller -> [LitByte 0x33] OpCallvalue -> [LitByte 0x34] OpCalldataload -> [LitByte 0x35] OpCalldatasize -> [LitByte 0x36] OpCalldatacopy -> [LitByte 0x37] OpCodesize -> [LitByte 0x38] OpCodecopy -> [LitByte 0x39] OpGasprice -> [LitByte 0x3A] OpExtcodesize -> [LitByte 0x3B] OpExtcodecopy -> [LitByte 0x3C] OpReturndatasize -> [LitByte 0x3D] OpReturndatacopy -> [LitByte 0x3E] OpExtcodehash -> [LitByte 0x3F] OpBlockhash -> [LitByte 0x40] OpCoinbase -> [LitByte 0x41] OpTimestamp -> [LitByte 0x42] OpNumber -> [LitByte 0x43] OpPrevRandao -> [LitByte 0x44] OpGaslimit -> [LitByte 0x45] OpChainid -> [LitByte 0x46] OpSelfbalance -> [LitByte 0x47] OpBaseFee -> [LitByte 0x48] OpPop -> [LitByte 0x50] OpMload -> [LitByte 0x51] OpMstore -> [LitByte 0x52] OpMstore8 -> [LitByte 0x53] OpSload -> [LitByte 0x54] OpSstore -> [LitByte 0x55] OpJump -> [LitByte 0x56] OpJumpi -> [LitByte 0x57] OpPc -> [LitByte 0x58] OpMsize -> [LitByte 0x59] OpGas -> [LitByte 0x5A] OpJumpdest -> [LitByte 0x5B] OpCreate -> [LitByte 0xF0] OpCall -> [LitByte 0xF1] OpStaticcall -> [LitByte 0xFA] OpCallcode -> [LitByte 0xF2] OpReturn -> [LitByte 0xF3] OpDelegatecall -> [LitByte 0xF4] OpCreate2 -> [LitByte 0xF5] OpRevert -> [LitByte 0xFD] OpSelfdestruct -> [LitByte 0xFF] OpDup n -> if 1 <= n && n <= 16 then [LitByte (0x80 + (n - 1))] else error $ "Internal Error: invalid argument to OpDup: " <> show n OpSwap n -> if 1 <= n && n <= 16 then [LitByte (0x90 + (n - 1))] else error $ "Internal Error: invalid argument to OpSwap: " <> show n OpLog n -> if 0 <= n && n <= 4 then [LitByte (0xA0 + n)] else error $ "Internal Error: invalid argument to OpLog: " <> show n -- we just always assemble OpPush into PUSH32 OpPush wrd -> (LitByte 0x7f) : [Expr.indexWord (Lit i) wrd | i <- [0..31]] OpPush0 -> [LitByte 0x5f] OpUnknown o -> [LitByte o]