avr: add interrupt support

Interrupts are supported using a special //go:interrupt pragma.
For example:

//go:interrupt INT0_vect
func handleINT0() {
    // do something here
}
This commit is contained in:
Ayke van Laethem
2018-09-23 23:31:28 +02:00
parent dc88948f55
commit 13cb7d6503
3 changed files with 27 additions and 3 deletions
+3
View File
@@ -1135,6 +1135,9 @@ func (c *Compiler) parseFunc(frame *Frame) error {
if !frame.fn.IsExported() {
frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage)
}
if frame.fn.IsInterrupt() && strings.HasPrefix(c.Triple, "avr") {
frame.fn.LLVMFn.SetFunctionCallConv(85) // CallingConv::AVR_SIGNAL
}
if c.Debug {
pos := c.ir.Program.Fset.Position(frame.fn.Pos())
+23 -2
View File
@@ -40,11 +40,12 @@ type Program struct {
type Function struct {
*ssa.Function
LLVMFn llvm.Value
linkName string // go:linkname or go:export pragma
linkName string // go:linkname, go:export, go:interrupt
exported bool // go:export
nobounds bool // go:nobounds pragma
nobounds bool // go:nobounds
blocking bool // calculated by AnalyseBlockingRecursive
flag bool // used by dead code elimination
interrupt bool // go:interrupt
addressTaken bool // used as function pointer, calculated by AnalyseFunctionPointers
parents []*Function // calculated by AnalyseCallgraph
children []*Function // calculated by AnalyseCallgraph
@@ -298,6 +299,18 @@ func (f *Function) parsePragmas() {
}
f.linkName = parts[1]
f.exported = true
case "//go:interrupt":
if len(parts) != 2 {
continue
}
name := parts[1]
if strings.HasSuffix(name, "_vect") {
// AVR vector naming
name = "__vector_" + name[:len(name)-5]
}
f.linkName = name
f.exported = true
f.interrupt = true
case "//go:linkname":
if len(parts) != 3 || parts[1] != f.Name() {
continue
@@ -331,6 +344,14 @@ func (f *Function) IsExported() bool {
return f.exported
}
// Return true for functions annotated with //go:interrupt. The function name is
// already customized in LinkName() to hook up in the interrupt vector.
//
// On some platforms (like AVR), interrupts need a special compiler flag.
func (f *Function) IsInterrupt() bool {
return f.exported
}
// Return the link name for this function.
func (f *Function) LinkName() string {
if f.linkName != "" {
+1 -1
View File
@@ -266,7 +266,7 @@ func (p *Program) SimpleDCE() {
p.GetFunction(main).flag = true
worklist := []*ssa.Function{main}
for _, f := range p.Functions {
if f.Synthetic == "package initializer" || f.Pkg == runtimePkg {
if f.exported || f.Synthetic == "package initializer" || f.Pkg == runtimePkg {
if f.flag || isCGoInternal(f.Name()) {
continue
}