aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-07-07 15:51:52 +0200
committerRon Evans <[email protected]>2019-07-08 00:02:28 +0200
commit7ed6b45149fdcff29f3149b8bc5a5d7fc857077d (patch)
tree1ff819cb8d4c398214e4a658f6c37c506f921462
parentc66d979ba310feb94bee49e264a1af9d9981127b (diff)
downloadtinygo-7ed6b45149fdcff29f3149b8bc5a5d7fc857077d.tar.gz
tinygo-7ed6b45149fdcff29f3149b8bc5a5d7fc857077d.zip
compiler: add the //go:noinline pragma
This is directly useful to avoid some unsafety around runtime.alloc and should be useful in general. This pragma has the same form as in the main Go compiler: https://github.com/golang/go/issues/12312
-rw-r--r--compiler/compiler.go4
-rw-r--r--ir/ir.go6
-rw-r--r--src/runtime/gc_conservative.go1
3 files changed, 11 insertions, 0 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go
index 82aaee36e..1800f462a 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -865,6 +865,10 @@ func (c *Compiler) parseFunc(frame *Frame) {
// Add LLVM inline hint to functions with //go:inline pragma.
inline := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("inlinehint"), 0)
frame.fn.LLVMFn.AddFunctionAttr(inline)
+ case ir.InlineNone:
+ // Add LLVM attribute to always avoid inlining this function.
+ noinline := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("noinline"), 0)
+ frame.fn.LLVMFn.AddFunctionAttr(noinline)
}
// Add debug info, if needed.
diff --git a/ir/ir.go b/ir/ir.go
index d9d5764ee..f69173568 100644
--- a/ir/ir.go
+++ b/ir/ir.go
@@ -56,6 +56,10 @@ const (
// //go:inline). The compiler will be more likely to inline this function,
// but it is not a guarantee.
InlineHint
+
+ // Don't inline, just like the GCC noinline attribute. Signalled using
+ // //go:noinline.
+ InlineNone
)
// Create and initialize a new *Program from a *ssa.Program.
@@ -227,6 +231,8 @@ func (f *Function) parsePragmas() {
f.exported = true
case "//go:inline":
f.inline = InlineHint
+ case "//go:noinline":
+ f.inline = InlineNone
case "//go:interrupt":
if len(parts) != 2 {
continue
diff --git a/src/runtime/gc_conservative.go b/src/runtime/gc_conservative.go
index c8cb535a6..6b5b7a5cf 100644
--- a/src/runtime/gc_conservative.go
+++ b/src/runtime/gc_conservative.go
@@ -203,6 +203,7 @@ func init() {
// alloc tries to find some free space on the heap, possibly doing a garbage
// collection cycle if needed. If no space is free, it panics.
+//go:noinline
func alloc(size uintptr) unsafe.Pointer {
if size == 0 {
return unsafe.Pointer(&zeroSizedAlloc)