Implemented parameter passing for function pointers
This commit is contained in:
parent
751614e7c0
commit
df6f7d5a57
21
src/core/AfterCall.go
Normal file
21
src/core/AfterCall.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
|
"git.urbach.dev/cli/q/src/cpu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AfterCall pops used register values back from the stack.
|
||||||
|
func (f *Function) AfterCall(registers []cpu.Register) {
|
||||||
|
for _, register := range slices.Backward(f.CPU.General) {
|
||||||
|
if f.RegisterIsUsed(register) {
|
||||||
|
f.Register(asm.POP, register)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, register := range registers {
|
||||||
|
f.FreeRegister(register)
|
||||||
|
}
|
||||||
|
}
|
18
src/core/BeforeCall.go
Normal file
18
src/core/BeforeCall.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BeforeCall pushes used registers to the stack.
|
||||||
|
func (f *Function) BeforeCall() {
|
||||||
|
for _, register := range f.CPU.Output {
|
||||||
|
f.SaveRegister(register)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, register := range f.CPU.General {
|
||||||
|
if f.RegisterIsUsed(register) {
|
||||||
|
f.Register(asm.PUSH, register)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +0,0 @@
|
|||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
|
||||||
"git.urbach.dev/cli/q/src/cpu"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CallSafe pushes used registers to the stack, executes the call and restores the original register value.
|
|
||||||
func (f *Function) CallSafe(fn *Function, registers []cpu.Register) {
|
|
||||||
for _, register := range f.CPU.Output {
|
|
||||||
f.SaveRegister(register)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, register := range f.CPU.General {
|
|
||||||
if f.RegisterIsUsed(register) {
|
|
||||||
f.Register(asm.PUSH, register)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Label(asm.CALL, fn.UniqueName)
|
|
||||||
|
|
||||||
for _, register := range slices.Backward(f.CPU.General) {
|
|
||||||
if f.RegisterIsUsed(register) {
|
|
||||||
f.Register(asm.POP, register)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, register := range registers {
|
|
||||||
f.FreeRegister(register)
|
|
||||||
}
|
|
||||||
}
|
|
@ -59,14 +59,32 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
f.CallSafe(fn, registers)
|
f.BeforeCall()
|
||||||
|
f.Label(asm.CALL, value.Label)
|
||||||
|
f.AfterCall(registers)
|
||||||
return fn.OutputTypes, nil
|
return fn.OutputTypes, nil
|
||||||
|
|
||||||
case *eval.Register:
|
case *eval.Register:
|
||||||
|
err := f.ExpressionsToRegisters(parameters, registers, nil, true)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.BeforeCall()
|
||||||
f.Register(asm.CALL, value.Register)
|
f.Register(asm.CALL, value.Register)
|
||||||
|
f.AfterCall(registers)
|
||||||
|
|
||||||
case *eval.Memory:
|
case *eval.Memory:
|
||||||
|
err := f.ExpressionsToRegisters(parameters, registers, nil, true)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.BeforeCall()
|
||||||
f.Memory(asm.CALL, value.Memory)
|
f.Memory(asm.CALL, value.Memory)
|
||||||
|
f.AfterCall(registers)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -23,7 +23,9 @@ func (f *Function) CompileDelete(root *expression.Expression) error {
|
|||||||
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Value.Register)
|
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Value.Register)
|
||||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Value.Typ.(*types.Pointer).To.Size())
|
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Value.Typ.(*types.Pointer).To.Size())
|
||||||
free := f.All.Functions["mem.free"]
|
free := f.All.Functions["mem.free"]
|
||||||
f.CallSafe(free, f.CPU.Input[:2])
|
f.BeforeCall()
|
||||||
|
f.Label(asm.CALL, "mem.free")
|
||||||
|
f.AfterCall(f.CPU.Input[:2])
|
||||||
f.Dependencies = append(f.Dependencies, free)
|
f.Dependencies = append(f.Dependencies, free)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,9 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
|
|||||||
f.SaveRegister(f.CPU.Input[0])
|
f.SaveRegister(f.CPU.Input[0])
|
||||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
||||||
alloc := f.All.Functions["mem.alloc"]
|
alloc := f.All.Functions["mem.alloc"]
|
||||||
f.CallSafe(alloc, f.CPU.Input[:1])
|
f.BeforeCall()
|
||||||
|
f.Label(asm.CALL, "mem.alloc")
|
||||||
|
f.AfterCall(f.CPU.Input[:1])
|
||||||
f.Dependencies = append(f.Dependencies, alloc)
|
f.Dependencies = append(f.Dependencies, alloc)
|
||||||
return &types.Pointer{To: typ}, nil
|
return &types.Pointer{To: typ}, nil
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ struct Struct {
|
|||||||
main() {
|
main() {
|
||||||
s := new(Struct)
|
s := new(Struct)
|
||||||
s.func = f
|
s.func = f
|
||||||
s.func()
|
s.func(0)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
f() {
|
f(code int) {
|
||||||
sys.exit(0)
|
sys.exit(code)
|
||||||
}
|
}
|
@ -1,13 +1,12 @@
|
|||||||
import core
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
func := f
|
func := f
|
||||||
func()
|
func(0)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
f() {
|
f(code int) {
|
||||||
exit := core.exit
|
exit := sys.exit
|
||||||
exit()
|
exit(code)
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user