Example #1
0
func TestLLVMIRReadCloser(t *testing.T) {
	const input = `;abc\n;def\n;xyz`

	var buf bytes.Buffer
	buf.WriteString(input)
	r := build.NewLLVMIRReader(ioutil.NopCloser(&buf))
	b, err := ioutil.ReadAll(iotest.OneByteReader(r))
	if err != nil {
		t.Errorf("unexpected error: %s", err)
	}

	str := string(b)
	expected := strings.Replace(str, ";", "//", -1)
	if str != expected {
		t.Errorf("%q != %q", str, expected)
	}
}
Example #2
0
File: build.go Project: minux/llgo
func getPackage(pkgpath string) (pkg *build.Package, err error) {
	// These packages are special: they're mostly written from
	// scratch, so we don't both with the overlay.
	if pkgpath == "runtime" || pkgpath == "runtime/cgo" {
		defer func(pkgpath string) { pkg.ImportPath = pkgpath }(pkgpath)
		pkgpath = llgoPkgPrefix + pkgpath
	}

	// Make a copy, as we'll be modifying ReadDir/OpenFile.
	buildctx := *buildctx

	// Attempt to find an overlay package path,
	// which we'll use in ReadDir below.
	overlayentries := make(map[string]bool)
	overlaypkgpath := llgoPkgPrefix + pkgpath
	overlaypkg, err := buildctx.Import(overlaypkgpath, "", build.FindOnly)
	if err != nil {
		overlaypkg = nil
	}

	// ReadDir is overridden to return a fake ".s"
	// file for each ".ll" file in the directory.
	buildctx.ReadDir = func(dir string) (fi []os.FileInfo, err error) {
		fi, err = ioutil.ReadDir(dir)
		if err != nil {
			return nil, err
		}
		entries := make(map[string]os.FileInfo)
		for _, info := range fi {
			entries[info.Name()] = info
		}
		// Overlay all files in the overlay package dir.
		// If we find any .ll files, replace the suffix
		// with .s.
		if overlaypkg != nil {
			fi, err = ioutil.ReadDir(overlaypkg.Dir)
		}
		if err == nil {
			// Check for .ll files in the overlay dir if
			// we have one, else in the standard package dir.
			for _, info := range fi {
				name := info.Name()
				if strings.HasSuffix(name, ".ll") {
					name = name[:len(name)-3] + ".s"
					info = &renamedFileInfo{info, name}
				}
				overlayentries[name] = true
				entries[name] = info
			}
		}
		fi = make([]os.FileInfo, 0, len(entries))
		for _, info := range entries {
			fi = append(fi, info)
		}
		return fi, nil
	}

	// OpenFile is overridden to return the contents
	// of the ".ll" file found in ReadDir above. The
	// returned ReadCloser is wrapped to transform
	// LLVM IR comments to use "//", as expected by
	// go/build when looking for build tags.
	buildctx.OpenFile = func(path string) (io.ReadCloser, error) {
		base := filepath.Base(path)
		overlay := overlayentries[base]
		if overlay {
			if overlaypkg != nil {
				path = filepath.Join(overlaypkg.Dir, base)
			}
			if strings.HasSuffix(path, ".s") {
				path := path[:len(path)-2] + ".ll"
				var r io.ReadCloser
				var err error
				r, err = os.Open(path)
				if err == nil {
					r = llgobuild.NewLLVMIRReader(r)
				}
				return r, err
			}
		}
		return os.Open(path)
	}

	pkg, err = buildctx.Import(pkgpath, "", 0)
	if err != nil {
		return nil, err
	} else {
		if overlaypkg == nil {
			overlaypkg = pkg
		}
		// TODO(axw) factor out the repeated code
		for i, filename := range pkg.GoFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.GoFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.CgoFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.CgoFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.TestGoFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.TestGoFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.XTestGoFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.XTestGoFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.CFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.CFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.SFiles {
			pkgdir := pkg.Dir
			if strings.HasSuffix(filename, ".S") {
				// .S files go straight to clang
			} else if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
				filename = filename[:len(filename)-2] + ".ll"
			} else {
				err := fmt.Errorf("No matching .ll file for %q", filename)
				return nil, err
			}
			pkg.SFiles[i] = path.Join(pkgdir, filename)
		}
	}
	return pkg, nil
}
Example #3
0
func getPackage(pkgpath string) (*gobuild.Package, error) {
	var ctx gobuild.Context = gobuild.Default
	ctx.GOARCH = GOARCH
	ctx.GOOS = GOOS
	ctx.BuildTags = append(ctx.BuildTags[:], "llgo")
	//ctx.Compiler = "llgo"

	// Attempt to find an overlay package path,
	// which we'll use in ReadDir below.
	overlayentries := make(map[string]bool)
	overlaypkgpath := llgoPkgPrefix + pkgpath
	overlaypkg, err := ctx.Import(overlaypkgpath, "", gobuild.FindOnly)
	if err != nil {
		overlaypkg = nil
	}

	// ReadDir is overridden to return a fake ".s"
	// file for each ".ll" file in the directory.
	ctx.ReadDir = func(dir string) (fi []os.FileInfo, err error) {
		fi, err = ioutil.ReadDir(dir)
		if err != nil {
			return nil, err
		}
		entries := make(map[string]os.FileInfo)
		for _, info := range fi {
			entries[info.Name()] = info
		}
		// Overlay all files in the overlay package dir.
		// If we find any .ll files, replace the suffix
		// with .s.
		if overlaypkg != nil {
			fi, err = ioutil.ReadDir(overlaypkg.Dir)
		}
		if err == nil {
			// Check for .ll files in the overlay dir if
			// we have one, else in the standard package dir.
			for _, info := range fi {
				name := info.Name()
				if strings.HasSuffix(name, ".ll") {
					name = name[:len(name)-3] + ".s"
					info = &renamedFileInfo{info, name}
				}
				overlayentries[name] = true
				entries[name] = info
			}
		}
		fi = make([]os.FileInfo, 0, len(entries))
		for _, info := range entries {
			fi = append(fi, info)
		}
		return fi, nil
	}

	// OpenFile is overridden to return the contents
	// of the ".ll" file found in ReadDir above. The
	// returned ReadCloser is wrapped to transform
	// LLVM IR comments to use "//", as expected by
	// go/build when looking for build tags.
	ctx.OpenFile = func(path string) (io.ReadCloser, error) {
		base := filepath.Base(path)
		overlay := overlayentries[base]
		if overlay {
			if overlaypkg != nil {
				path = filepath.Join(overlaypkg.Dir, base)
			}
			if strings.HasSuffix(path, ".s") {
				path := path[:len(path)-2] + ".ll"
				var r io.ReadCloser
				var err error
				r, err = os.Open(path)
				if err == nil {
					r = build.NewLLVMIRReader(r)
				}
				return r, err
			}
		}
		return os.Open(path)
	}

	pkg, err := ctx.Import(pkgpath, "", 0)
	if err != nil {
		return nil, err
	} else {
		if overlaypkg == nil {
			overlaypkg = pkg
		}
		for i, filename := range pkg.GoFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.GoFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.CFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
			}
			pkg.CFiles[i] = path.Join(pkgdir, filename)
		}
		for i, filename := range pkg.SFiles {
			pkgdir := pkg.Dir
			if overlayentries[filename] {
				pkgdir = overlaypkg.Dir
				filename = filename[:len(filename)-2] + ".ll"
			} else {
				err := fmt.Errorf("No matching .ll file for %q", filename)
				return nil, err
			}
			pkg.SFiles[i] = path.Join(pkgdir, filename)
		}
	}
	return pkg, nil
}