diff --git a/src/ssa/Block.go b/src/ssa/Block.go index 30d854b..32ac6dd 100644 --- a/src/ssa/Block.go +++ b/src/ssa/Block.go @@ -1,11 +1,12 @@ package ssa +// Block is a list of instructions that can be targeted in branches. type Block struct { - Entry []*Block 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) + return &b.Instructions[len(b.Instructions)-1] } \ No newline at end of file diff --git a/src/ssa/Function.go b/src/ssa/Function.go index 1831743..d5df02a 100644 --- a/src/ssa/Function.go +++ b/src/ssa/Function.go @@ -1,5 +1,13 @@ package ssa +// Function is a list of basic blocks. type Function struct { 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 } \ No newline at end of file diff --git a/src/ssa/Index.go b/src/ssa/Index.go deleted file mode 100644 index 9f27529..0000000 --- a/src/ssa/Index.go +++ /dev/null @@ -1,3 +0,0 @@ -package ssa - -type Index = uint16 \ No newline at end of file diff --git a/src/ssa/Instruction.go b/src/ssa/Instruction.go index dcccd4a..76e8e38 100644 --- a/src/ssa/Instruction.go +++ b/src/ssa/Instruction.go @@ -1,11 +1,28 @@ 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. type Instruction struct { - Type Type - Parameters []Index - Int int64 - Float float64 - String string + Type Type + Args []*Instruction + Int int64 + Float float64 + 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 "" + } } \ No newline at end of file diff --git a/src/ssa/Type.go b/src/ssa/Type.go index c1aba45..1ea82b1 100644 --- a/src/ssa/Type.go +++ b/src/ssa/Type.go @@ -1,5 +1,6 @@ package ssa +// Type represents the instruction type. type Type byte const ( @@ -24,6 +25,10 @@ const ( Shl Shr + // Branch + If + Jump + // Special Call Phi diff --git a/src/ssa/bench_test.go b/src/ssa/bench_test.go index 03799f3..d959299 100644 --- a/src/ssa/bench_test.go +++ b/src/ssa/bench_test.go @@ -8,6 +8,8 @@ import ( "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 type FatStruct struct { diff --git a/src/ssa/ssa_test.go b/src/ssa/ssa_test.go index 8b74df0..7455424 100644 --- a/src/ssa/ssa_test.go +++ b/src/ssa/ssa_test.go @@ -4,11 +4,19 @@ import ( "testing" "git.urbach.dev/cli/q/src/ssa" + "git.urbach.dev/go/assert" ) 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}}) + f := ssa.Function{} + block := f.AddBlock() + a := block.Append(ssa.Instruction{Type: ssa.Int, Int: 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(), "") } \ No newline at end of file