mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-12 23:13:40 +00:00
Compare commits
6 Commits
v0.19.0
...
debug-flag
| Author | SHA1 | Date | |
|---|---|---|---|
| a3ee85890d | |||
| 2930c44bfc | |||
| 0565b7c0e0 | |||
| 444dded92c | |||
| 42785e08e8 | |||
| 2d633e3a28 |
+53
-7
@@ -100,7 +100,6 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.Target.DefaultStackSize,
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
Debug: config.Debug(),
|
|
||||||
LLVMFeatures: config.LLVMFeatures(),
|
LLVMFeatures: config.LLVMFeatures(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,6 +536,41 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
ldflags = append(ldflags, lprogram.LDFlags...)
|
ldflags = append(ldflags, lprogram.LDFlags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strip debug information if -debug is true. This is sometimes the default,
|
||||||
|
// such as with WebAssembly targets.
|
||||||
|
if !config.Debug() {
|
||||||
|
for _, tag := range config.BuildTags() {
|
||||||
|
if tag == "baremetal" {
|
||||||
|
// Don't use -debug=false on baremetal targets. It makes no
|
||||||
|
// sense: the debug information isn't flashed to the device
|
||||||
|
// anyway.
|
||||||
|
return fmt.Errorf("stripping debug information is unnecessary for baremetal targets")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.Target.Linker == "wasm-ld" {
|
||||||
|
// Don't just strip debug information, also compress relocations
|
||||||
|
// while we're at it. Relocations can only be compressed when debug
|
||||||
|
// information is stripped.
|
||||||
|
ldflags = append(ldflags, "--strip-debug", "--compress-relocations")
|
||||||
|
} else {
|
||||||
|
switch config.GOOS() {
|
||||||
|
case "linux":
|
||||||
|
// Either real linux or an embedded system (like AVR) that
|
||||||
|
// pretends to be Linux. It's a ELF linker wrapped by GCC in any
|
||||||
|
// case.
|
||||||
|
ldflags = append(ldflags, "-Wl,--strip-debug")
|
||||||
|
case "darwin":
|
||||||
|
// MacOS (darwin) doesn't have a linker flag to strip debug
|
||||||
|
// information. Apple expects you to use the strip command
|
||||||
|
// instead.
|
||||||
|
return errors.New("cannot remove debug information: MacOS doesn't suppor this linker flag")
|
||||||
|
default:
|
||||||
|
// Other OSes may have different flags.
|
||||||
|
return errors.New("cannot remove debug information: unknown OS: " + config.GOOS())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a linker job, which links all object files together and does some
|
// Create a linker job, which links all object files together and does some
|
||||||
// extra stuff that can only be done after linking.
|
// extra stuff that can only be done after linking.
|
||||||
jobs = append(jobs, &compileJob{
|
jobs = append(jobs, &compileJob{
|
||||||
@@ -953,15 +987,19 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
if fn.stackSizeType == stacksize.Bounded {
|
if fn.stackSizeType == stacksize.Bounded {
|
||||||
stackSize := uint32(fn.stackSize)
|
stackSize := uint32(fn.stackSize)
|
||||||
|
|
||||||
// Adding 4 for the stack canary. Even though the size may be
|
|
||||||
// automatically determined, stack overflow checking is still
|
|
||||||
// important as the stack size cannot be determined for all
|
|
||||||
// goroutines.
|
|
||||||
stackSize += 4
|
|
||||||
|
|
||||||
// Add stack size used by interrupts.
|
// Add stack size used by interrupts.
|
||||||
switch fileHeader.Machine {
|
switch fileHeader.Machine {
|
||||||
case elf.EM_ARM:
|
case elf.EM_ARM:
|
||||||
|
if stackSize%8 != 0 {
|
||||||
|
// If the stack isn't a multiple of 8, it means the leaf
|
||||||
|
// function with the biggest stack depth doesn't have an aligned
|
||||||
|
// stack. If the STKALIGN flag is set (which it is by default)
|
||||||
|
// the interrupt controller will forcibly align the stack before
|
||||||
|
// storing in-use registers. This will thus overwrite one word
|
||||||
|
// past the end of the stack (off-by-one).
|
||||||
|
stackSize += 4
|
||||||
|
}
|
||||||
|
|
||||||
// On Cortex-M (assumed here), this stack size is 8 words or 32
|
// On Cortex-M (assumed here), this stack size is 8 words or 32
|
||||||
// bytes. This is only to store the registers that the interrupt
|
// bytes. This is only to store the registers that the interrupt
|
||||||
// may modify, the interrupt will switch to the interrupt stack
|
// may modify, the interrupt will switch to the interrupt stack
|
||||||
@@ -969,6 +1007,14 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
// Some background:
|
// Some background:
|
||||||
// https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching
|
// https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching
|
||||||
stackSize += 32
|
stackSize += 32
|
||||||
|
|
||||||
|
// Adding 4 for the stack canary, and another 4 to keep the
|
||||||
|
// stack aligned. Even though the size may be automatically
|
||||||
|
// determined, stack overflow checking is still important as the
|
||||||
|
// stack size cannot be determined for all goroutines.
|
||||||
|
stackSize += 8
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown architecture: %s", fileHeader.Machine.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally write the stack size to the binary.
|
// Finally write the stack size to the binary.
|
||||||
|
|||||||
+21
-5
@@ -209,9 +209,8 @@ func (c *Config) CFlags() []string {
|
|||||||
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
|
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
|
||||||
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
|
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
|
||||||
}
|
}
|
||||||
if c.Debug() {
|
// Always emit debug information. It is optionally stripped at link time.
|
||||||
cflags = append(cflags, "-g")
|
cflags = append(cflags, "-g")
|
||||||
}
|
|
||||||
return cflags
|
return cflags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,10 +249,27 @@ func (c *Config) VerifyIR() bool {
|
|||||||
return c.Options.VerifyIR
|
return c.Options.VerifyIR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug returns whether to add debug symbols to the IR, for debugging with GDB
|
// Debug returns whether debug (DWARF) information should be retained by the
|
||||||
// and similar.
|
// linker. The default varies by target but can be controlled with the -debug
|
||||||
|
// command line flag.
|
||||||
func (c *Config) Debug() bool {
|
func (c *Config) Debug() bool {
|
||||||
return c.Options.Debug
|
switch c.Options.Debug {
|
||||||
|
case "true":
|
||||||
|
return true
|
||||||
|
case "false":
|
||||||
|
return false
|
||||||
|
case "auto":
|
||||||
|
// Emit debug information everywhere by default except on WebAssembly.
|
||||||
|
for _, tag := range c.BuildTags() {
|
||||||
|
if tag == "tinygo.wasm" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
// This is already checked so shouldn't happen.
|
||||||
|
panic("unknown -debug flag")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BinaryFormat returns an appropriate binary format, based on the file
|
// BinaryFormat returns an appropriate binary format, based on the file
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
|
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
|
||||||
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
|
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
|
||||||
|
validDebugOptions = []string{"auto", "true", "false"}
|
||||||
validSerialOptions = []string{"none", "uart", "usb"}
|
validSerialOptions = []string{"none", "uart", "usb"}
|
||||||
validPrintSizeOptions = []string{"none", "short", "full"}
|
validPrintSizeOptions = []string{"none", "short", "full"}
|
||||||
validPanicStrategyOptions = []string{"print", "trap"}
|
validPanicStrategyOptions = []string{"print", "trap"}
|
||||||
@@ -28,7 +29,7 @@ type Options struct {
|
|||||||
DumpSSA bool
|
DumpSSA bool
|
||||||
VerifyIR bool
|
VerifyIR bool
|
||||||
PrintCommands func(cmd string, args ...string)
|
PrintCommands func(cmd string, args ...string)
|
||||||
Debug bool
|
Debug string
|
||||||
PrintSizes string
|
PrintSizes string
|
||||||
PrintAllocs *regexp.Regexp // regexp string
|
PrintAllocs *regexp.Regexp // regexp string
|
||||||
PrintStacks bool
|
PrintStacks bool
|
||||||
@@ -70,6 +71,12 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isInArray(validDebugOptions, o.Debug) {
|
||||||
|
return fmt.Errorf(`invalid debug option '%s': valid values are %s`,
|
||||||
|
o.Debug,
|
||||||
|
strings.Join(validDebugOptions, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
if o.PrintSizes != "" {
|
if o.PrintSizes != "" {
|
||||||
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
||||||
if !valid {
|
if !valid {
|
||||||
|
|||||||
+2
-16
@@ -58,7 +58,6 @@ type Config struct {
|
|||||||
AutomaticStackSize bool
|
AutomaticStackSize bool
|
||||||
DefaultStackSize uint64
|
DefaultStackSize uint64
|
||||||
NeedsStackObjects bool
|
NeedsStackObjects bool
|
||||||
Debug bool // Whether to emit debug information in the LLVM module.
|
|
||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,9 +102,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
|
|||||||
c.mod = c.ctx.NewModule(moduleName)
|
c.mod = c.ctx.NewModule(moduleName)
|
||||||
c.mod.SetTarget(config.Triple)
|
c.mod.SetTarget(config.Triple)
|
||||||
c.mod.SetDataLayout(c.targetData.String())
|
c.mod.SetDataLayout(c.targetData.String())
|
||||||
if c.Debug {
|
|
||||||
c.dibuilder = llvm.NewDIBuilder(c.mod)
|
c.dibuilder = llvm.NewDIBuilder(c.mod)
|
||||||
}
|
|
||||||
|
|
||||||
c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
|
c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
|
||||||
if c.targetData.PointerSize() <= 4 {
|
if c.targetData.PointerSize() <= 4 {
|
||||||
@@ -263,7 +260,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
ssaPkg.Build()
|
ssaPkg.Build()
|
||||||
|
|
||||||
// Initialize debug information.
|
// Initialize debug information.
|
||||||
if c.Debug {
|
|
||||||
c.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{
|
c.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{
|
||||||
Language: 0xb, // DW_LANG_C99 (0xc, off-by-one?)
|
Language: 0xb, // DW_LANG_C99 (0xc, off-by-one?)
|
||||||
File: "<unknown>",
|
File: "<unknown>",
|
||||||
@@ -271,7 +267,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
Producer: "TinyGo",
|
Producer: "TinyGo",
|
||||||
Optimized: true,
|
Optimized: true,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// Load comments such as //go:extern on globals.
|
// Load comments such as //go:extern on globals.
|
||||||
c.loadASTComments(pkg)
|
c.loadASTComments(pkg)
|
||||||
@@ -286,7 +281,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
c.createPackage(irbuilder, ssaPkg)
|
c.createPackage(irbuilder, ssaPkg)
|
||||||
|
|
||||||
// see: https://reviews.llvm.org/D18355
|
// see: https://reviews.llvm.org/D18355
|
||||||
if c.Debug {
|
|
||||||
c.mod.AddNamedMetadataOperand("llvm.module.flags",
|
c.mod.AddNamedMetadataOperand("llvm.module.flags",
|
||||||
c.ctx.MDNode([]llvm.Metadata{
|
c.ctx.MDNode([]llvm.Metadata{
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
|
llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
|
||||||
@@ -302,7 +296,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
c.dibuilder.Finalize()
|
c.dibuilder.Finalize()
|
||||||
}
|
|
||||||
|
|
||||||
return c.mod, c.diagnostics
|
return c.mod, c.diagnostics
|
||||||
}
|
}
|
||||||
@@ -812,8 +805,7 @@ func (b *builder) createFunction() {
|
|||||||
b.llvmFn.AddFunctionAttr(noinline)
|
b.llvmFn.AddFunctionAttr(noinline)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add debug info, if needed.
|
// Add debug info.
|
||||||
if b.Debug {
|
|
||||||
if b.fn.Synthetic == "package initializer" {
|
if b.fn.Synthetic == "package initializer" {
|
||||||
// Package initializers have no debug info. Create some fake debug
|
// Package initializers have no debug info. Create some fake debug
|
||||||
// info to at least have *something*.
|
// info to at least have *something*.
|
||||||
@@ -825,7 +817,6 @@ func (b *builder) createFunction() {
|
|||||||
}
|
}
|
||||||
pos := b.program.Fset.Position(b.fn.Pos())
|
pos := b.program.Fset.Position(b.fn.Pos())
|
||||||
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-create all basic blocks in the function.
|
// Pre-create all basic blocks in the function.
|
||||||
for _, block := range b.fn.DomPreorder() {
|
for _, block := range b.fn.DomPreorder() {
|
||||||
@@ -850,7 +841,7 @@ func (b *builder) createFunction() {
|
|||||||
b.locals[param] = b.collapseFormalParam(llvmType, fields)
|
b.locals[param] = b.collapseFormalParam(llvmType, fields)
|
||||||
|
|
||||||
// Add debug information to this parameter (if available)
|
// Add debug information to this parameter (if available)
|
||||||
if b.Debug && b.fn.Syntax() != nil {
|
if b.fn.Syntax() != nil {
|
||||||
dbgParam := b.getLocalVariable(param.Object().(*types.Var))
|
dbgParam := b.getLocalVariable(param.Object().(*types.Var))
|
||||||
loc := b.GetCurrentDebugLocation()
|
loc := b.GetCurrentDebugLocation()
|
||||||
if len(fields) == 1 {
|
if len(fields) == 1 {
|
||||||
@@ -910,9 +901,6 @@ func (b *builder) createFunction() {
|
|||||||
b.currentBlock = block
|
b.currentBlock = block
|
||||||
for _, instr := range block.Instrs {
|
for _, instr := range block.Instrs {
|
||||||
if instr, ok := instr.(*ssa.DebugRef); ok {
|
if instr, ok := instr.(*ssa.DebugRef); ok {
|
||||||
if !b.Debug {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
object := instr.Object()
|
object := instr.Object()
|
||||||
variable, ok := object.(*types.Var)
|
variable, ok := object.(*types.Var)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -1029,10 +1017,8 @@ func getPos(val posser) token.Pos {
|
|||||||
// createInstruction builds the LLVM IR equivalent instructions for the
|
// createInstruction builds the LLVM IR equivalent instructions for the
|
||||||
// particular Go SSA instruction.
|
// particular Go SSA instruction.
|
||||||
func (b *builder) createInstruction(instr ssa.Instruction) {
|
func (b *builder) createInstruction(instr ssa.Instruction) {
|
||||||
if b.Debug {
|
|
||||||
pos := b.program.Fset.Position(getPos(instr))
|
pos := b.program.Fset.Position(getPos(instr))
|
||||||
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
||||||
}
|
|
||||||
|
|
||||||
switch instr := instr.(type) {
|
switch instr := instr.(type) {
|
||||||
case ssa.Value:
|
case ssa.Value:
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||||||
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
||||||
builder.SetInsertPointAtEnd(entry)
|
builder.SetInsertPointAtEnd(entry)
|
||||||
|
|
||||||
if c.Debug {
|
// Add debug information.
|
||||||
pos := c.program.Fset.Position(pos)
|
pos := c.program.Fset.Position(pos)
|
||||||
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
||||||
File: c.getDIFile(pos.Filename),
|
File: c.getDIFile(pos.Filename),
|
||||||
@@ -202,7 +202,6 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||||||
})
|
})
|
||||||
wrapper.SetSubprogram(difunc)
|
wrapper.SetSubprogram(difunc)
|
||||||
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
}
|
|
||||||
|
|
||||||
// Create the list of params for the call.
|
// Create the list of params for the call.
|
||||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||||
@@ -246,7 +245,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||||||
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
||||||
builder.SetInsertPointAtEnd(entry)
|
builder.SetInsertPointAtEnd(entry)
|
||||||
|
|
||||||
if c.Debug {
|
// Add debug information.
|
||||||
pos := c.program.Fset.Position(pos)
|
pos := c.program.Fset.Position(pos)
|
||||||
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
||||||
File: c.getDIFile(pos.Filename),
|
File: c.getDIFile(pos.Filename),
|
||||||
@@ -266,7 +265,6 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||||||
})
|
})
|
||||||
wrapper.SetSubprogram(difunc)
|
wrapper.SetSubprogram(difunc)
|
||||||
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of parameters, with the extra parameters at the end.
|
// Get the list of parameters, with the extra parameters at the end.
|
||||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||||
|
|||||||
@@ -501,12 +501,10 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv
|
|||||||
}
|
}
|
||||||
defer b.Builder.Dispose()
|
defer b.Builder.Dispose()
|
||||||
|
|
||||||
// add debug info if needed
|
// add debug info
|
||||||
if c.Debug {
|
|
||||||
pos := c.program.Fset.Position(fn.Pos())
|
pos := c.program.Fset.Position(fn.Pos())
|
||||||
difunc := c.attachDebugInfoRaw(fn, wrapper, "$invoke", pos.Filename, pos.Line)
|
difunc := c.attachDebugInfoRaw(fn, wrapper, "$invoke", pos.Filename, pos.Line)
|
||||||
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
}
|
|
||||||
|
|
||||||
// set up IR builder
|
// set up IR builder
|
||||||
block := b.ctx.AddBasicBlock(wrapper, "entry")
|
block := b.ctx.AddBasicBlock(wrapper, "entry")
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||||||
global.SetInitializer(initializer)
|
global.SetInitializer(initializer)
|
||||||
|
|
||||||
// Add debug info to the interrupt global.
|
// Add debug info to the interrupt global.
|
||||||
if b.Debug {
|
|
||||||
pos := b.program.Fset.Position(instr.Pos())
|
pos := b.program.Fset.Position(instr.Pos())
|
||||||
diglobal := b.dibuilder.CreateGlobalVariableExpression(b.getDIFile(pos.Filename), llvm.DIGlobalVariableExpression{
|
diglobal := b.dibuilder.CreateGlobalVariableExpression(b.getDIFile(pos.Filename), llvm.DIGlobalVariableExpression{
|
||||||
Name: "interrupt" + strconv.FormatInt(id.Int64(), 10),
|
Name: "interrupt" + strconv.FormatInt(id.Int64(), 10),
|
||||||
@@ -64,7 +63,6 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||||||
LocalToUnit: false,
|
LocalToUnit: false,
|
||||||
})
|
})
|
||||||
global.AddMetadata(0, diglobal)
|
global.AddMetadata(0, diglobal)
|
||||||
}
|
|
||||||
|
|
||||||
// Create the runtime/interrupt.Interrupt type. It is a struct with a single
|
// Create the runtime/interrupt.Interrupt type. It is a struct with a single
|
||||||
// member of type int.
|
// member of type int.
|
||||||
|
|||||||
+1
-1
@@ -386,7 +386,7 @@ func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {
|
|||||||
llvmGlobal.SetAlignment(alignment)
|
llvmGlobal.SetAlignment(alignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Debug && !info.extern {
|
if !info.extern {
|
||||||
// Add debug info.
|
// Add debug info.
|
||||||
pos := c.program.Fset.Position(g.Pos())
|
pos := c.program.Fset.Position(g.Pos())
|
||||||
diglobal := c.dibuilder.CreateGlobalVariableExpression(c.difiles[pos.Filename], llvm.DIGlobalVariableExpression{
|
diglobal := c.dibuilder.CreateGlobalVariableExpression(c.difiles[pos.Filename], llvm.DIGlobalVariableExpression{
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.19.0"
|
const Version = "0.20.0-dev"
|
||||||
|
|
||||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
|
|||||||
@@ -1019,7 +1019,7 @@ func main() {
|
|||||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||||
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
||||||
printCommands := flag.Bool("x", false, "Print commands")
|
printCommands := flag.Bool("x", false, "Print commands")
|
||||||
nodebug := flag.Bool("no-debug", false, "disable DWARF debug symbol generation")
|
debug := flag.String("debug", "auto", "remove debug information (auto, true, false)")
|
||||||
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
||||||
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
||||||
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
||||||
@@ -1086,7 +1086,7 @@ func main() {
|
|||||||
PrintIR: *printIR,
|
PrintIR: *printIR,
|
||||||
DumpSSA: *dumpSSA,
|
DumpSSA: *dumpSSA,
|
||||||
VerifyIR: *verifyIR,
|
VerifyIR: *verifyIR,
|
||||||
Debug: !*nodebug,
|
Debug: *debug,
|
||||||
PrintSizes: *printSize,
|
PrintSizes: *printSize,
|
||||||
PrintStacks: *printStacks,
|
PrintStacks: *printStacks,
|
||||||
PrintAllocs: printAllocs,
|
PrintAllocs: printAllocs,
|
||||||
@@ -1173,11 +1173,6 @@ func main() {
|
|||||||
err := Flash(pkgName, *port, options)
|
err := Flash(pkgName, *port, options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
} else {
|
} else {
|
||||||
if !options.Debug {
|
|
||||||
fmt.Fprintln(os.Stderr, "Debug disabled while running gdb?")
|
|
||||||
usage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
err := FlashGDB(pkgName, *ocdOutput, options)
|
err := FlashGDB(pkgName, *ocdOutput, options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -194,7 +194,7 @@ func runTest(name, target string, t *testing.T, cmdArgs, environmentVars []strin
|
|||||||
PrintIR: false,
|
PrintIR: false,
|
||||||
DumpSSA: false,
|
DumpSSA: false,
|
||||||
VerifyIR: true,
|
VerifyIR: true,
|
||||||
Debug: true,
|
EmitDWARF: true,
|
||||||
PrintSizes: "",
|
PrintSizes: "",
|
||||||
WasmAbi: "",
|
WasmAbi: "",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,3 +7,81 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
const hexDigit = "0123456789abcdef"
|
const hexDigit = "0123456789abcdef"
|
||||||
|
|
||||||
|
// A HardwareAddr represents a physical hardware address.
|
||||||
|
type HardwareAddr []byte
|
||||||
|
|
||||||
|
func (a HardwareAddr) String() string {
|
||||||
|
if len(a) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
buf := make([]byte, 0, len(a)*3-1)
|
||||||
|
for i, b := range a {
|
||||||
|
if i > 0 {
|
||||||
|
buf = append(buf, ':')
|
||||||
|
}
|
||||||
|
buf = append(buf, hexDigit[b>>4])
|
||||||
|
buf = append(buf, hexDigit[b&0xF])
|
||||||
|
}
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet
|
||||||
|
// IP over InfiniBand link-layer address using one of the following formats:
|
||||||
|
// 00:00:5e:00:53:01
|
||||||
|
// 02:00:5e:10:00:00:00:01
|
||||||
|
// 00:00:00:00:fe:80:00:00:00:00:00:00:02:00:5e:10:00:00:00:01
|
||||||
|
// 00-00-5e-00-53-01
|
||||||
|
// 02-00-5e-10-00-00-00-01
|
||||||
|
// 00-00-00-00-fe-80-00-00-00-00-00-00-02-00-5e-10-00-00-00-01
|
||||||
|
// 0000.5e00.5301
|
||||||
|
// 0200.5e10.0000.0001
|
||||||
|
// 0000.0000.fe80.0000.0000.0000.0200.5e10.0000.0001
|
||||||
|
func ParseMAC(s string) (hw HardwareAddr, err error) {
|
||||||
|
if len(s) < 14 {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s[2] == ':' || s[2] == '-' {
|
||||||
|
if (len(s)+1)%3 != 0 {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
n := (len(s) + 1) / 3
|
||||||
|
if n != 6 && n != 8 && n != 20 {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
hw = make(HardwareAddr, n)
|
||||||
|
for x, i := 0, 0; i < n; i++ {
|
||||||
|
var ok bool
|
||||||
|
if hw[i], ok = xtoi2(s[x:], s[2]); !ok {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
x += 3
|
||||||
|
}
|
||||||
|
} else if s[4] == '.' {
|
||||||
|
if (len(s)+1)%5 != 0 {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
n := 2 * (len(s) + 1) / 5
|
||||||
|
if n != 6 && n != 8 && n != 20 {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
hw = make(HardwareAddr, n)
|
||||||
|
for x, i := 0, 0; i < n; i += 2 {
|
||||||
|
var ok bool
|
||||||
|
if hw[i], ok = xtoi2(s[x:x+2], 0); !ok {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
if hw[i+1], ok = xtoi2(s[x+2:], s[4]); !ok {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
x += 5
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
goto err
|
||||||
|
}
|
||||||
|
return hw, nil
|
||||||
|
|
||||||
|
err:
|
||||||
|
return nil, &AddrError{Err: "invalid MAC address", Addr: s}
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,6 +52,18 @@ func xtoi(s string) (n int, i int, ok bool) {
|
|||||||
return n, i, true
|
return n, i, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xtoi2 converts the next two hex digits of s into a byte.
|
||||||
|
// If s is longer than 2 bytes then the third byte must be e.
|
||||||
|
// If the first two bytes of s are not hex digits or the third byte
|
||||||
|
// does not match e, false is returned.
|
||||||
|
func xtoi2(s string, e byte) (byte, bool) {
|
||||||
|
if len(s) > 2 && s[2] != e {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
n, ei, ok := xtoi(s[:2])
|
||||||
|
return byte(n), ok && ei == 2
|
||||||
|
}
|
||||||
|
|
||||||
// Convert unsigned integer to decimal string.
|
// Convert unsigned integer to decimal string.
|
||||||
func uitoa(val uint) string {
|
func uitoa(val uint) string {
|
||||||
if val == 0 { // avoid string allocation
|
if val == 0 { // avoid string allocation
|
||||||
|
|||||||
Reference in New Issue
Block a user