Added Windows support for the hello example
All checks were successful
/ test (push) Successful in 16s

This commit is contained in:
Eduard Urbach 2025-07-02 21:56:20 +02:00
parent e833268061
commit 47b4b1f1dd
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
7 changed files with 92 additions and 55 deletions

View file

@ -1,10 +1,12 @@
write(_ string) -> (written int) { write(buffer string) -> (written int) {
return 0 stdout := kernel32.GetStdHandle(-11)
kernel32.WriteConsoleA(stdout, buffer.ptr, buffer.len, 0)
return buffer.len
} }
extern { extern {
kernel32 { kernel32 {
GetStdHandle(handle int64) -> int64 GetStdHandle(device int64) -> (handle int64)
WriteConsoleA(fd int64, buffer *byte, length uint32, written *uint32) -> bool WriteConsoleA(fd int64, buffer *byte, length uint32, written *uint32) -> (success bool)
} }
} }

View file

@ -42,8 +42,9 @@ const (
) )
var CPU = cpu.CPU{ var CPU = cpu.CPU{
Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6}, Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5}, Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5},
ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7}, ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7},
Return: []cpu.Register{X0, X1, X2}, 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},
} }

View file

@ -122,6 +122,21 @@ func (f *Function) Evaluate(expr *expression.Expression) (ssa.Value, error) {
for i, param := range slices.Backward(parameters) { for i, param := range slices.Backward(parameters) {
if !types.Is(param.Type(), fn.Input[i].Typ) { 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{ return nil, errors.New(&TypeMismatch{
Encountered: param.Type().Name(), Encountered: param.Type().Name(),
Expected: fn.Input[i].Typ.Name(), Expected: fn.Input[i].Typ.Name(),

View file

@ -2,8 +2,9 @@ package cpu
// CPU represents the processor. // CPU represents the processor.
type CPU struct { type CPU struct {
Call []Register Call []Register
Syscall []Register Syscall []Register
ExternCall []Register ExternCall []Register
Return []Register ExternCallVolatile []Register
Return []Register
} }

View file

@ -2,7 +2,6 @@ package ssa2asm
import ( import (
"slices" "slices"
"strings"
"git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/asm"
"git.urbach.dev/cli/q/src/ssa" "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 { for instr := range ir.Values {
if instr.CountUsers() != 0 {
continue
}
switch instr := instr.(type) { switch instr := instr.(type) {
case *ssa.Call: case *ssa.Call, *ssa.Syscall:
fn := instr.Arguments[0].(*ssa.Function) f.ValueToRegister(instr, f.CPU.Return[0])
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.Return: case *ssa.Return:
for i := range slices.Backward(instr.Arguments) { 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{}) 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{})
} }
} }

View file

@ -1,6 +1,9 @@
package ssa2asm package ssa2asm
import ( import (
"slices"
"strings"
"git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/asm"
"git.urbach.dev/cli/q/src/cpu" "git.urbach.dev/cli/q/src/cpu"
"git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/ssa"
@ -19,6 +22,47 @@ func (f *Compiler) ValueToRegister(instr ssa.Value, destination cpu.Register) {
Label: label.Name, 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: case *ssa.Int:
f.Assembler.Append(&asm.MoveRegisterNumber{ f.Assembler.Append(&asm.MoveRegisterNumber{
Destination: destination, Destination: destination,
@ -52,6 +96,12 @@ func (f *Compiler) ValueToRegister(instr ssa.Value, destination cpu.Register) {
}) })
case *ssa.Syscall: 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] { if destination == f.CPU.Return[0] {
return return
} }

View file

@ -22,8 +22,9 @@ const (
) )
var CPU = cpu.CPU{ var CPU = cpu.CPU{
Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9}, Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
Syscall: []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}, ExternCall: []cpu.Register{R1, R2, R8, R9},
Return: []cpu.Register{R0, R7, R6}, ExternCallVolatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11},
Return: []cpu.Register{R0, R7, R6},
} }