From 47b4b1f1ddb054aceafc990c130036cc7abfbb72 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 2 Jul 2025 21:56:20 +0200 Subject: [PATCH] Added Windows support for the hello example --- lib/io/write_windows.q | 10 ++++--- src/arm/Registers.go | 9 +++--- src/core/Evaluate.go | 15 ++++++++++ src/cpu/CPU.go | 9 +++--- src/ssa2asm/GenerateAssembly.go | 45 ++++------------------------- src/ssa2asm/ValueToRegister.go | 50 +++++++++++++++++++++++++++++++++ src/x86/Registers.go | 9 +++--- 7 files changed, 92 insertions(+), 55 deletions(-) diff --git a/lib/io/write_windows.q b/lib/io/write_windows.q index 0b40b6a..c9a4f3d 100644 --- a/lib/io/write_windows.q +++ b/lib/io/write_windows.q @@ -1,10 +1,12 @@ -write(_ string) -> (written int) { - return 0 +write(buffer string) -> (written int) { + stdout := kernel32.GetStdHandle(-11) + kernel32.WriteConsoleA(stdout, buffer.ptr, buffer.len, 0) + return buffer.len } extern { kernel32 { - GetStdHandle(handle int64) -> int64 - WriteConsoleA(fd int64, buffer *byte, length uint32, written *uint32) -> bool + GetStdHandle(device int64) -> (handle int64) + WriteConsoleA(fd int64, buffer *byte, length uint32, written *uint32) -> (success bool) } } \ No newline at end of file diff --git a/src/arm/Registers.go b/src/arm/Registers.go index 794c658..ec53bd7 100644 --- a/src/arm/Registers.go +++ b/src/arm/Registers.go @@ -42,8 +42,9 @@ const ( ) var CPU = cpu.CPU{ - Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6}, - Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5}, - ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7}, - Return: []cpu.Register{X0, X1, X2}, + Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6}, + Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5}, + ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7}, + ExternCallVolatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17}, + Return: []cpu.Register{X0, X1, X2}, } \ No newline at end of file diff --git a/src/core/Evaluate.go b/src/core/Evaluate.go index 90fee68..f7eef07 100644 --- a/src/core/Evaluate.go +++ b/src/core/Evaluate.go @@ -122,6 +122,21 @@ func (f *Function) Evaluate(expr *expression.Expression) (ssa.Value, error) { for i, param := range slices.Backward(parameters) { if !types.Is(param.Type(), fn.Input[i].Typ) { + _, isPointer := fn.Input[i].Typ.(*types.Pointer) + + if isPointer { + number, isInt := param.(*ssa.Int) + + if isInt && number.Int == 0 { + continue + } + } + + // Temporary hack to allow int64 -> uint32 conversion + if types.Is(param.Type(), types.AnyInt) && types.Is(fn.Input[i].Typ, types.AnyInt) { + continue + } + return nil, errors.New(&TypeMismatch{ Encountered: param.Type().Name(), Expected: fn.Input[i].Typ.Name(), diff --git a/src/cpu/CPU.go b/src/cpu/CPU.go index 30ef6cd..68b41ee 100644 --- a/src/cpu/CPU.go +++ b/src/cpu/CPU.go @@ -2,8 +2,9 @@ package cpu // CPU represents the processor. type CPU struct { - Call []Register - Syscall []Register - ExternCall []Register - Return []Register + Call []Register + Syscall []Register + ExternCall []Register + ExternCallVolatile []Register + Return []Register } \ No newline at end of file diff --git a/src/ssa2asm/GenerateAssembly.go b/src/ssa2asm/GenerateAssembly.go index 4edb6fd..e36f902 100644 --- a/src/ssa2asm/GenerateAssembly.go +++ b/src/ssa2asm/GenerateAssembly.go @@ -2,7 +2,6 @@ package ssa2asm import ( "slices" - "strings" "git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/ssa" @@ -17,38 +16,13 @@ func (f *Compiler) GenerateAssembly(ir ssa.IR, isLeaf bool) { } for instr := range ir.Values { + if instr.CountUsers() != 0 { + continue + } + switch instr := instr.(type) { - case *ssa.Call: - fn := instr.Arguments[0].(*ssa.Function) - args := instr.Arguments[1:] - - if fn.IsExtern { - for i := range slices.Backward(args) { - f.ValueToRegister(args[i], f.CPU.ExternCall[i]) - } - - dot := strings.IndexByte(fn.UniqueName, '.') - library := fn.UniqueName[:dot] - function := fn.UniqueName[dot+1:] - f.Assembler.Append(&asm.CallExtern{Library: library, Function: function}) - } else { - offset := 0 - - for i := range slices.Backward(args) { - structure, isStruct := args[i].(*ssa.Struct) - - if isStruct { - for _, field := range structure.Arguments { - f.ValueToRegister(field, f.CPU.Call[offset+i]) - i++ - } - } else { - f.ValueToRegister(args[i], f.CPU.Call[offset+i]) - } - } - - f.Assembler.Append(&asm.Call{Label: fn.UniqueName}) - } + case *ssa.Call, *ssa.Syscall: + f.ValueToRegister(instr, f.CPU.Return[0]) case *ssa.Return: for i := range slices.Backward(instr.Arguments) { @@ -56,13 +30,6 @@ func (f *Compiler) GenerateAssembly(ir ssa.IR, isLeaf bool) { } f.Assembler.Append(&asm.Return{}) - - case *ssa.Syscall: - for i := range slices.Backward(instr.Arguments) { - f.ValueToRegister(instr.Arguments[i], f.CPU.Syscall[i]) - } - - f.Assembler.Append(&asm.Syscall{}) } } diff --git a/src/ssa2asm/ValueToRegister.go b/src/ssa2asm/ValueToRegister.go index 2e341c4..10b1bfb 100644 --- a/src/ssa2asm/ValueToRegister.go +++ b/src/ssa2asm/ValueToRegister.go @@ -1,6 +1,9 @@ package ssa2asm import ( + "slices" + "strings" + "git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/cpu" "git.urbach.dev/cli/q/src/ssa" @@ -19,6 +22,47 @@ func (f *Compiler) ValueToRegister(instr ssa.Value, destination cpu.Register) { Label: label.Name, }) + case *ssa.Call: + fn := instr.Arguments[0].(*ssa.Function) + args := instr.Arguments[1:] + + if fn.IsExtern { + for i := range slices.Backward(args) { + f.ValueToRegister(args[i], f.CPU.ExternCall[i]) + } + + dot := strings.IndexByte(fn.UniqueName, '.') + library := fn.UniqueName[:dot] + function := fn.UniqueName[dot+1:] + f.Assembler.Append(&asm.CallExtern{Library: library, Function: function}) + } else { + offset := 0 + + for i := range slices.Backward(args) { + structure, isStruct := args[i].(*ssa.Struct) + + if isStruct { + for _, field := range structure.Arguments { + f.ValueToRegister(field, f.CPU.Call[offset+i]) + i++ + } + } else { + f.ValueToRegister(args[i], f.CPU.Call[offset+i]) + } + } + + f.Assembler.Append(&asm.Call{Label: fn.UniqueName}) + } + + if destination == f.CPU.Return[0] { + return + } + + f.Assembler.Append(&asm.MoveRegisterRegister{ + Destination: destination, + Source: f.CPU.Return[0], + }) + case *ssa.Int: f.Assembler.Append(&asm.MoveRegisterNumber{ Destination: destination, @@ -52,6 +96,12 @@ func (f *Compiler) ValueToRegister(instr ssa.Value, destination cpu.Register) { }) case *ssa.Syscall: + for i := range slices.Backward(instr.Arguments) { + f.ValueToRegister(instr.Arguments[i], f.CPU.Syscall[i]) + } + + f.Assembler.Append(&asm.Syscall{}) + if destination == f.CPU.Return[0] { return } diff --git a/src/x86/Registers.go b/src/x86/Registers.go index 4e13458..f939b5f 100644 --- a/src/x86/Registers.go +++ b/src/x86/Registers.go @@ -22,8 +22,9 @@ const ( ) var CPU = cpu.CPU{ - Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, - Syscall: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, - ExternCall: []cpu.Register{R1, R2, R8, R9}, - Return: []cpu.Register{R0, R7, R6}, + Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, + Syscall: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, + ExternCall: []cpu.Register{R1, R2, R8, R9}, + ExternCallVolatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11}, + Return: []cpu.Register{R0, R7, R6}, } \ No newline at end of file