-
Notifications
You must be signed in to change notification settings - Fork 49
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
Adding label support to assembler #36
base: master
Are you sure you want to change the base?
Conversation
@@ -329,7 +328,17 @@ def is_arithmetic(self): | |||
'ADD', 'MUL', 'SUB', 'DIV', 'SDIV', 'MOD', 'SMOD', 'ADDMOD', 'MULMOD', 'EXP', 'SIGNEXTEND', 'SHL', 'SHR', 'SAR'} | |||
|
|||
|
|||
def assemble_one(asmcode, pc=0, fork=DEFAULT_FORK): | |||
def is_push(instr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternative instr.semantics == "PUSH"
Also if you really need an is_push
make one like is_branch
(you can use opcodes instead of semantics if you want)
Lines 305 to 308 in 0933d39
@property | |
def is_branch(self): | |
""" True if the instruction is a jump """ | |
return self.semantics in {'JUMP', 'JUMPI'} |
return instr | ||
except: | ||
raise AssembleError("Something wrong at pc %d" % pc) | ||
|
||
def fixup_instr(instr, label_offset): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Being it so simple I vote to do this inline so we do not need to document, maintain, etc and we save 1 func call.
line = line[:index] | ||
|
||
# skip directives: | ||
if line.find(".") is 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line.statrswith ?
pc += instr.size | ||
|
||
# fixup instructions | ||
for label in labels: | ||
if label not in fillins.keys(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for keys()
. label not in fillins
is enough I think, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you can check if the instruction has any operan referring to a label and fix them.
Add an Instruction.uses_labels()
that encapsulates that?
else: | ||
fillins[operand] = [pc] | ||
else: | ||
instr.operand = int(asmcode[1], 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea:
Not sure we need the fillings dict?
Maybe just write whatever there is to the instruction.operand. An int or label(string).
And then consider the instructions with a string operand to need fixup. ?
Instruction will not be able to generate a bytecode until it is "fixedup"
for label in labels: | ||
if label not in fillins.keys(): | ||
continue | ||
for instr in instrs: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of iterating over al linstructions for each label that qualifies maybe just rework all this do a single iteration over the instructions and fix the ones that needs it ? The instructions with Instruction.uses_labels()
true
Hey @lialan thank you for this. The idea of having labels and other more high level constructs is very interesting. I was secretly expecting for someone to use this in some compiler-ish project. I gave it a first pass. I hope we do not loss the filter like structure of the disassembler/assembler. |
hi @feliam, thanks for the reply (and suggestions!), I will update accordingly to your comments later this week. so I basically am using this assembler in my LLVM project for EVM backend, and I need an easy way to generate some LLVM IR for EVM target, such as https://github.com/etclabscore/evm_llvm/blob/EVM/test/CodeGen/EVM/runtime_tests/fib.ll Because I have not figured out how to represent contract creation code in LLVM code so here is what I am doing: using a contract template, instantiate it with with generated EVM assembly, then emit a real contract assembly, then use this assembler to emit EVM binary for testing on Geth. Here is how I integrate it into my testing workflow: Yes, this is a real use case of your code, kudo for that, and thanks for this little tool! I will try to see if I can figure out your comments and make proper changes to this pull request. |
I would like to use this little tool to do some easy assembling in my project but found that this does not support label syntax, such as:
So I just added the labeling syntax.
Another thing is that it seems that EVM memory space address starts with 1 rather than 0. So I changed
pc
according.