This commit is contained in:
parent
89f375f4fc
commit
14bccadd0f
7 changed files with 54 additions and 16 deletions
|
@ -1,11 +1,12 @@
|
||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
|
// Block is a list of instructions that can be targeted in branches.
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Entry []*Block
|
|
||||||
Instructions []Instruction
|
Instructions []Instruction
|
||||||
Exit []*Block
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) Append(instr Instruction) {
|
// Append adds a new instruction to the block.
|
||||||
|
func (b *Block) Append(instr Instruction) *Instruction {
|
||||||
b.Instructions = append(b.Instructions, instr)
|
b.Instructions = append(b.Instructions, instr)
|
||||||
|
return &b.Instructions[len(b.Instructions)-1]
|
||||||
}
|
}
|
|
@ -1,5 +1,13 @@
|
||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
|
// Function is a list of basic blocks.
|
||||||
type Function struct {
|
type Function struct {
|
||||||
Blocks []*Block
|
Blocks []*Block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddBlock adds a new block to the function.
|
||||||
|
func (f *Function) AddBlock() *Block {
|
||||||
|
block := &Block{}
|
||||||
|
f.Blocks = append(f.Blocks, block)
|
||||||
|
return block
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
package ssa
|
|
||||||
|
|
||||||
type Index = uint16
|
|
|
@ -1,11 +1,28 @@
|
||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
// Instruction is a "fat struct" for performance reasons.
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Instruction is a single instruction in a basic block.
|
||||||
|
// It is implemented as a "fat struct" for performance reasons.
|
||||||
// It contains all the fields necessary to represent all instruction types.
|
// It contains all the fields necessary to represent all instruction types.
|
||||||
type Instruction struct {
|
type Instruction struct {
|
||||||
Type Type
|
Type Type
|
||||||
Parameters []Index
|
Args []*Instruction
|
||||||
Int int64
|
Int int64
|
||||||
Float float64
|
Float float64
|
||||||
String string
|
Text string
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable representation of the instruction.
|
||||||
|
func (i *Instruction) String() string {
|
||||||
|
switch i.Type {
|
||||||
|
case Int:
|
||||||
|
return fmt.Sprintf("%d", i.Int)
|
||||||
|
case Add:
|
||||||
|
return fmt.Sprintf("%s + %s", i.Args[0], i.Args[1])
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
|
// Type represents the instruction type.
|
||||||
type Type byte
|
type Type byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -24,6 +25,10 @@ const (
|
||||||
Shl
|
Shl
|
||||||
Shr
|
Shr
|
||||||
|
|
||||||
|
// Branch
|
||||||
|
If
|
||||||
|
Jump
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
Call
|
Call
|
||||||
Phi
|
Phi
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"git.urbach.dev/go/assert"
|
"git.urbach.dev/go/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This benchmark compares the performance of fat structs and interfaces.
|
||||||
|
// It allocates `n` objects where `n` must be divisible by 2.
|
||||||
const n = 100
|
const n = 100
|
||||||
|
|
||||||
type FatStruct struct {
|
type FatStruct struct {
|
||||||
|
|
|
@ -4,11 +4,19 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/ssa"
|
"git.urbach.dev/cli/q/src/ssa"
|
||||||
|
"git.urbach.dev/go/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBlock(t *testing.T) {
|
func TestBlock(t *testing.T) {
|
||||||
block := &ssa.Block{}
|
f := ssa.Function{}
|
||||||
block.Append(ssa.Instruction{Type: ssa.Int, Int: 1})
|
block := f.AddBlock()
|
||||||
block.Append(ssa.Instruction{Type: ssa.Int, Int: 2})
|
a := block.Append(ssa.Instruction{Type: ssa.Int, Int: 1})
|
||||||
block.Append(ssa.Instruction{Type: ssa.Add, Parameters: []ssa.Index{0, 1}})
|
b := block.Append(ssa.Instruction{Type: ssa.Int, Int: 2})
|
||||||
|
c := block.Append(ssa.Instruction{Type: ssa.Add, Args: []*ssa.Instruction{a, b}})
|
||||||
|
assert.Equal(t, c.String(), "1 + 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInvalidInstruction(t *testing.T) {
|
||||||
|
instr := ssa.Instruction{}
|
||||||
|
assert.Equal(t, instr.String(), "")
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue