aboutsummaryrefslogtreecommitdiffhomepage
path: root/transform/allocs_test.go
blob: 7f7ff5b75ecd2d5521dcbee967702fd5f71fb266 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package transform_test

import (
	"go/token"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"testing"

	"github.com/tinygo-org/tinygo/transform"
	"tinygo.org/x/go-llvm"
)

func TestAllocs(t *testing.T) {
	t.Parallel()
	testTransform(t, "testdata/allocs", func(mod llvm.Module) {
		transform.OptimizeAllocs(mod, nil, 256, nil)
	})
}

type allocsTestOutput struct {
	filename string
	line     int
	msg      string
}

func (out allocsTestOutput) String() string {
	return out.filename + ":" + strconv.Itoa(out.line) + ": " + out.msg
}

// Test with a Go file as input (for more accurate tests).
func TestAllocs2(t *testing.T) {
	t.Parallel()

	mod := compileGoFileForTesting(t, "./testdata/allocs2.go")

	// Run functionattrs pass, which is necessary for escape analysis.
	po := llvm.NewPassBuilderOptions()
	defer po.Dispose()
	err := mod.RunPasses("function(instcombine),function-attrs", llvm.TargetMachine{}, po)
	if err != nil {
		t.Error("failed to run passes:", err)
	}

	// Run heap to stack transform.
	var testOutputs []allocsTestOutput
	transform.OptimizeAllocs(mod, regexp.MustCompile("."), 256, func(pos token.Position, msg string) {
		testOutputs = append(testOutputs, allocsTestOutput{
			filename: filepath.Base(pos.Filename),
			line:     pos.Line,
			msg:      msg,
		})
	})
	sort.Slice(testOutputs, func(i, j int) bool {
		return testOutputs[i].line < testOutputs[j].line
	})
	testOutput := ""
	for _, out := range testOutputs {
		testOutput += out.String() + "\n"
	}

	// Load expected test output (the OUT: lines).
	testInput, err := os.ReadFile("./testdata/allocs2.go")
	if err != nil {
		t.Fatal("could not read test input:", err)
	}
	var expectedTestOutput string
	for i, line := range strings.Split(strings.ReplaceAll(string(testInput), "\r\n", "\n"), "\n") {
		if idx := strings.Index(line, " // OUT: "); idx > 0 {
			msg := line[idx+len(" // OUT: "):]
			expectedTestOutput += "allocs2.go:" + strconv.Itoa(i+1) + ": " + msg + "\n"
		}
	}

	if testOutput != expectedTestOutput {
		t.Errorf("output does not match expected output:\n%s", testOutput)
	}
}