Cr0a3 / ygen

Ygen - Yet another code generator
https://ygen.vercel.app/
Apache License 2.0
9 stars 0 forks source link

[BUG] Register override #8

Open Cr0a3 opened 2 weeks ago

Cr0a3 commented 2 weeks ago

Describe the bug Running a simple example from simplelang:

import with (fmt: string, ...) printf // printf from libc

extern with () main: {
    printf("Hello World!\n");

    var x: u32 = 5;

    printf("%d = %d", x, 5);

    return 0;
}

Outputs:

Hello World!
1827627024 = 5

What it shouldn't. Here's the expected output:

Hello World!
5= 5

The 1827627024 is the adress of the formatting string (%d = %d) which means that the register of the variable x gets overrideden.

IR

const .const0 = [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10, ,]
const .const1 = [ 37, 100, 32, 61, 32, 37, 100, ,]
define i32 @main() {
 entry:
    %0 = ptr .const0
    %1 = call i32 printf ptr %0
    %2 = i64 5
    %3 = i64 %2
    %4 = ptr .const1
    %5 = i64 5
    %6 = call i32 printf ptr %4 i64 %3 i64 %5
    %7 = i64 0
    ret i64 %7

}
declare i32 @printf( ptr %0 )

In line: %3 = i64 %2 the compile thinks that %2 is dropped which means it frees the resources. But sussly the resources from the last free aren't assignet back so the register for the variable gets overriden by the next line: %4 = ptr .const1

Generated assembly

// made using ygen v0.1.1
// by Cr0a3

section .rodata

.const0: [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10, 0] # Hello World!
.const1: [37, 100, 32, 61, 32, 37, 100, 0] # %d = %d
section .text

global main
main:
    push rbp
    mov rbp, rsp
    sub rsp, 40
    lea rax, [ rip+ 1 ]

    mov rcx, rax    # %0 = ptr .const0
    call 0

    mov ecx, eax    # %1 = call i32 printf ptr %0
    mov rcx, 5  # %2 = i64 5    # %3 = i64 %2
    lea rax, [ rip+ 1 ]

    mov rsi, rax    # %4 = ptr .const1
    mov rdi, 5  # %5 = i64 5
    mov rcx, rsi
    mov rdx, rcx
    mov r8, rdi
    call 0

    mov edi, eax    # %6 = call i32 printf ptr %4i64 %3i64 %5
    mov rcx, 0  # %7 = i64 0
    mov rax, rcx    # ret i64 %7
    add rsp, 40
    pop rbp
    ret
global printf
Cr0a3 commented 2 weeks ago

Is open for reopen

Cr0a3 commented 2 weeks ago

Wasn't fixed i knew it

Cr0a3 commented 2 weeks ago

Debugging is a bit hard because https://github.com/gimli-rs/object/issues/721

Cr0a3 commented 2 weeks ago

Fixed.

After some long debugging sessions i found out why. It's because the variables which are in the registers for the function arguments get overriten and then read for the new argument. They are also not saved because they aren't used after the call.

Example assembly line:

mov rcx, r10 // r10 = adress of string
mov rdx, rcx // rcx was the variable which is now overriden by the arg
mov r8, rsi
mov r9d, r11d
push rdi
call printf

Yeah, so i need to fix that. Maybe by using the stack?

Cr0a3 commented 2 weeks ago

Why did github close the issue??

Cr0a3 commented 2 weeks ago

So i found out the generated assembly code is now correct but the instruction encoding has some errors again!