1 package transform
2 3 import (
4 "tinygo.org/x/go-llvm"
5 )
6 7 // Return a list of values (actually, instructions) where this value is used as
8 // an operand.
9 func getUses(value llvm.Value) []llvm.Value {
10 if value.IsNil() {
11 return nil
12 }
13 var uses []llvm.Value
14 use := value.FirstUse()
15 for !use.IsNil() {
16 uses = append(uses, use.User())
17 use = use.NextUse()
18 }
19 return uses
20 }
21 22 // hasUses returns whether the given value has any uses. It is equivalent to
23 // getUses(value) != nil but faster.
24 func hasUses(value llvm.Value) bool {
25 if value.IsNil() {
26 return false
27 }
28 return !value.FirstUse().IsNil()
29 }
30 31 // getGlobalBytes returns the slice contained in the array of the provided
32 // global. The builder parameter is only used for constant operations.
33 func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
34 value := global.Initializer()
35 buf := make([]byte, value.Type().ArrayLength())
36 for i := range buf {
37 buf[i] = byte(builder.CreateExtractValue(value, i, "").ZExtValue())
38 }
39 return buf
40 }
41 42 // stripPointerCasts strips instruction pointer casts (getelementptr and
43 // bitcast) and returns the original value without the casts.
44 func stripPointerCasts(value llvm.Value) llvm.Value {
45 if !value.IsAConstantExpr().IsNil() {
46 switch value.Opcode() {
47 case llvm.GetElementPtr, llvm.BitCast:
48 return stripPointerCasts(value.Operand(0))
49 }
50 }
51 if !value.IsAInstruction().IsNil() {
52 switch value.InstructionOpcode() {
53 case llvm.GetElementPtr, llvm.BitCast:
54 return stripPointerCasts(value.Operand(0))
55 }
56 }
57 return value
58 }
59