Skip to content
This repository has been archived by the owner on Oct 18, 2022. It is now read-only.

Add support for value-related opcodes #28

Open
wants to merge 3 commits into
base: develop-0.7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 59 additions & 14 deletions libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,53 @@ bool CompilerContext::appendCallback(evmasm::AssemblyItem const& _i) {
m_disable_rewrite = true;

auto callYUL = R"(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically a copy-paste of what was there before -- looks intimidating but the diff is just a few lines really

// declare helper functions
function max(first, second) -> bigger {
bigger := first
if gt(second, first) { bigger := second }
}
function min(first, second) -> smaller {
smaller := first
if lt(second, first) { smaller := second }
}
// store _gasLimit
mstore(add(callBytes, 0x04), in_gas)
// store _address
mstore(add(callBytes, 0x24), addr)
// store call value
mstore(add(callBytes,0x44), value)
// store abi bytes memory offset
mstore(add(callBytes, 0x64), 0x80)
// store bytes memory _calldata.length
mstore(add(callBytes, 0x84), argsLength)
// store bytes memory _calldata raw data
let rawCallBytes := add(callBytes, 0xa4)
for { let ptr := 0 } lt(ptr, argsLength) { ptr := add(ptr, 0x20) } {
mstore(add(rawCallBytes, ptr), mload(add(argsOffset, ptr)))
}
// kall, only grabbing 3 words of returndata (success & abi encoding params) and just throw on top of where we put calldata (successfull kall will awlays return >= 0x60 bytes)
// overpad calldata by a word (argsLen [raw data] + 0xa4 [abi prefixing] + 0x20 [1 word max to pad] = argsLen + 0xc4) to ensure sufficient right 0-padding for abi encoding
kall(callBytes, add(0xc4, argsLength), callBytes, 0x60)
// get _success
let wasSuccess := mload(callBytes)
// get abi length of _data output by EM
let returnedDataLengthFromABI := mload(add(callBytes, 0x40))
// call identity precompile with ALL raw returndata (ignores bool and abi) to make returndatasize() correct.
// also copies the relevant data back to the CALL's intended vals (retOffset, retLength)
returndatacopy(callBytes, 0, returndatasize())
kopy(add(callBytes, 0x60), returnedDataLengthFromABI, retOffset, retLength)
// remove all the stuff we did at callbytes
let newMemSize := msize()
// overwrite zeros starting from either the pre-modification msize, or the end of returndata (whichever is bigger)
let endOfReturnData := add(retOffset,min(returndatasize(), retLength))
for { let ptr := max(callBytes, endOfReturnData) } lt(ptr, newMemSize) { ptr := add(ptr, 0x20) } {
mstore(ptr, 0x00)
}
// set the first stack element out, this looks weird but it's really saying this is the intended stack output of the replaced EVM operation
retLength := wasSuccess
})";

auto noValueCallYUL = R"(
// declare helper functions
function max(first, second) -> bigger {
bigger := first
Expand Down Expand Up @@ -191,17 +238,6 @@ bool CompilerContext::appendCallback(evmasm::AssemblyItem const& _i) {
if (_i.type() == Operation) {
ret = true; // will be set to false again if we don't change the instruction
switch (_i.instruction()) {
case Instruction::SELFBALANCE:
case Instruction::BALANCE:
m_errorReporter.parserError(
1633_error,
assemblyPtr()->currentSourceLocation(),
"OVM: " +
instructionInfo(_i.instruction()).name +
" is not implemented in the OVM. (We have no native ETH -- use deposited WETH instead!)"
);
ret = false;
break;
case Instruction::BLOCKHASH:
case Instruction::CALLCODE:
case Instruction::COINBASE:
Expand Down Expand Up @@ -230,9 +266,18 @@ bool CompilerContext::appendCallback(evmasm::AssemblyItem const& _i) {
case Instruction::EXTCODEHASH:
simpleRewrite("ovmEXTCODEHASH(address)", 1, 1);
break;
case Instruction::BALANCE:
simpleRewrite("ovmBALANCE(address)", 1, 1);
break;
case Instruction::CALLER:
simpleRewrite("ovmCALLER()", 0, 1);
break;
case Instruction::CALLVALUE:
simpleRewrite("ovmCALLVALUE()", 0, 1);
break;
case Instruction::SELFBALANCE:
simpleRewrite("ovmSELFBALANCE()", 0, 1);
break;
case Instruction::ADDRESS:
// address doesn't like to be optimized for some reason
// a very small price to pay
Expand All @@ -251,15 +296,15 @@ bool CompilerContext::appendCallback(evmasm::AssemblyItem const& _i) {
simpleRewrite("ovmGASLIMIT()", 0, 1);
break;
case Instruction::CALL:
complexRewrite("ovmCALL(uint256,address,bytes)", 7, 1, callYUL,
complexRewrite("ovmCALL(uint256,address,uint256,bytes)", 7, 1, callYUL,
{"retLength", "retOffset", "argsLength", "argsOffset", "value", "addr", "in_gas"});
break;
case Instruction::STATICCALL:
complexRewrite("ovmSTATICCALL(uint256,address,bytes)", 6, 1, callYUL,
complexRewrite("ovmSTATICCALL(uint256,address,bytes)", 6, 1, noValueCallYUL,
{"retLength", "retOffset", "argsLength", "argsOffset", "addr", "in_gas"});
break;
case Instruction::DELEGATECALL:
complexRewrite("ovmDELEGATECALL(uint256,address,bytes)", 6, 1, callYUL,
complexRewrite("ovmDELEGATECALL(uint256,address,bytes)", 6, 1, noValueCallYUL,
{"retLength", "retOffset", "argsLength", "argsOffset", "addr", "in_gas"});
break;
case Instruction::REVERT:
Expand Down
2 changes: 1 addition & 1 deletion scripts/build_emscripten.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ else
BUILD_DIR="$1"
fi

docker run -v $(pwd):/root/project -w /root/project \
docker run --platform linux/amd64 -v $(pwd):/root/project -w /root/project \
solbuildpackpusher/solidity-buildpack-deps@sha256:23dad3b34deae8107c8551804ef299f6a89c23ed506e8118fac151e2bdc9018c\
./scripts/ci/build_emscripten.sh $BUILD_DIR