compiler: add //go:inline pragma

Этот коммит содержится в:
Ayke van Laethem 2019-05-10 21:01:41 +02:00 коммит произвёл Ron Evans
родитель 397b90753c
коммит 6f6afb0515
2 изменённых файлов: 36 добавлений и 5 удалений

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

@ -828,6 +828,14 @@ func (c *Compiler) parseFunc(frame *Frame) {
frame.fn.LLVMFn.SetFunctionCallConv(85) // CallingConv::AVR_SIGNAL frame.fn.LLVMFn.SetFunctionCallConv(85) // CallingConv::AVR_SIGNAL
} }
// Some functions have a pragma controlling the inlining level.
switch frame.fn.Inline() {
case ir.InlineHint:
// Add LLVM inline hint to functions with //go:inline pragma.
inline := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("inlinehint"), 0)
frame.fn.LLVMFn.AddFunctionAttr(inline)
}
// Add debug info, if needed. // Add debug info, if needed.
if c.Debug { if c.Debug {
if frame.fn.Synthetic == "package initializer" { if frame.fn.Synthetic == "package initializer" {

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

@ -33,11 +33,12 @@ type Program struct {
type Function struct { type Function struct {
*ssa.Function *ssa.Function
LLVMFn llvm.Value LLVMFn llvm.Value
linkName string // go:linkname, go:export, go:interrupt linkName string // go:linkname, go:export, go:interrupt
exported bool // go:export exported bool // go:export
nobounds bool // go:nobounds nobounds bool // go:nobounds
flag bool // used by dead code elimination flag bool // used by dead code elimination
interrupt bool // go:interrupt interrupt bool // go:interrupt
inline InlineType // go:inline
} }
// Global variable, possibly constant. // Global variable, possibly constant.
@ -69,6 +70,21 @@ type Interface struct {
Type *types.Interface Type *types.Interface
} }
type InlineType int
// How much to inline.
const (
// Default behavior. The compiler decides for itself whether any given
// function will be inlined. Whether any function is inlined depends on the
// optimization level.
InlineDefault InlineType = iota
// Inline hint, just like the C inline keyword (signalled using
// //go:inline). The compiler will be more likely to inline this function,
// but it is not a guarantee.
InlineHint
)
// Create and initialize a new *Program from a *ssa.Program. // Create and initialize a new *Program from a *ssa.Program.
func NewProgram(lprogram *loader.Program, mainPath string) *Program { func NewProgram(lprogram *loader.Program, mainPath string) *Program {
comments := map[string]*ast.CommentGroup{} comments := map[string]*ast.CommentGroup{}
@ -279,6 +295,8 @@ func (f *Function) parsePragmas() {
} }
f.linkName = parts[1] f.linkName = parts[1]
f.exported = true f.exported = true
case "//go:inline":
f.inline = InlineHint
case "//go:interrupt": case "//go:interrupt":
if len(parts) != 2 { if len(parts) != 2 {
continue continue
@ -332,6 +350,11 @@ func (f *Function) IsInterrupt() bool {
return f.interrupt return f.interrupt
} }
// Return the inline directive of this function.
func (f *Function) Inline() InlineType {
return f.inline
}
// Return the link name for this function. // Return the link name for this function.
func (f *Function) LinkName() string { func (f *Function) LinkName() string {
if f.linkName != "" { if f.linkName != "" {