This commit is contained in:
parent
c9c6b94c18
commit
3301cf5542
49 changed files with 690 additions and 262 deletions
|
@ -12,6 +12,7 @@ type BinaryOp struct {
|
|||
Left Value
|
||||
Right Value
|
||||
Op token.Kind
|
||||
Id
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
@ -42,6 +43,10 @@ func (v *BinaryOp) IsConst() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (v *BinaryOp) Debug() string {
|
||||
return fmt.Sprintf("%%%d %s %%%d", v.Left.ID(), expression.Operators[v.Op].Symbol, v.Right.ID())
|
||||
}
|
||||
|
||||
func (v *BinaryOp) String() string {
|
||||
return fmt.Sprintf("%s %s %s", v.Left, expression.Operators[v.Op].Symbol, v.Right)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ type Block struct {
|
|||
// Append adds a new instruction to the block.
|
||||
func (block *Block) Append(instr Value) Value {
|
||||
for _, dep := range instr.Dependencies() {
|
||||
dep.AddUse(instr)
|
||||
dep.AddUser(instr)
|
||||
}
|
||||
|
||||
block.Instructions = append(block.Instructions, instr)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type Bytes struct {
|
||||
Id
|
||||
Bytes []byte
|
||||
Liveness
|
||||
Source
|
||||
|
@ -31,10 +32,14 @@ func (v *Bytes) IsConst() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (v *Bytes) Debug() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *Bytes) String() string {
|
||||
return strconv.Quote(string(v.Bytes))
|
||||
}
|
||||
|
||||
func (v *Bytes) Type() types.Type {
|
||||
return types.String
|
||||
return types.CString
|
||||
}
|
|
@ -19,5 +19,5 @@ func TestBytes(t *testing.T) {
|
|||
assert.False(t, hello.Equals(one))
|
||||
assert.True(t, hello.Equals(helloDup))
|
||||
assert.Equal(t, hello.String(), "\"Hello\"")
|
||||
assert.True(t, types.Is(hello.Type(), types.String))
|
||||
assert.True(t, types.Is(hello.Type(), types.CString))
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
type Call struct {
|
||||
Id
|
||||
Arguments
|
||||
Liveness
|
||||
Source
|
||||
|
@ -27,14 +28,42 @@ func (v *Call) IsConst() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (v *Call) String() string {
|
||||
args := make([]string, 0, len(v.Arguments)-1)
|
||||
func (v *Call) Debug() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString("%")
|
||||
tmp.WriteString(strconv.Itoa(v.Arguments[0].ID()))
|
||||
tmp.WriteString("(")
|
||||
args := v.Arguments[1:]
|
||||
|
||||
for _, arg := range v.Arguments[1:] {
|
||||
args = append(args, arg.String())
|
||||
for i, arg := range args {
|
||||
tmp.WriteString("%")
|
||||
tmp.WriteString(strconv.Itoa(arg.ID()))
|
||||
|
||||
if i != len(args)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s(%s)", v.Arguments[0].String(), strings.Join(args, ", "))
|
||||
tmp.WriteString(")")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Call) String() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString(v.Arguments[0].String())
|
||||
tmp.WriteString("(")
|
||||
args := v.Arguments[1:]
|
||||
|
||||
for i, arg := range args {
|
||||
tmp.WriteString(arg.String())
|
||||
|
||||
if i != len(args)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
tmp.WriteString(")")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Call) Type() types.Type {
|
||||
|
|
|
@ -5,6 +5,8 @@ import "git.urbach.dev/cli/q/src/types"
|
|||
type Function struct {
|
||||
UniqueName string
|
||||
Typ *types.Function
|
||||
IsExtern bool
|
||||
Id
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
@ -27,6 +29,10 @@ func (v *Function) IsConst() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (v *Function) Debug() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *Function) String() string {
|
||||
return v.UniqueName
|
||||
}
|
||||
|
|
11
src/ssa/ID.go
Normal file
11
src/ssa/ID.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package ssa
|
||||
|
||||
type Id int
|
||||
|
||||
func (id Id) ID() int {
|
||||
return int(id)
|
||||
}
|
||||
|
||||
func (id *Id) SetID(newId int) {
|
||||
*id = Id(newId)
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package ssa
|
||||
|
||||
import "git.urbach.dev/cli/q/src/types"
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
// IR is a list of basic blocks.
|
||||
type IR struct {
|
||||
Blocks []*Block
|
||||
nextId int
|
||||
}
|
||||
|
||||
// AddBlock adds a new block to the function.
|
||||
|
@ -31,35 +34,29 @@ func (f *IR) Append(instr Value) Value {
|
|||
}
|
||||
}
|
||||
|
||||
instr.SetID(f.nextId)
|
||||
f.nextId++
|
||||
return f.Blocks[len(f.Blocks)-1].Append(instr)
|
||||
}
|
||||
|
||||
// AppendInt adds a new integer value to the last block.
|
||||
func (f *IR) AppendInt(x int) *Int {
|
||||
v := &Int{Int: x}
|
||||
f.Append(v)
|
||||
return v
|
||||
func (f *IR) AppendInt(x int) Value {
|
||||
return f.Append(&Int{Int: x})
|
||||
}
|
||||
|
||||
// AppendFunction adds a new function value to the last block.
|
||||
func (f *IR) AppendFunction(name string, typ *types.Function) *Function {
|
||||
v := &Function{UniqueName: name, Typ: typ}
|
||||
f.Append(v)
|
||||
return v
|
||||
func (f *IR) AppendFunction(name string, typ *types.Function, extern bool) Value {
|
||||
return f.Append(&Function{UniqueName: name, Typ: typ, IsExtern: extern})
|
||||
}
|
||||
|
||||
// AppendBytes adds a new byte slice value to the last block.
|
||||
func (f *IR) AppendBytes(s []byte) *Bytes {
|
||||
v := &Bytes{Bytes: s}
|
||||
f.Append(v)
|
||||
return v
|
||||
func (f *IR) AppendBytes(s []byte) Value {
|
||||
return f.Append(&Bytes{Bytes: s})
|
||||
}
|
||||
|
||||
// AppendString adds a new string value to the last block.
|
||||
func (f *IR) AppendString(s string) *Bytes {
|
||||
v := &Bytes{Bytes: []byte(s)}
|
||||
f.Append(v)
|
||||
return v
|
||||
func (f *IR) AppendString(s string) Value {
|
||||
return f.Append(&Bytes{Bytes: []byte(s)})
|
||||
}
|
||||
|
||||
// Values yields on each value.
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
type Int struct {
|
||||
Int int
|
||||
Id
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
@ -30,6 +31,10 @@ func (v *Int) IsConst() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (v *Int) Debug() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *Int) String() string {
|
||||
return fmt.Sprintf("%d", v.Int)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package ssa
|
||||
|
||||
type Liveness struct {
|
||||
alive int
|
||||
users []Value
|
||||
}
|
||||
|
||||
func (v *Liveness) AddUse(user Value) {
|
||||
v.alive++
|
||||
func (v *Liveness) AddUser(user Value) {
|
||||
v.users = append(v.users, user)
|
||||
}
|
||||
|
||||
func (v *Liveness) Alive() int {
|
||||
return v.alive
|
||||
func (v *Liveness) CountUsers() int {
|
||||
return len(v.users)
|
||||
}
|
6
src/ssa/NoLiveness.go
Normal file
6
src/ssa/NoLiveness.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package ssa
|
||||
|
||||
type NoLiveness struct{}
|
||||
|
||||
func (a *NoLiveness) AddUser(user Value) { panic("value does not have liveness") }
|
||||
func (a *NoLiveness) CountUsers() int { return 0 }
|
|
@ -10,6 +10,7 @@ type Parameter struct {
|
|||
Index uint8
|
||||
Name string
|
||||
Typ types.Type
|
||||
Id
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
@ -32,6 +33,10 @@ func (v *Parameter) IsConst() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (v *Parameter) Debug() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *Parameter) String() string {
|
||||
return fmt.Sprintf("in[%d]", v.Index)
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
type Return struct {
|
||||
Id
|
||||
Arguments
|
||||
Source
|
||||
NoLiveness
|
||||
}
|
||||
|
||||
func (a *Return) AddUse(user Value) { panic("return is not a value") }
|
||||
func (a *Return) Alive() int { return 0 }
|
||||
|
||||
func (a *Return) Equals(v Value) bool {
|
||||
b, sameType := v.(*Return)
|
||||
|
||||
|
@ -39,18 +38,43 @@ func (v *Return) IsConst() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (v *Return) Debug() string {
|
||||
if len(v.Arguments) == 0 {
|
||||
return "return"
|
||||
}
|
||||
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString("return ")
|
||||
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString("%")
|
||||
tmp.WriteString(strconv.Itoa(arg.ID()))
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Return) String() string {
|
||||
if len(v.Arguments) == 0 {
|
||||
return "return"
|
||||
}
|
||||
|
||||
args := make([]string, 0, len(v.Arguments))
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString("return ")
|
||||
|
||||
for _, arg := range v.Arguments {
|
||||
args = append(args, arg.String())
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString(arg.String())
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("return %s", strings.Join(args, ", "))
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Return) Type() types.Type {
|
||||
|
|
|
@ -4,10 +4,14 @@ import "git.urbach.dev/cli/q/src/token"
|
|||
|
||||
type Source token.List
|
||||
|
||||
func (v Source) Start() token.Position {
|
||||
return v[0].Position
|
||||
}
|
||||
|
||||
func (v Source) End() token.Position {
|
||||
return v[len(v)-1].End()
|
||||
}
|
||||
|
||||
func (v *Source) SetSource(source token.List) {
|
||||
*v = Source(source)
|
||||
}
|
||||
|
||||
func (v Source) Start() token.Position {
|
||||
return v[0].Position
|
||||
}
|
69
src/ssa/Struct.go
Normal file
69
src/ssa/Struct.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
type Struct struct {
|
||||
Typ *types.Struct
|
||||
Id
|
||||
Arguments
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
||||
func (a *Struct) Equals(v Value) bool {
|
||||
b, sameType := v.(*Struct)
|
||||
|
||||
if !sameType {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.Arguments.Equals(b.Arguments)
|
||||
}
|
||||
|
||||
func (v *Struct) IsConst() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *Struct) Debug() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString(v.Typ.Name())
|
||||
tmp.WriteString("{")
|
||||
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString("%")
|
||||
tmp.WriteString(strconv.Itoa(arg.ID()))
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
tmp.WriteString("}")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Struct) String() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString(v.Typ.Name())
|
||||
tmp.WriteString("{")
|
||||
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString(arg.String())
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
tmp.WriteString("}")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Struct) Type() types.Type {
|
||||
return v.Typ
|
||||
}
|
45
src/ssa/StructField.go
Normal file
45
src/ssa/StructField.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
type StructField struct {
|
||||
Struct Value
|
||||
Field *types.Field
|
||||
Id
|
||||
Liveness
|
||||
Source
|
||||
}
|
||||
|
||||
func (v *StructField) Dependencies() []Value {
|
||||
return []Value{v.Struct}
|
||||
}
|
||||
|
||||
func (a *StructField) Equals(v Value) bool {
|
||||
b, sameType := v.(*StructField)
|
||||
|
||||
if !sameType {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.Field == b.Field
|
||||
}
|
||||
|
||||
func (v *StructField) IsConst() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *StructField) Debug() string {
|
||||
return fmt.Sprintf("%%%d.%s", v.Struct.ID(), v.Field)
|
||||
}
|
||||
|
||||
func (v *StructField) String() string {
|
||||
return fmt.Sprintf("%s.%s", v.Struct, v.Field)
|
||||
}
|
||||
|
||||
func (v *StructField) Type() types.Type {
|
||||
return v.Field.Type
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
type Syscall struct {
|
||||
Id
|
||||
Arguments
|
||||
Liveness
|
||||
Source
|
||||
|
@ -27,14 +28,37 @@ func (v *Syscall) IsConst() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (v *Syscall) String() string {
|
||||
args := make([]string, 0, len(v.Arguments))
|
||||
func (v *Syscall) Debug() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString("syscall(")
|
||||
|
||||
for _, arg := range v.Arguments {
|
||||
args = append(args, arg.String())
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString("%")
|
||||
tmp.WriteString(strconv.Itoa(arg.ID()))
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("syscall(%s)", strings.Join(args, ", "))
|
||||
tmp.WriteString(")")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Syscall) String() string {
|
||||
tmp := strings.Builder{}
|
||||
tmp.WriteString("syscall(")
|
||||
|
||||
for i, arg := range v.Arguments {
|
||||
tmp.WriteString(arg.String())
|
||||
|
||||
if i != len(v.Arguments)-1 {
|
||||
tmp.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
tmp.WriteString(")")
|
||||
return tmp.String()
|
||||
}
|
||||
|
||||
func (v *Syscall) Type() types.Type {
|
||||
|
|
|
@ -6,13 +6,24 @@ import (
|
|||
)
|
||||
|
||||
type Value interface {
|
||||
AddUse(Value)
|
||||
Alive() int
|
||||
Dependencies() []Value
|
||||
End() token.Position
|
||||
Equals(Value) bool
|
||||
// Essentials
|
||||
Debug() string
|
||||
ID() int
|
||||
IsConst() bool
|
||||
SetID(int)
|
||||
String() string
|
||||
Start() token.Position
|
||||
Type() types.Type
|
||||
|
||||
// Arguments
|
||||
Dependencies() []Value
|
||||
Equals(Value) bool
|
||||
|
||||
// Liveness
|
||||
AddUser(Value)
|
||||
CountUsers() int
|
||||
|
||||
// Source
|
||||
SetSource(token.List)
|
||||
Start() token.Position
|
||||
End() token.Position
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue