diff options
author | Ayke van Laethem <[email protected]> | 2019-08-17 16:39:14 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-09-15 21:26:27 +0200 |
commit | d905476231b5f625dfc65ddaf497bc25980b6e7b (patch) | |
tree | ca6d8a048b425b468ce8d9f6e38cadd51e059991 /transform/util.go | |
parent | 10ed3decb076c88077ccd849029357e1c2c33f7c (diff) | |
download | tinygo-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.go | 34 |
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 +} |