cmd/compile: add //go:embed support

This commit contains the compiler support for //go:embed lines.
The go command passes to the compiler an "embed config"
that maps literal patterns like *.txt to the set of files to embed.
The compiler then lays out the content of those files as static data
in the form of an embed.Files or string or []byte in the final object file.

The test for this code is the end-to-end test hooking up the
embed, cmd/compile, and cmd/go changes, in the next CL.

For #41191.

Change-Id: I916e57f8cc65871dc0044c13d3f90c252a3fe1bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/243944
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Russ Cox 2020-07-19 00:32:02 -04:00
parent 400581b8b0
commit 8bde9b320e
8 changed files with 682 additions and 48 deletions

View file

@ -16,6 +16,8 @@ import (
"encoding/binary"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
@ -147,14 +149,20 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
// Data indexes
h.Offsets[goobj.BlkDataIdx] = w.Offset()
dataOff := uint32(0)
dataOff := int64(0)
for _, list := range lists {
for _, s := range list {
w.Uint32(dataOff)
dataOff += uint32(len(s.P))
w.Uint32(uint32(dataOff))
dataOff += int64(len(s.P))
if file := s.File(); file != nil {
dataOff += int64(file.Size)
}
}
}
w.Uint32(dataOff)
if int64(uint32(dataOff)) != dataOff {
log.Fatalf("data too large")
}
w.Uint32(uint32(dataOff))
// Relocs
h.Offsets[goobj.BlkReloc] = w.Offset()
@ -179,6 +187,9 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
for _, list := range lists {
for _, s := range list {
w.Bytes(s.P)
if file := s.File(); file != nil {
w.writeFile(ctxt, file)
}
}
}
@ -218,6 +229,7 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
type writer struct {
*goobj.Writer
filebuf []byte
ctxt *Link
pkgpath string // the package import path (escaped), "" if unknown
pkglist []string // list of packages referenced, indexed by ctxt.pkgIdx
@ -232,6 +244,35 @@ func (w *writer) init() {
}
}
func (w *writer) writeFile(ctxt *Link, file *FileInfo) {
f, err := os.Open(file.Name)
if err != nil {
ctxt.Diag("%v", err)
return
}
defer f.Close()
if w.filebuf == nil {
w.filebuf = make([]byte, 1024)
}
buf := w.filebuf
written := int64(0)
for {
n, err := f.Read(buf)
w.Bytes(buf[:n])
written += int64(n)
if err == io.EOF {
break
}
if err != nil {
ctxt.Diag("%v", err)
return
}
}
if written != file.Size {
ctxt.Diag("copy %s: unexpected length %d != %d", file.Name, written, file.Size)
}
}
func (w *writer) StringTable() {
w.AddString("")
for _, p := range w.ctxt.Imports {