Added ssa package
All checks were successful
/ test (push) Successful in 22s

This commit is contained in:
Eduard Urbach 2025-06-20 21:05:49 +02:00
parent ec300c9a70
commit 89f375f4fc
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
8 changed files with 234 additions and 0 deletions

View file

@ -4,11 +4,13 @@ import (
"fmt"
"git.urbach.dev/cli/q/src/fs"
"git.urbach.dev/cli/q/src/ssa"
"git.urbach.dev/cli/q/src/token"
)
// Function is the smallest unit of code.
type Function struct {
ssa.Function
Name string
UniqueName string
File *fs.File

11
src/ssa/Block.go Normal file
View file

@ -0,0 +1,11 @@
package ssa
type Block struct {
Entry []*Block
Instructions []Instruction
Exit []*Block
}
func (b *Block) Append(instr Instruction) {
b.Instructions = append(b.Instructions, instr)
}

5
src/ssa/Function.go Normal file
View file

@ -0,0 +1,5 @@
package ssa
type Function struct {
Blocks []*Block
}

3
src/ssa/Index.go Normal file
View file

@ -0,0 +1,3 @@
package ssa
type Index = uint16

11
src/ssa/Instruction.go Normal file
View file

@ -0,0 +1,11 @@
package ssa
// Instruction is a "fat struct" for performance reasons.
// It contains all the fields necessary to represent all instruction types.
type Instruction struct {
Type Type
Parameters []Index
Int int64
Float float64
String string
}

30
src/ssa/Type.go Normal file
View file

@ -0,0 +1,30 @@
package ssa
type Type byte
const (
None Type = iota
// Values
Int
Float
String
// Binary
Add
Sub
Mul
Div
Mod
// Bitwise
And
Or
Xor
Shl
Shr
// Special
Call
Phi
)

158
src/ssa/bench_test.go Normal file
View file

@ -0,0 +1,158 @@
package ssa_test
import (
"os"
"runtime/debug"
"testing"
"git.urbach.dev/go/assert"
)
const n = 100
type FatStruct struct {
Type byte
A int
B int
C int
D int
E int
F int
G int
}
type Instruction interface{}
type BinaryInstruction struct {
A int
B int
}
type OtherInstruction struct {
C int
D int
E int
F int
G int
}
func TestMain(m *testing.M) {
debug.SetGCPercent(-1)
os.Exit(m.Run())
}
func BenchmarkFatStructRaw(b *testing.B) {
for b.Loop() {
entries := make([]FatStruct, 0, n)
for i := range n {
entries = append(entries, FatStruct{
Type: byte(i % 2),
A: i,
B: i,
})
}
count := 0
for _, entry := range entries {
switch entry.Type {
case 0:
count++
case 1:
}
}
assert.Equal(b, count, n/2)
}
}
func BenchmarkFatStructPtr(b *testing.B) {
for b.Loop() {
entries := make([]*FatStruct, 0, n)
for i := range n {
entries = append(entries, &FatStruct{
Type: byte(i % 2),
A: i,
B: i,
})
}
count := 0
for _, entry := range entries {
switch entry.Type {
case 0:
count++
case 1:
}
}
assert.Equal(b, count, n/2)
}
}
func BenchmarkInterfaceRaw(b *testing.B) {
for b.Loop() {
entries := make([]Instruction, 0, n)
for i := range n {
if i%2 == 0 {
entries = append(entries, BinaryInstruction{
A: i,
B: i,
})
} else {
entries = append(entries, OtherInstruction{
C: i,
D: i,
})
}
}
count := 0
for _, entry := range entries {
switch entry.(type) {
case BinaryInstruction:
count++
case OtherInstruction:
}
}
assert.Equal(b, count, n/2)
}
}
func BenchmarkInterfacePtr(b *testing.B) {
for b.Loop() {
entries := make([]Instruction, 0, n)
for i := range n {
if i%2 == 0 {
entries = append(entries, &BinaryInstruction{
A: i,
B: i,
})
} else {
entries = append(entries, &OtherInstruction{
C: i,
D: i,
})
}
}
count := 0
for _, entry := range entries {
switch entry.(type) {
case *BinaryInstruction:
count++
case *OtherInstruction:
}
}
assert.Equal(b, count, n/2)
}
}

14
src/ssa/ssa_test.go Normal file
View file

@ -0,0 +1,14 @@
package ssa_test
import (
"testing"
"git.urbach.dev/cli/q/src/ssa"
)
func TestBlock(t *testing.T) {
block := &ssa.Block{}
block.Append(ssa.Instruction{Type: ssa.Int, Int: 1})
block.Append(ssa.Instruction{Type: ssa.Int, Int: 2})
block.Append(ssa.Instruction{Type: ssa.Add, Parameters: []ssa.Index{0, 1}})
}