mirror of https://github.com/tinygo-org/tinygo.git
wasmstm32webassemblymicrocontrollerarmavrspiwasiadafruitarduinocircuitplayground-expressgpioi2cllvmmicrobitnrf51nrf52nrf52840samd21tinygo
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.5 KiB
57 lines
1.5 KiB
package transform
|
|
|
|
import (
|
|
"tinygo.org/x/go-llvm"
|
|
)
|
|
|
|
// OptimizeStringToBytes transforms runtime.stringToBytes(...) calls into const
|
|
// []byte slices whenever possible. This optimizes the following pattern:
|
|
//
|
|
// w.Write([]byte("foo"))
|
|
//
|
|
// where Write does not store to the slice.
|
|
func OptimizeStringToBytes(mod llvm.Module) {
|
|
stringToBytes := mod.NamedFunction("runtime.stringToBytes")
|
|
if stringToBytes.IsNil() {
|
|
// nothing to optimize
|
|
return
|
|
}
|
|
|
|
for _, call := range getUses(stringToBytes) {
|
|
strptr := call.Operand(0)
|
|
strlen := call.Operand(1)
|
|
|
|
// strptr is always constant because strings are always constant.
|
|
|
|
convertedAllUses := true
|
|
for _, use := range getUses(call) {
|
|
if use.IsAExtractValueInst().IsNil() {
|
|
// Expected an extractvalue, but this is something else.
|
|
convertedAllUses = false
|
|
continue
|
|
}
|
|
switch use.Type().TypeKind() {
|
|
case llvm.IntegerTypeKind:
|
|
// A length (len or cap). Propagate the length value.
|
|
use.ReplaceAllUsesWith(strlen)
|
|
use.EraseFromParentAsInstruction()
|
|
case llvm.PointerTypeKind:
|
|
// The string pointer itself.
|
|
if !isReadOnly(use) {
|
|
convertedAllUses = false
|
|
continue
|
|
}
|
|
use.ReplaceAllUsesWith(strptr)
|
|
use.EraseFromParentAsInstruction()
|
|
default:
|
|
// should not happen
|
|
panic("unknown return type of runtime.stringToBytes: " + use.Type().String())
|
|
}
|
|
}
|
|
if convertedAllUses {
|
|
// Call to runtime.stringToBytes can be eliminated: both the input
|
|
// and the output is constant.
|
|
call.EraseFromParentAsInstruction()
|
|
}
|
|
}
|
|
}
|
|
|