// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package noder import ( "bytes" "fmt" "io" "cmd/compile/internal/base" "cmd/compile/internal/typecheck" "cmd/internal/bio" ) // writeNewExportFunc is a hook that can be added to append extra // export data after the normal export data section. It allows // experimenting with new export data format designs without requiring // immediate support in the go/internal or x/tools importers. var writeNewExportFunc func(out io.Writer) func WriteExports(out *bio.Writer) { // When unified IR exports are enable, we simply append it to the // end of the normal export data (with compiler extensions // disabled), and write an extra header giving its size. // // If the compiler sees this header, it knows to read the new data // instead; meanwhile the go/types importers will silently ignore it // and continue processing the old export instead. // // This allows us to experiment with changes to the new export data // format without needing to update the go/internal/gcimporter or // (worse) x/tools/go/gcexportdata. useNewExport := writeNewExportFunc != nil var old, new bytes.Buffer typecheck.WriteExports(&old, !useNewExport) if useNewExport { writeNewExportFunc(&new) } oldLen := old.Len() newLen := new.Len() if useNewExport { fmt.Fprintf(out, "\nnewexportsize %v\n", newLen) } // The linker also looks for the $$ marker - use char after $$ to distinguish format. out.WriteString("\n$$B\n") // indicate binary export format io.Copy(out, &old) out.WriteString("\n$$\n") io.Copy(out, &new) if base.Debug.Export != 0 { fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, oldLen) if useNewExport { fmt.Printf("BenchmarkNewExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, newLen) } } }