Added separate value type for extern calls
All checks were successful
/ test (push) Successful in 30s

This commit is contained in:
Eduard Urbach 2025-07-03 16:57:39 +02:00
parent 4aa4d613a1
commit 3f481d0bd3
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
4 changed files with 110 additions and 28 deletions

View file

@ -145,12 +145,11 @@ func (f *Function) Evaluate(expr *expression.Expression) (ssa.Value, error) {
} }
} }
call := &ssa.Call{ if fn.IsExtern() {
Arguments: args, return f.Append(&ssa.CallExtern{Arguments: args, Source: ssa.Source(expr.Source)}), nil
Source: ssa.Source(expr.Source),
} }
return f.Append(call), nil return f.Append(&ssa.Call{Arguments: args, Source: ssa.Source(expr.Source)}), nil
} }
case token.Dot: case token.Dot:

73
src/ssa/CallExtern.go Normal file
View file

@ -0,0 +1,73 @@
package ssa
import (
"strconv"
"strings"
"git.urbach.dev/cli/q/src/types"
)
type CallExtern struct {
Id
Arguments
Liveness
Source
}
func (a *CallExtern) Equals(v Value) bool {
b, sameType := v.(*CallExtern)
if !sameType {
return false
}
return a.Arguments.Equals(b.Arguments)
}
func (v *CallExtern) IsConst() bool {
return false
}
func (v *CallExtern) Debug(expand bool) string {
tmp := strings.Builder{}
if expand {
tmp.WriteString(v.Arguments[0].String())
} else {
tmp.WriteString("%")
tmp.WriteString(strconv.Itoa(v.Arguments[0].ID()))
}
tmp.WriteString("(")
args := v.Arguments[1:]
for i, arg := range args {
if expand {
tmp.WriteString(arg.String())
} else {
tmp.WriteString("%")
tmp.WriteString(strconv.Itoa(arg.ID()))
}
if i != len(args)-1 {
tmp.WriteString(", ")
}
}
tmp.WriteString(")")
return tmp.String()
}
func (v *CallExtern) String() string {
return v.Debug(true)
}
func (v *CallExtern) Type() types.Type {
typ := v.Arguments[0].(*Function).Typ
if len(typ.Output) == 0 {
return types.Void
}
return typ.Output[0]
}

View file

@ -21,7 +21,7 @@ func (f *Compiler) GenerateAssembly(ir ssa.IR, isLeaf bool) {
} }
switch instr := instr.(type) { switch instr := instr.(type) {
case *ssa.Call, *ssa.Syscall: case *ssa.Call, *ssa.CallExtern, *ssa.Syscall:
f.ValueToRegister(instr, f.CPU.Return[0]) f.ValueToRegister(instr, f.CPU.Return[0])
case *ssa.Return: case *ssa.Return:

View file

@ -25,35 +25,45 @@ func (f *Compiler) ValueToRegister(instr ssa.Value, destination cpu.Register) {
case *ssa.Call: case *ssa.Call:
fn := instr.Arguments[0].(*ssa.Function) fn := instr.Arguments[0].(*ssa.Function)
args := instr.Arguments[1:] args := instr.Arguments[1:]
offset := 0
if fn.IsExtern { for i := range slices.Backward(args) {
for i := range slices.Backward(args) { structure, isStruct := args[i].(*ssa.Struct)
f.ValueToRegister(args[i], f.CPU.ExternCall[i])
}
dot := strings.IndexByte(fn.UniqueName, '.') if isStruct {
library := fn.UniqueName[:dot] for _, field := range structure.Arguments {
function := fn.UniqueName[dot+1:] f.ValueToRegister(field, f.CPU.Call[offset+i])
f.Assembler.Append(&asm.CallExtern{Library: library, Function: function}) i++
} 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])
} }
} else {
f.ValueToRegister(args[i], f.CPU.Call[offset+i])
} }
f.Assembler.Append(&asm.Call{Label: fn.UniqueName})
} }
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.CallExtern:
fn := instr.Arguments[0].(*ssa.Function)
args := instr.Arguments[1:]
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})
if destination == f.CPU.Return[0] { if destination == f.CPU.Return[0] {
return return
} }