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

//go:interrupt INT0_vect
func handleINT0() {
    // do something here
}
Этот коммит содержится в:
Ayke van Laethem 2018-09-23 23:31:28 +02:00
родитель dc88948f55
коммит 13cb7d6503
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
3 изменённых файлов: 27 добавлений и 3 удалений

Просмотреть файл

@ -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())

Просмотреть файл

@ -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 != "" {

Просмотреть файл

@ -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
}