diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 5227fa5cbc..48b74e5011 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -150,6 +150,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) case Instruction::RETURN: case Instruction::STOP: + case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. if (curr + 1 < bytecode.cend()) @@ -761,6 +762,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SUICIDE: + { + auto address = stack.pop(); + ext.suicide(address); + // Fall through + } case Instruction::STOP: { builder.CreateRet(builder.getInt64(0)); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index e82a91ae99..9fad58fa77 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -85,6 +85,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); + m_suicide = Function::Create(TypeBuilder*), true>::get(ctx), Linkage::ExternalLinkage, "ext_suicide", module); m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); @@ -147,6 +148,13 @@ Value* Ext::balance(Value* _address) return m_builder.CreateLoad(m_args[1]); } +void Ext::suicide(Value* _address) +{ + auto address = bswap(_address); // to BE + m_builder.CreateStore(address, m_args[0]); + m_builder.CreateCall(m_suicide, m_args[0]); +} + Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) { m_builder.CreateStore(_endowment, m_args[0]); @@ -225,6 +233,11 @@ EXPORT void ext_balance(h256* _address, i256* _value) *_value = eth2llvm(u); } +EXPORT void ext_suicide(h256* _address) +{ + Runtime::getExt().suicide(dev::right160(*_address)); +} + EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) { auto&& ext = Runtime::getExt(); diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 88fad15a1e..c2c9f8455f 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -33,6 +33,7 @@ public: llvm::Value* gaslimit(); llvm::Value* balance(llvm::Value* _address); + void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); @@ -58,6 +59,7 @@ private: llvm::Function* m_setStore; llvm::Function* m_calldataload; llvm::Function* m_balance; + llvm::Function* m_suicide; llvm::Function* m_create; llvm::Function* m_call; llvm::Function* m_bswap; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index e8da21f45f..6c99e8fa08 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f10060016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f130ff60016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 5e359cb7fd..0625afadcc 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -38,7 +38,8 @@ CREATE ADDRESS 3000 CALL -STOP +ADDRESS +SUICIDE 1 2 RETURN