cli,compiler: support emitting debug info in a file
This commit is contained in:
parent
5d3da26e1e
commit
5bdee683e6
3 changed files with 40 additions and 13 deletions
|
@ -92,6 +92,10 @@ func NewCommands() []cli.Command {
|
||||||
Name: "debug, d",
|
Name: "debug, d",
|
||||||
Usage: "Debug mode will print out additional information after a compiling",
|
Usage: "Debug mode will print out additional information after a compiling",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "emitdebug",
|
||||||
|
Usage: "Emit debug info in a separate file",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -348,6 +352,8 @@ func contractCompile(ctx *cli.Context) error {
|
||||||
o := &compiler.Options{
|
o := &compiler.Options{
|
||||||
Outfile: ctx.String("out"),
|
Outfile: ctx.String("out"),
|
||||||
Debug: ctx.Bool("debug"),
|
Debug: ctx.Bool("debug"),
|
||||||
|
|
||||||
|
DebugInfo: ctx.String("emitdebug"),
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := compiler.CompileAndSave(src, o)
|
result, err := compiler.CompileAndSave(src, o)
|
||||||
|
|
|
@ -1313,19 +1313,19 @@ func newCodegen(info *buildInfo, pkg *loader.PackageInfo) *codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeGen compiles the program to bytecode.
|
// CodeGen compiles the program to bytecode.
|
||||||
func CodeGen(info *buildInfo) ([]byte, error) {
|
func CodeGen(info *buildInfo) ([]byte, *DebugInfo, error) {
|
||||||
pkg := info.program.Package(info.initialPackage)
|
pkg := info.program.Package(info.initialPackage)
|
||||||
c := newCodegen(info, pkg)
|
c := newCodegen(info, pkg)
|
||||||
|
|
||||||
if err := c.compile(info, pkg); err != nil {
|
if err := c.compile(info, pkg); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := c.prog.Bytes()
|
buf := c.prog.Bytes()
|
||||||
if err := c.writeJumps(buf); err != nil {
|
if err := c.writeJumps(buf); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return buf, nil
|
return buf, c.emitDebugInfo(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) resolveFuncDecls(f *ast.File) {
|
func (c *codegen) resolveFuncDecls(f *ast.File) {
|
||||||
|
|
|
@ -2,11 +2,13 @@ package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/loader"
|
"golang.org/x/tools/go/loader"
|
||||||
|
@ -22,6 +24,9 @@ type Options struct {
|
||||||
// The name of the output file.
|
// The name of the output file.
|
||||||
Outfile string
|
Outfile string
|
||||||
|
|
||||||
|
// The name of the output for debug info.
|
||||||
|
DebugInfo string
|
||||||
|
|
||||||
// Debug outputs a hex encoded string of the generated bytecode.
|
// Debug outputs a hex encoded string of the generated bytecode.
|
||||||
Debug bool
|
Debug bool
|
||||||
}
|
}
|
||||||
|
@ -52,12 +57,7 @@ func getBuildInfo(src interface{}) (*buildInfo, error) {
|
||||||
|
|
||||||
// Compile compiles a Go program into bytecode that can run on the NEO virtual machine.
|
// Compile compiles a Go program into bytecode that can run on the NEO virtual machine.
|
||||||
func Compile(r io.Reader) ([]byte, error) {
|
func Compile(r io.Reader) ([]byte, error) {
|
||||||
ctx, err := getBuildInfo(r)
|
buf, _, err := CompileWithDebugInfo(r)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err := CodeGen(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,15 @@ func Compile(r io.Reader) ([]byte, error) {
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompileWithDebugInfo compiles a Go program into bytecode and emits debug info.
|
||||||
|
func CompileWithDebugInfo(r io.Reader) ([]byte, *DebugInfo, error) {
|
||||||
|
ctx, err := getBuildInfo(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return CodeGen(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// CompileAndSave will compile and save the file to disk.
|
// CompileAndSave will compile and save the file to disk.
|
||||||
func CompileAndSave(src string, o *Options) ([]byte, error) {
|
func CompileAndSave(src string, o *Options) ([]byte, error) {
|
||||||
if !strings.HasSuffix(src, ".go") {
|
if !strings.HasSuffix(src, ".go") {
|
||||||
|
@ -81,11 +90,23 @@ func CompileAndSave(src string, o *Options) ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
b, err = Compile(bytes.NewReader(b))
|
b, di, err := CompileWithDebugInfo(bytes.NewReader(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error while trying to compile smart contract file: %v", err)
|
return nil, fmt.Errorf("error while trying to compile smart contract file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
out := fmt.Sprintf("%s.%s", o.Outfile, o.Ext)
|
out := fmt.Sprintf("%s.%s", o.Outfile, o.Ext)
|
||||||
return b, ioutil.WriteFile(out, b, os.ModePerm)
|
err = ioutil.WriteFile(out, b, os.ModePerm)
|
||||||
|
if o.DebugInfo == "" {
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
p, err := filepath.Abs(src)
|
||||||
|
if err != nil {
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
di.Documents = append(di.Documents, p)
|
||||||
|
data, err := json.Marshal(di)
|
||||||
|
if err != nil {
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
return b, ioutil.WriteFile(o.DebugInfo, data, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue