Skip to content

Commit

Permalink
interp: limit max instructions per function
Browse files Browse the repository at this point in the history
  • Loading branch information
kenbell committed Sep 22, 2023
1 parent a73eac2 commit ced1fa6
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 8 deletions.
4 changes: 2 additions & 2 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
if pkgInit.IsNil() {
panic("init not found for " + pkg.Pkg.Path())
}
err := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.Options.InterpMaxDepth, config.DumpSSA())
err := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.Options.InterpMaxDepth, config.Options.InterpMaxInstr, config.DumpSSA())
if err != nil {
return err
}
Expand Down Expand Up @@ -1043,7 +1043,7 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
// needed to convert a program to its final form. Some transformations are not
// optional and must be run as the compiler expects them to run.
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
err := interp.Run(mod, config.Options.InterpTimeout, config.Options.InterpMaxDepth, config.DumpSSA())
err := interp.Run(mod, config.Options.InterpTimeout, config.Options.InterpMaxDepth, config.Options.InterpMaxInstr, config.DumpSSA())
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions compileopts/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Options struct {
Work bool // -work flag to print temporary build directory
InterpTimeout time.Duration
InterpMaxDepth int
InterpMaxInstr int
PrintIR bool
DumpSSA bool
VerifyIR bool
Expand Down
12 changes: 7 additions & 5 deletions interp/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ type runner struct {
start time.Time
timeout time.Duration
maxDepth int
maxInstr int
callsExecuted uint64
}

func newRunner(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool) *runner {
func newRunner(mod llvm.Module, timeout time.Duration, maxDepth int, maxInstr int, debug bool) *runner {
r := runner{
mod: mod,
targetData: llvm.NewTargetData(mod.DataLayout()),
Expand All @@ -46,6 +47,7 @@ func newRunner(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool)
start: time.Now(),
timeout: timeout,
maxDepth: maxDepth,
maxInstr: maxInstr,
}
r.pointerSize = uint32(r.targetData.PointerSize())
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
Expand All @@ -62,8 +64,8 @@ func (r *runner) dispose() {

// Run evaluates runtime.initAll function as much as possible at compile time.
// Set debug to true if it should print output while running.
func Run(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool) error {
r := newRunner(mod, timeout, maxDepth, debug)
func Run(mod llvm.Module, timeout time.Duration, maxDepth int, maxInstr int, debug bool) error {
r := newRunner(mod, timeout, maxDepth, maxInstr, debug)
defer r.dispose()

initAll := mod.NamedFunction("runtime.initAll")
Expand Down Expand Up @@ -203,10 +205,10 @@ func Run(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool) error

// RunFunc evaluates a single package initializer at compile time.
// Set debug to true if it should print output while running.
func RunFunc(fn llvm.Value, timeout time.Duration, maxDepth int, debug bool) error {
func RunFunc(fn llvm.Value, timeout time.Duration, maxDepth int, maxInstr int, debug bool) error {
// Create and initialize *runner object.
mod := fn.GlobalParent()
r := newRunner(mod, timeout, maxDepth, debug)
r := newRunner(mod, timeout, maxDepth, maxInstr, debug)
defer r.dispose()
initName := fn.Name()
if !strings.HasSuffix(initName, ".init") {
Expand Down
2 changes: 1 addition & 1 deletion interp/interp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) {
defer mod.Dispose()

// Perform the transform.
err = Run(mod, 10*time.Minute, 10, false)
err = Run(mod, 10*time.Minute, 10, 0, false)
if err != nil {
if err, match := err.(*Error); match {
println(err.Error())
Expand Down
7 changes: 7 additions & 0 deletions interp/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, depth
lastBB := -1 // last basic block is undefined, only defined after a branch
var operands []value
startRTInsts := len(mem.instructions)
instCount := 0
for instIndex := 0; instIndex < len(bb.instructions); instIndex++ {
instCount++
if r.maxInstr > 0 && instCount > r.maxInstr {
fmt.Printf("interp: excess instructions evaluated in %v\n", fn.name)
return nil, mem, r.errorAt(fn.blocks[0].instructions[0], errDepthExceeded)
}

if instIndex == 0 {
if r.maxDepth > 0 && depth >= r.maxDepth {
fmt.Printf("interp: depth exceeded in %v\n", fn.name)
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,7 @@ func main() {
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
interpMaxDepth := flag.Int("interp-maxdepth", 0, "interp optimization max depth (default 0=disabled)")
interpMaxInstr := flag.Int("interp-maxinstr", 100_000, "limit interp optimization max instructions (0=disabled)")
var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file")
Expand Down Expand Up @@ -1530,6 +1531,7 @@ func main() {
Work: *work,
InterpTimeout: *interpTimeout,
InterpMaxDepth: *interpMaxDepth,
InterpMaxInstr: *interpMaxInstr,
PrintIR: *printIR,
DumpSSA: *dumpSSA,
VerifyIR: *verifyIR,
Expand Down

0 comments on commit ced1fa6

Please sign in to comment.