avr: add interrupt support
Interrupts are supported using a special //go:interrupt pragma. For example: //go:interrupt INT0_vect func handleINT0() { // do something here }
Этот коммит содержится в:
родитель
dc88948f55
коммит
13cb7d6503
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())
|
||||
|
|
25
ir/ir.go
25
ir/ir.go
|
@ -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
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче