This commit is contained in:
parent
ec300c9a70
commit
89f375f4fc
8 changed files with 234 additions and 0 deletions
|
@ -4,11 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/fs"
|
"git.urbach.dev/cli/q/src/fs"
|
||||||
|
"git.urbach.dev/cli/q/src/ssa"
|
||||||
"git.urbach.dev/cli/q/src/token"
|
"git.urbach.dev/cli/q/src/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Function is the smallest unit of code.
|
// Function is the smallest unit of code.
|
||||||
type Function struct {
|
type Function struct {
|
||||||
|
ssa.Function
|
||||||
Name string
|
Name string
|
||||||
UniqueName string
|
UniqueName string
|
||||||
File *fs.File
|
File *fs.File
|
||||||
|
|
11
src/ssa/Block.go
Normal file
11
src/ssa/Block.go
Normal 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
5
src/ssa/Function.go
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package ssa
|
||||||
|
|
||||||
|
type Function struct {
|
||||||
|
Blocks []*Block
|
||||||
|
}
|
3
src/ssa/Index.go
Normal file
3
src/ssa/Index.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package ssa
|
||||||
|
|
||||||
|
type Index = uint16
|
11
src/ssa/Instruction.go
Normal file
11
src/ssa/Instruction.go
Normal 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
30
src/ssa/Type.go
Normal 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
158
src/ssa/bench_test.go
Normal 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
14
src/ssa/ssa_test.go
Normal 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}})
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue