Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Wrc20 code golfing #1

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 4 additions & 1 deletion eth_contracts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,12 @@ proc getBlockTimestamp*(): int64
proc callDataCopy*[T](res: var T, offset: int) {.inline.} =
callDataCopy(addr res, offset.int32, sizeof(res).int32)

proc callDataCopy*(T: type, offset: int): T {.inline.} =
callDataCopy(addr result, offset.int32, sizeof(T).int32)

proc callDataCopy*[N](res: var array[N, byte], offset: int, bytes: int) {.inline.} =
## copy bytes from calldata, zeroing out the rest of the array
callDataCopy(addr res[0], offset.int32, res.len.int32)
callDataCopy(addr res[0], offset.int32, bytes.int32)
zeroMem(addr res[bytes], res.len - bytes)

proc getCaller*[N](res: var array[N, byte]) {.inline.} =
Expand Down
34 changes: 34 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
L=/home/arnetheduck/src/nlvm/ext/llvm-8.0.0.src/sha/bin
Copy link

Choose a reason for hiding this comment

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

Could you fix these paths?

Copy link
Member Author

Choose a reason for hiding this comment

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

I could if I had a good idea how that didn't involve lots of mess :) WIP for now, this branch shouldn't be merged yet

NFLAGS=--checks:off --nlvm.target=wasm32-unknown-unknown --gc:none -l:--compress-relocations -l:--no-entry -l:--allow-undefined -l:--strip-all --noMain
B=/home/arnetheduck/src/binaryen/bin

.PHONY: all
all: wrc20.wat wrc20opt.wat wrc20opt.ll wrc20strip.wat wrc20binaryen.wat
ls -l

wrc20opt.wasm: wrc20opt.ll
$(L)/llc -filetype=obj -O2 wrc20opt.ll -o wrc20opt.o
$(L)/wasm-ld -o wrc20opt.wasm wrc20opt.o -O2 --strip-all --no-entry --allow-undefined --export-dynamic --compress-relocations

wrc20.ll: wrc20.nim
nlvm c $(NFLAGS) -c -d:release --opt:size wrc20

wrc20.wasm: wrc20.nim
nlvm c $(NFLAGS) -d:release --opt:size wrc20

wrc20opt.ll: wrc20.ll
$(L)/opt -O2 -disable-inlining wrc20.ll | $(L)/llvm-dis > wrc20opt.ll

.PHONY: clean
clean:
rm -f *.wasm *.ll *.wat

%.wat: %.wasm
wasm2wat --generate-names $< > $@

wrc20strip.wasm: wrc20opt.wat
sed -e '/__heap_base\|__data_end\|funcref/d' -e 's/env/ethereum/g' wrc20opt.wat > wrc20tmp.wat
wat2wasm -o wrc20strip.wasm wrc20tmp.wat

wrc20binaryen.wasm: wrc20strip.wasm
$(B)/wasm-opt -Os -o wrc20binaryen.wasm wrc20strip.wasm
22 changes: 0 additions & 22 deletions examples/config.nims

This file was deleted.

31 changes: 13 additions & 18 deletions examples/wrc20.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,20 @@

import ../eth_contracts

proc bigEndian64*(inp: pointer): uint64 =
# If we turn on the llvm inliner, it will inline calls to the bswap intrinsic
# causing a code size explosion - looks like for the wasm target, it doesn't
# count expansion that's done due to the lack of a bswap instruction.
# As a workaround, one needs to make sure that inlining is disabled when
# compiling with llvm / clang!
# Also as a workaround, we do a special version of bigEndian64 here that
# avoids some random calls that are generally needed for byte alignment but
# can be avoided here..
# TODO report upstream
var x = cast[ptr uint64](inp)[]

x = (x and 0x00000000FFFFFFFF'u64) shl 32'u64 or (x and 0xFFFFFFFF00000000'u64) shr 32'u64
proc bigEndian64*(x: uint64): uint64 {.noinline.} =
# If we use inliner or enable the bswap intrinsic, code size explodes as wasm
# lacks a bswap instruction
var x = (x and 0x00000000FFFFFFFF'u64) shl 32'u64 or (x and 0xFFFFFFFF00000000'u64) shr 32'u64
x = (x and 0x0000FFFF0000FFFF'u64) shl 16'u64 or (x and 0xFFFF0000FFFF0000'u64) shr 16'u64
x = (x and 0x00FF00FF00FF00FF'u64) shl 8'u64 or (x and 0xFF00FF00FF00FF00'u64) shr 8'u64
x

template bigEndian64*(v: uint64, outp: var openArray[byte]) =
cast[ptr uint64](addr outp[0])[] = bigEndian64(unsafeAddr v)
cast[ptr uint64](addr outp[0])[] = bigEndian64(v)

template bigEndian64*[N: static int](v: array[N, byte]): uint64 =
static: assert N >= sizeof(uint64)
bigEndian64(cast[ptr uint64](addr v[0])[])

proc do_balance() =
if getCallDataSize() != 24:
Expand Down Expand Up @@ -54,20 +49,20 @@ proc do_transfer() =
storageLoad(recipient, recipientBalance)

var
sb = bigEndian64(addr senderBalance)
v = bigEndian64(addr value)
sb = bigEndian64(senderBalance)
v = bigEndian64(value)

if sb < v:
revert(nil, 0)

var
rb = bigEndian64(addr recipientBalance)
rb = bigEndian64(recipientBalance)

sb -= v
rb += v # TODO there's an overflow possible here..

bigEndian64(sb, senderBalance)
bigEndian64(sb, recipientBalance)
bigEndian64(rb, recipientBalance)

storageStore(sender, senderBalance)
storageStore(recipient, recipientBalance)
Expand Down