Example #1
0
func run(t *testing.T, dir, input string) bool {
	fmt.Printf("Input: %s\n", input)

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		inputs = append(inputs, dir+i)
	}

	b := ssa.NewBuilder(&ssa.Context{
		Mode:   ssa.SanityCheckFunctions,
		Loader: ssa.MakeGoBuildLoader(nil),
	})
	files, err := ssa.ParseFiles(b.Prog.Files, ".", inputs...)
	if err != nil {
		t.Errorf("ssa.ParseFiles(%s) failed: %s", inputs, err.Error())
		return false
	}

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println("FAIL")
			fmt.Println(hint)
		} else {
			fmt.Println("PASS")
		}
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go run exp/ssa/ssadump.go -build=CFP %s\n", input)
	mainpkg, err := b.CreatePackage("main", files)
	if err != nil {
		t.Errorf("ssa.Builder.CreatePackage(%s) failed: %s", inputs, err.Error())

		return false
	}

	b.BuildAllPackages()
	b = nil // discard Builder

	hint = fmt.Sprintf("To trace execution, run:\n%% go run exp/ssa/ssadump.go -build=C -run --interp=T %s\n", input)
	if exitCode := interp.Interpret(mainpkg, 0, inputs[0], []string{}); exitCode != 0 {
		t.Errorf("interp.Interpret(%s) exited with code %d, want zero", inputs, exitCode)
		return false
	}

	hint = "" // call off the hounds
	return true
}
Example #2
0
func main() {
	flag.Parse()
	args := flag.Args()

	var mode ssa.BuilderMode
	for _, c := range *buildFlag {
		switch c {
		case 'P':
			mode |= ssa.LogPackages | ssa.BuildSerially
		case 'F':
			mode |= ssa.LogFunctions | ssa.BuildSerially
		case 'S':
			mode |= ssa.LogSource | ssa.BuildSerially
		case 'C':
			mode |= ssa.SanityCheckFunctions
		case 'N':
			mode |= ssa.NaiveForm
		case 'G':
			mode |= ssa.UseGCImporter
		case 'L':
			mode |= ssa.BuildSerially
		default:
			log.Fatalf("Unknown -build option: '%c'.", c)
		}
	}

	var interpMode interp.Mode
	for _, c := range *interpFlag {
		switch c {
		case 'T':
			interpMode |= interp.EnableTracing
		case 'R':
			interpMode |= interp.DisableRecover
		default:
			log.Fatalf("Unknown -interp option: '%c'.", c)
		}
	}

	if len(args) == 0 {
		fmt.Fprint(os.Stderr, usage)
		os.Exit(1)
	}

	// Profiling support.
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	context := &ssa.Context{
		Mode:   mode,
		Loader: ssa.MakeGoBuildLoader(nil),
	}
	b := ssa.NewBuilder(context)
	mainpkg, args, err := ssa.CreatePackageFromArgs(b, args)
	if err != nil {
		log.Fatal(err.Error())
	}
	b.BuildAllPackages()
	b = nil // discard Builder

	if *runFlag {
		interp.Interpret(mainpkg, interpMode, mainpkg.Name(), args)
	}
}
Example #3
0
// This program demonstrates how to run the SSA builder on a "Hello,
// World!" program and shows the printed representation of packages,
// functions and instructions.
//
// Within the function listing, the name of each BasicBlock such as
// ".0.entry" is printed left-aligned, followed by the block's
// Instructions.
//
// For each instruction that defines an SSA virtual register
// (i.e. implements Value), the type of that value is shown in the
// right column.
//
// Build and run the ssadump.go program in this package if you want a
// standalone tool with similar functionality.
//
func Example() {
	const hello = `
package main

import "fmt"

const message = "Hello, World!"

func main() {
	fmt.Println(message)
}
`

	// Construct a builder.  Imports will be loaded as if by 'go build'.
	builder := ssa.NewBuilder(&ssa.Context{Loader: ssa.MakeGoBuildLoader(nil)})

	// Parse the input file.
	file, err := parser.ParseFile(builder.Prog.Files, "hello.go", hello, parser.DeclarationErrors)
	if err != nil {
		fmt.Printf(err.Error()) // parse error
		return
	}

	// Create a "main" package containing one file.
	mainPkg, err := builder.CreatePackage("main", []*ast.File{file})
	if err != nil {
		fmt.Printf(err.Error()) // type error
		return
	}

	// Print out the package.
	mainPkg.DumpTo(os.Stdout)
	fmt.Println()

	// Build SSA code for bodies of functions in mainPkg.
	builder.BuildPackage(mainPkg)

	// Print out the package-level functions.
	mainPkg.Init.DumpTo(os.Stdout)
	for _, mem := range mainPkg.Members {
		if fn, ok := mem.(*ssa.Function); ok {
			fn.DumpTo(os.Stdout)
		}
	}

	// Output:
	//
	// Package main:
	//   var   init$guard *bool
	//   func  main       func()
	//   const message    message = "Hello, World!":untyped string
	//
	// # Name: main.init
	// # Synthetic
	// func init():
	// .0.entry:                                                               P:0 S:2
	// 	t0 = *init$guard                                                   bool
	// 	if t0 goto 2.init.done else 1.init.start
	// .1.init.start:                                                          P:1 S:1
	// 	*init$guard = true:bool
	// 	t1 = fmt.init()                                                      ()
	// 	jump 2.init.done
	// .2.init.done:                                                           P:2 S:0
	// 	ret
	//
	// # Name: main.main
	// # Declared at hello.go:8:6
	// func main():
	// .0.entry:                                                               P:0 S:0
	// 	a0 = new [1]interface{}                                 *[1]interface{}
	// 	t0 = &a0[0:untyped integer]                                *interface{}
	// 	t1 = make interface interface{} <- string ("Hello, World!":string) interface{}
	// 	*t0 = t1
	// 	t2 = slice a0[:]                                          []interface{}
	// 	t3 = fmt.Println(t2)                                 (n int, err error)
	// 	ret
}