Added a program init function
This commit is contained in:
parent
00be603b8f
commit
9f125694be
8
lib/core/core_linux.q
Normal file
8
lib/core/core_linux.q
Normal file
@ -0,0 +1,8 @@
|
||||
init() {
|
||||
main.main()
|
||||
exit()
|
||||
}
|
||||
|
||||
exit() {
|
||||
syscall(60, 0)
|
||||
}
|
8
lib/core/core_mac.q
Normal file
8
lib/core/core_mac.q
Normal file
@ -0,0 +1,8 @@
|
||||
init() {
|
||||
main.main()
|
||||
exit()
|
||||
}
|
||||
|
||||
exit() {
|
||||
syscall(0x2000001, 0)
|
||||
}
|
20
lib/core/core_windows.q
Normal file
20
lib/core/core_windows.q
Normal file
@ -0,0 +1,20 @@
|
||||
extern kernel32 {
|
||||
SetConsoleCP(cp UInt)
|
||||
SetConsoleOutputCP(cp UInt)
|
||||
ExitProcess(code UInt)
|
||||
}
|
||||
|
||||
const cp {
|
||||
utf8 65001
|
||||
}
|
||||
|
||||
init() {
|
||||
kernel32.SetConsoleCP(cp.utf8)
|
||||
kernel32.SetConsoleOutputCP(cp.utf8)
|
||||
main.main()
|
||||
exit()
|
||||
}
|
||||
|
||||
exit() {
|
||||
kernel32.ExitProcess(0)
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import core
|
||||
import sys
|
||||
|
||||
const clone {
|
||||
@ -15,7 +16,7 @@ create(func *Any) -> Int {
|
||||
stack := sys.mmap(0, size, 0x1|0x2, 0x02|0x20|0x100|0x20000)
|
||||
stack += size
|
||||
stack -= 8
|
||||
store(stack, 8, _exit)
|
||||
store(stack, 8, core.exit)
|
||||
stack -= 8
|
||||
store(stack, 8, func)
|
||||
return sys.clone(clone.vm|clone.fs|clone.files|clone.sighand|clone.parent|clone.thread|clone.io, stack)
|
||||
|
@ -98,6 +98,13 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
|
||||
}
|
||||
}
|
||||
|
||||
// Check for existence of `init`
|
||||
init, exists := allFunctions["core.init"]
|
||||
|
||||
if !exists {
|
||||
return result, errors.MissingInitFunction
|
||||
}
|
||||
|
||||
// Check for existence of `main`
|
||||
main, exists := allFunctions["main.main"]
|
||||
|
||||
@ -105,6 +112,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
|
||||
return result, errors.MissingMainFunction
|
||||
}
|
||||
|
||||
result.Init = init
|
||||
result.Main = main
|
||||
result.Functions = allFunctions
|
||||
result.finalize()
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
// Result contains everything we need to write an executable file to disk.
|
||||
type Result struct {
|
||||
Init *core.Function
|
||||
Main *core.Function
|
||||
Functions map[string]*core.Function
|
||||
Traversed map[*core.Function]bool
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/asmc"
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/core"
|
||||
"git.akyoto.dev/cli/q/src/dll"
|
||||
"git.akyoto.dev/cli/q/src/x86"
|
||||
)
|
||||
|
||||
@ -20,33 +19,11 @@ func (r *Result) finalize() {
|
||||
Data: make(map[string][]byte, r.DataCount),
|
||||
}
|
||||
|
||||
final.Call("main.main")
|
||||
final.Label(asm.LABEL, "_exit")
|
||||
|
||||
switch config.TargetOS {
|
||||
case config.Linux:
|
||||
final.RegisterNumber(asm.MOVE, x86.SyscallInputRegisters[0], LinuxExit)
|
||||
final.RegisterNumber(asm.MOVE, x86.SyscallInputRegisters[1], 0)
|
||||
final.Syscall()
|
||||
case config.Mac:
|
||||
final.RegisterNumber(asm.MOVE, x86.SyscallInputRegisters[0], MacExit)
|
||||
final.RegisterNumber(asm.MOVE, x86.SyscallInputRegisters[1], 0)
|
||||
final.Syscall()
|
||||
case config.Windows:
|
||||
final.RegisterNumber(asm.MOVE, x86.WindowsInputRegisters[0], 0)
|
||||
final.RegisterNumber(asm.AND, x86.RSP, -16)
|
||||
final.DLLCall("kernel32.ExitProcess")
|
||||
}
|
||||
|
||||
r.DLLs = dll.List{
|
||||
{Name: "kernel32", Functions: []string{"ExitProcess"}},
|
||||
}
|
||||
|
||||
r.Traversed = make(map[*core.Function]bool, len(r.Functions))
|
||||
|
||||
// This will place the main function immediately after the entry point
|
||||
// and also add everything the main function calls recursively.
|
||||
r.eachFunction(r.Main, r.Traversed, func(f *core.Function) {
|
||||
// This will place the init function immediately after the entry point
|
||||
// and also add everything the init function calls recursively.
|
||||
r.eachFunction(r.Init, r.Traversed, func(f *core.Function) {
|
||||
final.Merge(f.Assembler)
|
||||
|
||||
for _, library := range f.DLLs {
|
||||
|
@ -44,6 +44,11 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
||||
name = nameNode.Token.Text(f.File.Bytes)
|
||||
}
|
||||
|
||||
if f.UniqueName == "core.init" && pkg == "main" && name == "main" {
|
||||
f.Call("main.main")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
fn, exists = f.Functions[pkg+"."+name]
|
||||
|
||||
if !exists {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/asm"
|
||||
@ -91,19 +92,28 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
|
||||
rightText := right.Token.Text(f.File.Bytes)
|
||||
variable := f.VariableByName(leftText)
|
||||
|
||||
if variable == nil {
|
||||
constant, isConst := f.Constants[f.Package+"."+leftText+"."+rightText]
|
||||
|
||||
if isConst {
|
||||
return f.TokenToRegister(constant.Value, register)
|
||||
}
|
||||
|
||||
return nil, errors.New(&errors.UnknownIdentifier{Name: leftText}, f.File, left.Token.Position)
|
||||
if variable != nil {
|
||||
field := variable.Type.(*types.Pointer).To.(*types.Struct).FieldByName(rightText)
|
||||
f.MemoryRegister(asm.LOAD, asm.Memory{Base: variable.Register, Offset: int8(field.Offset), Length: byte(field.Type.Size())}, register)
|
||||
return field.Type, nil
|
||||
}
|
||||
|
||||
field := variable.Type.(*types.Pointer).To.(*types.Struct).FieldByName(rightText)
|
||||
f.MemoryRegister(asm.LOAD, asm.Memory{Base: variable.Register, Offset: int8(field.Offset), Length: byte(field.Type.Size())}, register)
|
||||
return field.Type, nil
|
||||
constant, isConst := f.Constants[f.Package+"."+leftText+"."+rightText]
|
||||
|
||||
if isConst {
|
||||
return f.TokenToRegister(constant.Value, register)
|
||||
}
|
||||
|
||||
uniqueName := fmt.Sprintf("%s.%s", leftText, rightText)
|
||||
function, exists := f.Functions[uniqueName]
|
||||
|
||||
if exists {
|
||||
f.File.Imports[leftText].Used = true
|
||||
f.RegisterLabel(asm.MOVE, register, function.UniqueName)
|
||||
return types.AnyPointer, nil
|
||||
}
|
||||
|
||||
return nil, errors.New(&errors.UnknownIdentifier{Name: leftText}, f.File, left.Token.Position)
|
||||
}
|
||||
|
||||
if len(node.Children) == 1 {
|
||||
|
@ -17,6 +17,7 @@ var (
|
||||
MissingExpression = &Base{"Missing expression"}
|
||||
MissingGroupStart = &Base{"Missing '('"}
|
||||
MissingGroupEnd = &Base{"Missing ')'"}
|
||||
MissingInitFunction = &Base{"Missing init function"}
|
||||
MissingMainFunction = &Base{"Missing main function"}
|
||||
MissingOperand = &Base{"Missing operand"}
|
||||
MissingParameter = &Base{"Missing parameter"}
|
||||
|
@ -20,6 +20,7 @@ func Scan(files []string) (chan *core.Constant, <-chan *fs.File, <-chan *core.Fu
|
||||
}
|
||||
|
||||
go func() {
|
||||
scanner.queueDirectory(filepath.Join(config.Library, "core"), "core")
|
||||
scanner.queueDirectory(filepath.Join(config.Library, "mem"), "mem")
|
||||
scanner.queue(files...)
|
||||
scanner.group.Wait()
|
||||
|
Loading…
x
Reference in New Issue
Block a user