Skip to content

Commit

Permalink
Add ssax package.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Oct 22, 2024
1 parent be72680 commit bb5ab51
Show file tree
Hide file tree
Showing 10 changed files with 382 additions and 210 deletions.
100 changes: 0 additions & 100 deletions config/staticconfig/block.go

This file was deleted.

7 changes: 4 additions & 3 deletions config/staticconfig/configurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/dogmatiq/enginekit/config"
"github.com/dogmatiq/enginekit/config/internal/configbuilder"
"github.com/dogmatiq/enginekit/config/staticconfig/internal/ssax"
"golang.org/x/tools/go/ssa"
)

Expand Down Expand Up @@ -74,8 +75,8 @@ func emitConfigurerCallsInFunc(
return true
}

for block := range walkReachable(fn.Blocks[0]) {
for _, inst := range block.Instrs {
for b := range ssax.WalkDown(fn.Blocks[0]) {
for _, inst := range b.Instrs {
if !emitConfigurerCallsInInstruction(ctx, inst, yield) {
return false
}
Expand Down Expand Up @@ -108,7 +109,7 @@ func emitConfigurerCallsInCallInstruction(
if com.IsInvoke() && ctx.IsConfigurer(com.Value) {
// We've found a direct call to a method on the configurer.
var f config.Fidelity
if isConditional(call.Block()) {
if !ssax.IsUnconditional(call.Block()) {
f |= config.Speculative
}

Expand Down
1 change: 1 addition & 0 deletions config/staticconfig/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/dogmatiq/enginekit/config"
"github.com/dogmatiq/enginekit/config/internal/configbuilder"
"github.com/dogmatiq/enginekit/config/staticconfig/internal/ssax"

Check failure on line 8 in config/staticconfig/handler.go

View workflow job for this annotation

GitHub Actions / Shared / Go

"github.com/dogmatiq/enginekit/config/staticconfig/internal/ssax" imported and not used

Check failure on line 8 in config/staticconfig/handler.go

View workflow job for this annotation

GitHub Actions / Shared / Go

"github.com/dogmatiq/enginekit/config/staticconfig/internal/ssax" imported and not used
"github.com/dogmatiq/enginekit/internal/typename"
"golang.org/x/tools/go/ssa"
)
Expand Down
11 changes: 5 additions & 6 deletions config/staticconfig/identity.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package staticconfig

import (
"go/constant"

"github.com/dogmatiq/enginekit/config"
"github.com/dogmatiq/enginekit/config/internal/configbuilder"
"github.com/dogmatiq/enginekit/config/staticconfig/internal/ssax"
)

func analyzeIdentityCall(
Expand All @@ -14,14 +13,14 @@ func analyzeIdentityCall(
b.Identity(func(b *configbuilder.IdentityBuilder) {
b.UpdateFidelity(call.Fidelity)

if name := staticValue(call.Args[0]); name != nil {
b.SetName(constant.StringVal(name))
if name, ok := ssax.AsString(call.Args[0]).TryGet(); ok {
b.SetName(name)
} else {
b.UpdateFidelity(config.Incomplete)
}

if key := staticValue(call.Args[1]); key != nil {
b.SetKey(constant.StringVal(key))
if key, ok := ssax.AsString(call.Args[1]).TryGet(); ok {
b.SetKey(key)
} else {
b.UpdateFidelity(config.Incomplete)
}
Expand Down
37 changes: 37 additions & 0 deletions config/staticconfig/internal/ssax/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ssax

import (
"iter"

"github.com/dogmatiq/enginekit/optional"
"golang.org/x/tools/go/ssa"
)

// Terminator returns the final "transfer of control" instruction in the given
// block.
//
// If the block does not contain any instructions (as is the case for external
// functions), or the terminator instruction is not of type T, ok is false.
//
// The instruction is always [ssa.If], [ssa.Jump], [ssa.Return], or [ssa.Panic].
func Terminator[T ssa.Instruction](b *ssa.BasicBlock) optional.Optional[T] {
return optional.As[T](optional.Last(b.Instrs))
}

// InstructionsBefore yields all instructions in the block that precede the
// given instruction.
//
// It yields all instructions if inst is not in b.
func InstructionsBefore(b *ssa.BasicBlock, inst ssa.Instruction) iter.Seq[ssa.Instruction] {
return func(yield func(ssa.Instruction) bool) {
for _, x := range b.Instrs {
if x == inst {
return
}

if !yield(x) {
return
}
}
}
}
63 changes: 63 additions & 0 deletions config/staticconfig/internal/ssax/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ssax

import (
"go/constant"
"math"

"github.com/dogmatiq/enginekit/optional"
"golang.org/x/tools/go/ssa"
)

// Const returns the singlar constant value of v if possible.
func Const(v ssa.Value) optional.Optional[constant.Value] {
return optional.TryTransform(
StaticValue(v),
func(v ssa.Value) (constant.Value, bool) {
if c, ok := v.(*ssa.Const); ok {
return c.Value, true
}
return nil, false
},
)
}

// AsString returns the singular constant string value of v if possible.
func AsString(v ssa.Value) optional.Optional[string] {
return constAs(constant.StringVal, v)
}

// AsBool returns the singular constant boolean value of v if possible.
func AsBool(v ssa.Value) optional.Optional[bool] {
return constAs(constant.BoolVal, v)
}

// AsInt returns the singular constant integer value of v if possible.
func AsInt(v ssa.Value) optional.Optional[int] {
return optional.TryTransform(
Const(v),
func(c constant.Value) (_ int, ok bool) {
i, ok := constant.Int64Val(c)
return int(i), ok && i >= math.MinInt && i <= math.MaxInt
},
)
}

// constAsX returns the constant value of v, converted to type T by fn.
func constAs[T any](
fn func(constant.Value) T,
v ssa.Value,
) optional.Optional[T] {
return optional.TryTransform(
Const(v),
func(c constant.Value) (_ T, ok bool) {
defer func() {
if recover() != nil {
// ignore panics about type conversion
ok = false
}
}()

return fn(c), true
},
)
}
2 changes: 2 additions & 0 deletions config/staticconfig/internal/ssax/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package ssax contains general SSA-related utilities.
package ssax
Loading

0 comments on commit bb5ab51

Please sign in to comment.