aboutsummaryrefslogtreecommitdiffhomepage
path: root/transform/util.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-08-17 16:39:14 +0200
committerRon Evans <[email protected]>2019-09-15 21:26:27 +0200
commitd905476231b5f625dfc65ddaf497bc25980b6e7b (patch)
treeca6d8a048b425b468ce8d9f6e38cadd51e059991 /transform/util.go
parent10ed3decb076c88077ccd849029357e1c2c33f7c (diff)
downloadtinygo-d905476231b5f625dfc65ddaf497bc25980b6e7b.tar.gz
tinygo-d905476231b5f625dfc65ddaf497bc25980b6e7b.zip
all: refactor heap-to-stack transform into the transform package
Also add unit tests. This is the first of several transformation (optimization/lowering) passes that I'd like to move to the new transform package. This separates the compiler from the optimizer. Also, it finally adds unit tests for the compiler, not just end-to-end compilation tests. This should improve robustness and should make it easier to change these transformation passes in the future. While the heap-to-stack transform is relatively simple, other passes are much more complex. Adding unit tests not only helps robustness over time, but also doubles as documentation as to what these transformation passes do exactly.
Diffstat (limited to 'transform/util.go')
-rw-r--r--transform/util.go34
1 files changed, 34 insertions, 0 deletions
diff --git a/transform/util.go b/transform/util.go
new file mode 100644
index 000000000..a27bf9ec8
--- /dev/null
+++ b/transform/util.go
@@ -0,0 +1,34 @@
+package transform
+
+// This file contains utilities used across transforms.
+
+import (
+ "tinygo.org/x/go-llvm"
+)
+
+// Check whether all uses of this param as parameter to the call have the given
+// flag. In most cases, there will only be one use but a function could take the
+// same parameter twice, in which case both must have the flag.
+// A flag can be any enum flag, like "readonly".
+func hasFlag(call, param llvm.Value, kind string) bool {
+ fn := call.CalledValue()
+ if fn.IsAFunction().IsNil() {
+ // This is not a function but something else, like a function pointer.
+ return false
+ }
+ kindID := llvm.AttributeKindID(kind)
+ for i := 0; i < fn.ParamsCount(); i++ {
+ if call.Operand(i) != param {
+ // This is not the parameter we're checking.
+ continue
+ }
+ index := i + 1 // param attributes start at 1
+ attr := fn.GetEnumAttributeAtIndex(index, kindID)
+ if attr.IsNil() {
+ // At least one parameter doesn't have the flag (there may be
+ // multiple).
+ return false
+ }
+ }
+ return true
+}