builder: free LLVM objects after use
This reduces the TinyGo memory consumption when running make tinygo-test from 5.8GB to around 2GB on my laptop.
Этот коммит содержится в:
		
							родитель
							
								
									ea3b5dc689
								
							
						
					
					
						коммит
						777d3f3ea5
					
				
					 13 изменённых файлов: 49 добавлений и 6 удалений
				
			
		| 
						 | 
					@ -188,6 +188,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer machine.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load entire program AST into memory.
 | 
						// Load entire program AST into memory.
 | 
				
			||||||
	lprogram, err := loader.Load(config, []string{pkgName}, config.ClangHeaders, types.Config{
 | 
						lprogram, err := loader.Load(config, []string{pkgName}, config.ClangHeaders, types.Config{
 | 
				
			||||||
| 
						 | 
					@ -287,6 +288,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
				// Compile AST to IR. The compiler.CompilePackage function will
 | 
									// Compile AST to IR. The compiler.CompilePackage function will
 | 
				
			||||||
				// build the SSA as needed.
 | 
									// build the SSA as needed.
 | 
				
			||||||
				mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
 | 
									mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
 | 
				
			||||||
 | 
									defer mod.Context().Dispose()
 | 
				
			||||||
 | 
									defer mod.Dispose()
 | 
				
			||||||
				if errs != nil {
 | 
									if errs != nil {
 | 
				
			||||||
					return newMultiError(errs)
 | 
										return newMultiError(errs)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -432,6 +435,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add job that links and optimizes all packages together.
 | 
						// Add job that links and optimizes all packages together.
 | 
				
			||||||
	var mod llvm.Module
 | 
						var mod llvm.Module
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if !mod.IsNil() {
 | 
				
			||||||
 | 
								ctx := mod.Context()
 | 
				
			||||||
 | 
								mod.Dispose()
 | 
				
			||||||
 | 
								ctx.Dispose()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
	var stackSizeLoads []string
 | 
						var stackSizeLoads []string
 | 
				
			||||||
	programJob := &compileJob{
 | 
						programJob := &compileJob{
 | 
				
			||||||
		description:  "link+optimize packages (LTO)",
 | 
							description:  "link+optimize packages (LTO)",
 | 
				
			||||||
| 
						 | 
					@ -534,6 +544,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								defer llvmBuf.Dispose()
 | 
				
			||||||
			return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
 | 
								return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
 | 
				
			||||||
		case ".bc":
 | 
							case ".bc":
 | 
				
			||||||
			var buf llvm.MemoryBuffer
 | 
								var buf llvm.MemoryBuffer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -301,6 +301,7 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
 | 
				
			||||||
			}),
 | 
								}),
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
		c.dibuilder.Finalize()
 | 
							c.dibuilder.Finalize()
 | 
				
			||||||
 | 
							c.dibuilder.Destroy()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return c.mod, c.diagnostics
 | 
						return c.mod, c.diagnostics
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,7 @@ func TestCompiler(t *testing.T) {
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Fatal("failed to create target machine:", err)
 | 
									t.Fatal("failed to create target machine:", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								defer machine.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Load entire program AST into memory.
 | 
								// Load entire program AST into memory.
 | 
				
			||||||
			lprogram, err := loader.Load(config, []string{"./testdata/" + tc.file}, config.ClangHeaders, types.Config{
 | 
								lprogram, err := loader.Load(config, []string{"./testdata/" + tc.file}, config.ClangHeaders, types.Config{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ func CreateEntryBlockAlloca(builder llvm.Builder, t llvm.Type, name string) llvm
 | 
				
			||||||
func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, name string) (alloca, bitcast, size llvm.Value) {
 | 
					func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, name string) (alloca, bitcast, size llvm.Value) {
 | 
				
			||||||
	ctx := t.Context()
 | 
						ctx := t.Context()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
 | 
						i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
 | 
				
			||||||
	alloca = CreateEntryBlockAlloca(builder, t, name)
 | 
						alloca = CreateEntryBlockAlloca(builder, t, name)
 | 
				
			||||||
	bitcast = builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
 | 
						bitcast = builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
 | 
				
			||||||
| 
						 | 
					@ -46,6 +47,7 @@ func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, n
 | 
				
			||||||
func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, inst llvm.Value, name string) llvm.Value {
 | 
					func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, inst llvm.Value, name string) llvm.Value {
 | 
				
			||||||
	ctx := mod.Context()
 | 
						ctx := mod.Context()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
 | 
						i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	alloca := CreateEntryBlockAlloca(builder, t, name)
 | 
						alloca := CreateEntryBlockAlloca(builder, t, name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,8 +15,9 @@ import (
 | 
				
			||||||
func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix string, needsStackObjects bool, values []llvm.Value) llvm.Value {
 | 
					func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix string, needsStackObjects bool, values []llvm.Value) llvm.Value {
 | 
				
			||||||
	ctx := mod.Context()
 | 
						ctx := mod.Context()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
						i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
				
			||||||
	uintptrType := ctx.IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8)
 | 
						uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	valueTypes := make([]llvm.Type, len(values))
 | 
						valueTypes := make([]llvm.Type, len(values))
 | 
				
			||||||
	for i, value := range values {
 | 
						for i, value := range values {
 | 
				
			||||||
| 
						 | 
					@ -127,8 +128,9 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix string, needs
 | 
				
			||||||
func EmitPointerUnpack(builder llvm.Builder, mod llvm.Module, ptr llvm.Value, valueTypes []llvm.Type) []llvm.Value {
 | 
					func EmitPointerUnpack(builder llvm.Builder, mod llvm.Module, ptr llvm.Value, valueTypes []llvm.Type) []llvm.Value {
 | 
				
			||||||
	ctx := mod.Context()
 | 
						ctx := mod.Context()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
						i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
				
			||||||
	uintptrType := ctx.IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8)
 | 
						uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	packedType := ctx.StructType(valueTypes, false)
 | 
						packedType := ctx.StructType(valueTypes, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,10 +50,17 @@ func newRunner(mod llvm.Module, debug bool) *runner {
 | 
				
			||||||
	return &r
 | 
						return &r
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dispose deallocates all alloated LLVM resources.
 | 
				
			||||||
 | 
					func (r *runner) dispose() {
 | 
				
			||||||
 | 
						r.targetData.Dispose()
 | 
				
			||||||
 | 
						r.targetData = llvm.TargetData{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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, debug bool) error {
 | 
					func Run(mod llvm.Module, debug bool) error {
 | 
				
			||||||
	r := newRunner(mod, debug)
 | 
						r := newRunner(mod, debug)
 | 
				
			||||||
 | 
						defer r.dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	initAll := mod.NamedFunction("runtime.initAll")
 | 
						initAll := mod.NamedFunction("runtime.initAll")
 | 
				
			||||||
	bb := initAll.EntryBasicBlock()
 | 
						bb := initAll.EntryBasicBlock()
 | 
				
			||||||
| 
						 | 
					@ -196,6 +203,7 @@ func RunFunc(fn llvm.Value, debug bool) error {
 | 
				
			||||||
	// Create and initialize *runner object.
 | 
						// Create and initialize *runner object.
 | 
				
			||||||
	mod := fn.GlobalParent()
 | 
						mod := fn.GlobalParent()
 | 
				
			||||||
	r := newRunner(mod, debug)
 | 
						r := newRunner(mod, debug)
 | 
				
			||||||
 | 
						defer r.dispose()
 | 
				
			||||||
	initName := fn.Name()
 | 
						initName := fn.Name()
 | 
				
			||||||
	if !strings.HasSuffix(initName, ".init") {
 | 
						if !strings.HasSuffix(initName, ".init") {
 | 
				
			||||||
		return errorAt(fn, "interp: unexpected function name (expected *.init)")
 | 
							return errorAt(fn, "interp: unexpected function name (expected *.init)")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,7 @@ func TestInterp(t *testing.T) {
 | 
				
			||||||
func runTest(t *testing.T, pathPrefix string) {
 | 
					func runTest(t *testing.T, pathPrefix string) {
 | 
				
			||||||
	// Read the input IR.
 | 
						// Read the input IR.
 | 
				
			||||||
	ctx := llvm.NewContext()
 | 
						ctx := llvm.NewContext()
 | 
				
			||||||
 | 
						defer ctx.Dispose()
 | 
				
			||||||
	buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll")
 | 
						buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll")
 | 
				
			||||||
	os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching
 | 
						os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,7 @@ func runTest(t *testing.T, pathPrefix string) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("could not load module:\n%v", err)
 | 
							t.Fatalf("could not load module:\n%v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer mod.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Perform the transform.
 | 
						// Perform the transform.
 | 
				
			||||||
	err = Run(mod, false)
 | 
						err = Run(mod, false)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,8 +36,10 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
						i8ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
 | 
				
			||||||
	builder := mod.Context().NewBuilder()
 | 
						builder := mod.Context().NewBuilder()
 | 
				
			||||||
 | 
						defer builder.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, heapalloc := range getUses(allocator) {
 | 
						for _, heapalloc := range getUses(allocator) {
 | 
				
			||||||
		logAllocs := printAllocs != nil && printAllocs.MatchString(heapalloc.InstructionParent().Parent().Name())
 | 
							logAllocs := printAllocs != nil && printAllocs.MatchString(heapalloc.InstructionParent().Parent().Name())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,9 @@ func MakeGCStackSlots(mod llvm.Module) bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx := mod.Context()
 | 
						ctx := mod.Context()
 | 
				
			||||||
	builder := ctx.NewBuilder()
 | 
						builder := ctx.NewBuilder()
 | 
				
			||||||
 | 
						defer builder.Dispose()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
						uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Look at *all* functions to see whether they are free of function pointer
 | 
						// Look at *all* functions to see whether they are free of function pointer
 | 
				
			||||||
| 
						 | 
					@ -326,6 +328,7 @@ func AddGlobalsBitmap(mod llvm.Module) bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx := mod.Context()
 | 
						ctx := mod.Context()
 | 
				
			||||||
	targetData := llvm.NewTargetData(mod.DataLayout())
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
						uintptrType := ctx.IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Collect all globals that contain pointers (and thus must be scanned by
 | 
						// Collect all globals that contain pointers (and thus must be scanned by
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,19 +101,23 @@ type lowerInterfacesPass struct {
 | 
				
			||||||
// before LLVM can work on them. This is done so that a few cleanup passes can
 | 
					// before LLVM can work on them. This is done so that a few cleanup passes can
 | 
				
			||||||
// run before assigning the final type codes.
 | 
					// run before assigning the final type codes.
 | 
				
			||||||
func LowerInterfaces(mod llvm.Module, config *compileopts.Config) error {
 | 
					func LowerInterfaces(mod llvm.Module, config *compileopts.Config) error {
 | 
				
			||||||
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
	p := &lowerInterfacesPass{
 | 
						p := &lowerInterfacesPass{
 | 
				
			||||||
		mod:         mod,
 | 
							mod:         mod,
 | 
				
			||||||
		config:      config,
 | 
							config:      config,
 | 
				
			||||||
		builder:     mod.Context().NewBuilder(),
 | 
							builder:     mod.Context().NewBuilder(),
 | 
				
			||||||
		ctx:         mod.Context(),
 | 
							ctx:         mod.Context(),
 | 
				
			||||||
		uintptrType: mod.Context().IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8),
 | 
							uintptrType: mod.Context().IntType(targetData.PointerSize() * 8),
 | 
				
			||||||
		types:       make(map[string]*typeInfo),
 | 
							types:       make(map[string]*typeInfo),
 | 
				
			||||||
		signatures:  make(map[string]*signatureInfo),
 | 
							signatures:  make(map[string]*signatureInfo),
 | 
				
			||||||
		interfaces:  make(map[string]*interfaceInfo),
 | 
							interfaces:  make(map[string]*interfaceInfo),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer p.builder.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if config.Debug() {
 | 
						if config.Debug() {
 | 
				
			||||||
		p.dibuilder = llvm.NewDIBuilder(mod)
 | 
							p.dibuilder = llvm.NewDIBuilder(mod)
 | 
				
			||||||
 | 
							defer p.dibuilder.Destroy()
 | 
				
			||||||
		defer p.dibuilder.Finalize()
 | 
							defer p.dibuilder.Finalize()
 | 
				
			||||||
		p.difiles = make(map[string]llvm.Metadata)
 | 
							p.difiles = make(map[string]llvm.Metadata)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,10 +161,12 @@ func LowerReflect(mod llvm.Module) {
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Assign typecodes the way the reflect package expects.
 | 
						// Assign typecodes the way the reflect package expects.
 | 
				
			||||||
	uintptrType := mod.Context().IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8)
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
 | 
						uintptrType := mod.Context().IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
	state := typeCodeAssignmentState{
 | 
						state := typeCodeAssignmentState{
 | 
				
			||||||
		fallbackIndex:                    1,
 | 
							fallbackIndex:                    1,
 | 
				
			||||||
		uintptrLen:                       llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8,
 | 
							uintptrLen:                       targetData.PointerSize() * 8,
 | 
				
			||||||
		namedBasicTypes:                  make(map[string]int),
 | 
							namedBasicTypes:                  make(map[string]int),
 | 
				
			||||||
		namedNonBasicTypes:               make(map[string]int),
 | 
							namedNonBasicTypes:               make(map[string]int),
 | 
				
			||||||
		arrayTypes:                       make(map[string]int),
 | 
							arrayTypes:                       make(map[string]int),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,9 @@ func OptimizeReflectImplements(mod llvm.Module) {
 | 
				
			||||||
	defer builder.Dispose()
 | 
						defer builder.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get a few useful object for use later.
 | 
						// Get a few useful object for use later.
 | 
				
			||||||
	uintptrType := mod.Context().IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8)
 | 
						targetData := llvm.NewTargetData(mod.DataLayout())
 | 
				
			||||||
 | 
						defer targetData.Dispose()
 | 
				
			||||||
 | 
						uintptrType := mod.Context().IntType(targetData.PointerSize() * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Look up the (reflect.Value).Implements() method.
 | 
						// Look up the (reflect.Value).Implements() method.
 | 
				
			||||||
	var implementsFunc llvm.Value
 | 
						var implementsFunc llvm.Value
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ var defaultTestConfig = &compileopts.Config{
 | 
				
			||||||
func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Module)) {
 | 
					func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Module)) {
 | 
				
			||||||
	// Read the input IR.
 | 
						// Read the input IR.
 | 
				
			||||||
	ctx := llvm.NewContext()
 | 
						ctx := llvm.NewContext()
 | 
				
			||||||
 | 
						defer ctx.Dispose()
 | 
				
			||||||
	buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll")
 | 
						buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll")
 | 
				
			||||||
	os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching
 | 
						os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -41,6 +42,7 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("could not load module:\n%v", err)
 | 
							t.Fatalf("could not load module:\n%v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer mod.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Perform the transform.
 | 
						// Perform the transform.
 | 
				
			||||||
	transform(mod)
 | 
						transform(mod)
 | 
				
			||||||
| 
						 | 
					@ -141,6 +143,7 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal("failed to create target machine:", err)
 | 
							t.Fatal("failed to create target machine:", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer machine.Dispose()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load entire program AST into memory.
 | 
						// Load entire program AST into memory.
 | 
				
			||||||
	lprogram, err := loader.Load(config, []string{filename}, config.ClangHeaders, types.Config{
 | 
						lprogram, err := loader.Load(config, []string{filename}, config.ClangHeaders, types.Config{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче