Fixed input parameter interference
All checks were successful
/ test (push) Successful in 20s

This commit is contained in:
Eduard Urbach 2025-07-04 23:46:06 +02:00
parent 0ece1b092e
commit 59363e2ed3
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
7 changed files with 75 additions and 38 deletions

View file

@ -12,13 +12,10 @@ func showSSA(root *core.Function) {
root.EachDependency(make(map[*core.Function]bool), func(f *core.Function) { root.EachDependency(make(map[*core.Function]bool), func(f *core.Function) {
ansi.Yellow.Println(f.UniqueName + ":") ansi.Yellow.Println(f.UniqueName + ":")
for _, block := range f.Blocks { for i, step := range f.Steps {
for i, instr := range block.Instructions { ansi.Dim.Printf("%%%d = ", i)
ansi.Dim.Printf("%%%-1d = ", i) fmt.Print(step.Value.String())
fmt.Printf("%-30s ", instr.String()) ansi.Dim.Printf(" %s %s %s\n", step.Value.Type().Name(), step.Register, step.Live)
ansi.Dim.Printf(" %-30s", instr.Type().Name())
fmt.Println()
}
} }
fmt.Println() fmt.Println()

View file

@ -1,6 +1,11 @@
package core package core
import "git.urbach.dev/cli/q/src/types" import (
"fmt"
"git.urbach.dev/cli/q/src/ssa"
"git.urbach.dev/cli/q/src/types"
)
// Compile turns a function into machine code. // Compile turns a function into machine code.
func (f *Function) Compile() { func (f *Function) Compile() {
@ -11,14 +16,29 @@ func (f *Function) Compile() {
continue continue
} }
input.Index = uint8(offset + i) structType, isStructType := input.Typ.(*types.Struct)
f.Append(input)
f.Identifiers[input.Name] = input
structure, isStruct := input.Typ.(*types.Struct)
if isStruct { if isStructType {
offset += len(structure.Fields) - 1 for _, field := range structType.Fields {
param := &ssa.Parameter{
Index: uint8(offset + i),
Name: fmt.Sprintf("%s.%s", input.Name, field.Name),
Typ: field.Type,
Source: input.Source,
} }
f.Identifiers[param.Name] = param
f.Append(param)
offset++
}
offset--
continue
}
input.Index = uint8(offset + i)
f.Identifiers[input.Name] = input
f.Append(input)
} }
for instr := range f.Body.Instructions { for instr := range f.Body.Instructions {

View file

@ -169,27 +169,33 @@ func (f *Function) Evaluate(expr *expression.Expression) (ssa.Value, error) {
right := expr.Children[1] right := expr.Children[1]
leftText := left.String(f.File.Bytes) leftText := left.String(f.File.Bytes)
rightText := right.String(f.File.Bytes) rightText := right.String(f.File.Bytes)
identifier, exists := f.Identifiers[leftText] fullName := fmt.Sprintf("%s.%s", leftText, rightText)
identifier, exists := f.Identifiers[fullName]
if exists { if exists {
structure := identifier.Type().(*types.Struct) return identifier, nil
field := structure.FieldByName(rightText)
if field == nil {
return nil, errors.New(&UnknownStructField{StructName: structure.Name(), FieldName: rightText}, f.File, right.Token.Position)
} }
v := f.Append(&ssa.Field{ // identifier, exists := f.Identifiers[leftText]
Object: identifier,
Field: field,
Source: ssa.Source(expr.Source),
})
return v, nil // if exists {
} // structType := identifier.Type().(*types.Struct)
// field := structType.FieldByName(rightText)
label := fmt.Sprintf("%s.%s", leftText, rightText) // if field == nil {
function, exists := f.All.Functions[label] // return nil, errors.New(&UnknownStructField{StructName: structType.Name(), FieldName: rightText}, f.File, right.Token.Position)
// }
// v := f.Append(&ssa.Field{
// Object: identifier,
// Field: field,
// Source: ssa.Source(expr.Source),
// })
// return v, nil
// }
function, exists := f.All.Functions[fullName]
if exists { if exists {
if function.IsExtern() { if function.IsExtern() {
@ -208,7 +214,7 @@ func (f *Function) Evaluate(expr *expression.Expression) (ssa.Value, error) {
return v, nil return v, nil
} }
return nil, errors.New(&UnknownIdentifier{Name: label}, f.File, left.Token.Position) return nil, errors.New(&UnknownIdentifier{Name: fullName}, f.File, left.Token.Position)
default: default:
if expr.Token.IsOperator() { if expr.Token.IsOperator() {

View file

@ -9,6 +9,7 @@ import (
type Compiler struct { type Compiler struct {
UniqueName string UniqueName string
Assembler asm.Assembler Assembler asm.Assembler
Steps []Step
ValueToStep map[ssa.Value]*Step ValueToStep map[ssa.Value]*Step
CPU *cpu.CPU CPU *cpu.CPU
Count Count Count Count

View file

@ -65,6 +65,12 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
} }
liveStart := i liveStart := i
_, isParam := instr.(*ssa.Parameter)
if isParam {
liveStart = 0
}
liveEnd := f.ValueToStep[users[len(users)-1]].Index liveEnd := f.ValueToStep[users[len(users)-1]].Index
instrStep := f.ValueToStep[instr] instrStep := f.ValueToStep[instr]
@ -79,12 +85,19 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
continue continue
} }
oldRegister := cpu.Register(-1)
liveParam, isParam := live.Value.(*ssa.Parameter)
if isParam {
oldRegister = f.CPU.Call[liveParam.Index]
}
for _, existing := range step.Live[:liveIndex] { for _, existing := range step.Live[:liveIndex] {
if existing.Register == -1 { if existing.Register == -1 {
continue continue
} }
if existing.Register == live.Register { if existing.Register == live.Register || existing.Register == oldRegister {
a := existing.Index a := existing.Index
b := live.Index b := live.Index
freeRegister := cpu.Register(15) freeRegister := cpu.Register(15)

View file

@ -114,9 +114,9 @@ func (f *Compiler) Exec(step *Step) {
}) })
case *ssa.Field: case *ssa.Field:
parameter := instr.Object.(*ssa.Parameter) structure := instr.Object.(*ssa.Struct)
field := instr.Field field := structure.Arguments[instr.Field.Index]
source := f.CPU.Call[parameter.Index+field.Index] source := f.ValueToStep[field].Register
if step.Register == -1 || step.Register == source { if step.Register == -1 || step.Register == source {
return return

View file

@ -13,9 +13,9 @@ func (f *Compiler) GenerateAssembly(ir ssa.IR, isLeaf bool) {
f.Assembler.Append(&asm.FunctionStart{}) f.Assembler.Append(&asm.FunctionStart{})
} }
steps := f.CreateSteps(ir) f.Steps = f.CreateSteps(ir)
for _, step := range steps { for _, step := range f.Steps {
f.Exec(&step) f.Exec(&step)
} }