mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-18 19:44:00 +00:00
interp: limit max instructions per function
This commit is contained in:
+2
-2
@@ -446,7 +446,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
if pkgInit.IsNil() {
|
if pkgInit.IsNil() {
|
||||||
panic("init not found for " + pkg.Pkg.Path())
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -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
|
// 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.
|
// optional and must be run as the compiler expects them to run.
|
||||||
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Options struct {
|
|||||||
Work bool // -work flag to print temporary build directory
|
Work bool // -work flag to print temporary build directory
|
||||||
InterpTimeout time.Duration
|
InterpTimeout time.Duration
|
||||||
InterpMaxDepth int
|
InterpMaxDepth int
|
||||||
|
InterpMaxInstr int
|
||||||
PrintIR bool
|
PrintIR bool
|
||||||
DumpSSA bool
|
DumpSSA bool
|
||||||
VerifyIR bool
|
VerifyIR bool
|
||||||
|
|||||||
+7
-5
@@ -32,10 +32,11 @@ type runner struct {
|
|||||||
start time.Time
|
start time.Time
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
maxDepth int
|
maxDepth int
|
||||||
|
maxInstr int
|
||||||
callsExecuted uint64
|
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{
|
r := runner{
|
||||||
mod: mod,
|
mod: mod,
|
||||||
targetData: llvm.NewTargetData(mod.DataLayout()),
|
targetData: llvm.NewTargetData(mod.DataLayout()),
|
||||||
@@ -46,6 +47,7 @@ func newRunner(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool)
|
|||||||
start: time.Now(),
|
start: time.Now(),
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
maxDepth: maxDepth,
|
maxDepth: maxDepth,
|
||||||
|
maxInstr: maxInstr,
|
||||||
}
|
}
|
||||||
r.pointerSize = uint32(r.targetData.PointerSize())
|
r.pointerSize = uint32(r.targetData.PointerSize())
|
||||||
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||||
@@ -62,8 +64,8 @@ func (r *runner) dispose() {
|
|||||||
|
|
||||||
// Run evaluates runtime.initAll function as much as possible at compile time.
|
// Run evaluates runtime.initAll function as much as possible at compile time.
|
||||||
// Set debug to true if it should print output while running.
|
// Set debug to true if it should print output while running.
|
||||||
func Run(mod llvm.Module, timeout time.Duration, maxDepth int, debug bool) error {
|
func Run(mod llvm.Module, timeout time.Duration, maxDepth int, maxInstr int, debug bool) error {
|
||||||
r := newRunner(mod, timeout, maxDepth, debug)
|
r := newRunner(mod, timeout, maxDepth, maxInstr, debug)
|
||||||
defer r.dispose()
|
defer r.dispose()
|
||||||
|
|
||||||
initAll := mod.NamedFunction("runtime.initAll")
|
initAll := mod.NamedFunction("runtime.initAll")
|
||||||
@@ -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.
|
// RunFunc evaluates a single package initializer at compile time.
|
||||||
// Set debug to true if it should print output while running.
|
// 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.
|
// Create and initialize *runner object.
|
||||||
mod := fn.GlobalParent()
|
mod := fn.GlobalParent()
|
||||||
r := newRunner(mod, timeout, maxDepth, debug)
|
r := newRunner(mod, timeout, maxDepth, maxInstr, debug)
|
||||||
defer r.dispose()
|
defer r.dispose()
|
||||||
initName := fn.Name()
|
initName := fn.Name()
|
||||||
if !strings.HasSuffix(initName, ".init") {
|
if !strings.HasSuffix(initName, ".init") {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) {
|
|||||||
defer mod.Dispose()
|
defer mod.Dispose()
|
||||||
|
|
||||||
// Perform the transform.
|
// 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 != nil {
|
||||||
if err, match := err.(*Error); match {
|
if err, match := err.(*Error); match {
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
|
|||||||
@@ -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
|
lastBB := -1 // last basic block is undefined, only defined after a branch
|
||||||
var operands []value
|
var operands []value
|
||||||
startRTInsts := len(mem.instructions)
|
startRTInsts := len(mem.instructions)
|
||||||
|
instCount := 0
|
||||||
for instIndex := 0; instIndex < len(bb.instructions); instIndex++ {
|
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 instIndex == 0 {
|
||||||
if r.maxDepth > 0 && depth >= r.maxDepth {
|
if r.maxDepth > 0 && depth >= r.maxDepth {
|
||||||
fmt.Printf("interp: depth exceeded in %v\n", fn.name)
|
fmt.Printf("interp: depth exceeded in %v\n", fn.name)
|
||||||
|
|||||||
@@ -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")
|
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")
|
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)")
|
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
|
var tags buildutil.TagsFlag
|
||||||
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||||
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
||||||
@@ -1530,6 +1531,7 @@ func main() {
|
|||||||
Work: *work,
|
Work: *work,
|
||||||
InterpTimeout: *interpTimeout,
|
InterpTimeout: *interpTimeout,
|
||||||
InterpMaxDepth: *interpMaxDepth,
|
InterpMaxDepth: *interpMaxDepth,
|
||||||
|
InterpMaxInstr: *interpMaxInstr,
|
||||||
PrintIR: *printIR,
|
PrintIR: *printIR,
|
||||||
DumpSSA: *dumpSSA,
|
DumpSSA: *dumpSSA,
|
||||||
VerifyIR: *verifyIR,
|
VerifyIR: *verifyIR,
|
||||||
|
|||||||
Reference in New Issue
Block a user