github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/transform/util.go (about)

     1  package transform
     2  
     3  // This file contains utilities used across transforms.
     4  
     5  import (
     6  	"tinygo.org/x/go-llvm"
     7  )
     8  
     9  // Check whether all uses of this param as parameter to the call have the given
    10  // flag. In most cases, there will only be one use but a function could take the
    11  // same parameter twice, in which case both must have the flag.
    12  // A flag can be any enum flag, like "readonly".
    13  func hasFlag(call, param llvm.Value, kind string) bool {
    14  	fn := call.CalledValue()
    15  	if fn.IsAFunction().IsNil() {
    16  		// This is not a function but something else, like a function pointer.
    17  		return false
    18  	}
    19  	kindID := llvm.AttributeKindID(kind)
    20  	for i := 0; i < fn.ParamsCount(); i++ {
    21  		if call.Operand(i) != param {
    22  			// This is not the parameter we're checking.
    23  			continue
    24  		}
    25  		index := i + 1 // param attributes start at 1
    26  		attr := fn.GetEnumAttributeAtIndex(index, kindID)
    27  		if attr.IsNil() {
    28  			// At least one parameter doesn't have the flag (there may be
    29  			// multiple).
    30  			return false
    31  		}
    32  	}
    33  	return true
    34  }
    35  
    36  // isReadOnly returns true if the given value (which must be of pointer type) is
    37  // never stored to, and false if this cannot be proven.
    38  func isReadOnly(value llvm.Value) bool {
    39  	uses := getUses(value)
    40  	for _, use := range uses {
    41  		if !use.IsAGetElementPtrInst().IsNil() {
    42  			if !isReadOnly(use) {
    43  				return false
    44  			}
    45  		} else if !use.IsACallInst().IsNil() {
    46  			if !hasFlag(use, value, "readonly") {
    47  				return false
    48  			}
    49  		} else {
    50  			// Unknown instruction, might not be readonly.
    51  			return false
    52  		}
    53  	}
    54  	return true
    55  }