Skip to content

Function isolation, local vars, byte arrays + elif fix - #1

Open
Landen-Martin wants to merge 2 commits into
sha0coder:mainfrom
Landen-Martin:main
Open

Function isolation, local vars, byte arrays + elif fix#1
Landen-Martin wants to merge 2 commits into
sha0coder:mainfrom
Landen-Martin:main

Conversation

@Landen-Martin

Copy link
Copy Markdown

1. register isolation on calls

x64 has no pushad/popad so I do it by hand. Every function prologue pushes rbx-r15 and visit_Return pops em back (rax is left alone for the return value).

Before this, calling a function that used e.g. rbx internally would trash the caller's rbx with no warning. Now:

r9=checksum(rcx, rdx)
r8=mem[rcx+1] # rcx still valid, callee didnt touch it

cost is some stack churn + a few bytes per call, but for the code this thing generates its worth it.

2. local vars

names that arent regs64 now get a stack slot instead of failing to compile. find_locals() walks the function body at compile time and assigns each one an offset from rbp:

defclassify(rcx):
tag=0# lives at [rbp-8]
...

slot is found via locals_map, reset per function. const/reg/call assignment into a local all work.

3. byte array init

rax= [0x1a, 0x3b, 0xff, 0x00]

gets pushed onto the stack as little-endian qwords (zero padded to a multiple of 8) and the target reg points at the first byte. handy for building buffers / small string tables without a data section.

4. elif fix

the no-else branch of visit_If used generic_visit(node) which also walks node.orelse — so an elif (nested If inside orelse) got compiled twice and the labels were wrong. now the body is visited explicitly like the else path already did, and elif chains fall out of the existing orelse handling for free.

5. cleanup

indentation was all over the place (mixed 4/8/20 spaces from the elif blocks), reformatted everything. no logic changes there.

example

added example/check-class.py showing all of the above: checksum loop over a stack array, elif chain, callee that clobbers regs but doesn't matter now.

known limits

  • reading a local back into a reg (rax = tag) is not wired up yet, only writes. move through a reg for now
  • stack slots are allocated for every non-reg assign, even if its dead after the first write
  • the save_regs push/pop is unconditional — could skip regs we can prove unused, but not worth the complexity yet

This is my first pull request. So I may get things Wrong.

Implement a Python to NASM compiler for 64-bit architecture.
Implement checksum and classify functions for data processing.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Landen-Martin