mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-13 23:43:40 +00:00
all: modernize (#5498)
* modernize string cut usage * modernize string cut prefix usage * modernize slices helper usage * modernize min and max usage * modernize loop variable copies * modernize integer range loops * modernize map copy loops * modernize go types iterator usage * modernize empty interface usage * modernize atomic type usage * modernize string builders * modernize string split iteration * modernize remaining loop variable copies * modernize usb cdc min usage * modernize src integer range loops * modernize example empty interface usage * modernize src min and max usage * modernize src integer range loops * modernize src empty interface usage * modernize src atomic type usage * modernize reflect type lookups * modernize review nits
This commit is contained in:
@@ -168,7 +168,7 @@ type builder struct {
|
||||
dilocals map[*types.Var]llvm.Metadata
|
||||
initInlinedAt llvm.Metadata // fake inlinedAt position
|
||||
initPseudoFuncs map[string]llvm.Metadata // fake "inlined" functions for proper init debug locations
|
||||
allDeferFuncs []interface{}
|
||||
allDeferFuncs []any
|
||||
deferFuncs map[*ssa.Function]int
|
||||
deferInvokeFuncs map[string]int
|
||||
deferClosureFuncs map[*ssa.Function]int
|
||||
@@ -2154,13 +2154,10 @@ func (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {
|
||||
if elementSize == 0 {
|
||||
elementSize = 1
|
||||
}
|
||||
maxSize := maxPointerValue / elementSize
|
||||
|
||||
// len(slice) is an int. Make sure the length remains small enough to fit in
|
||||
// an int.
|
||||
if maxSize > maxIntegerValue {
|
||||
maxSize = maxIntegerValue
|
||||
}
|
||||
maxSize := min(
|
||||
// len(slice) is an int. Make sure the length remains small enough to fit in
|
||||
// an int.
|
||||
maxPointerValue/elementSize, maxIntegerValue)
|
||||
|
||||
return maxSize
|
||||
}
|
||||
|
||||
@@ -188,9 +188,9 @@ func TestCompilerErrors(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
errorsFileString := strings.ReplaceAll(string(errorsFile), "\r\n", "\n")
|
||||
for _, line := range strings.Split(errorsFileString, "\n") {
|
||||
if strings.HasPrefix(line, "// ERROR: ") {
|
||||
expectedErrors = append(expectedErrors, strings.TrimPrefix(line, "// ERROR: "))
|
||||
for line := range strings.SplitSeq(errorsFileString, "\n") {
|
||||
if after, ok := strings.CutPrefix(line, "// ERROR: "); ok {
|
||||
expectedErrors = append(expectedErrors, after)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -669,8 +669,8 @@ func (b *builder) createRunDefers() {
|
||||
fn := callback.Fn.(*ssa.Function)
|
||||
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
|
||||
params := fn.Signature.Params()
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
|
||||
for v := range params.Variables() {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(v.Type()))
|
||||
}
|
||||
valueTypes = append(valueTypes, b.dataPtrType) // closure
|
||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||
@@ -695,8 +695,8 @@ func (b *builder) createRunDefers() {
|
||||
|
||||
//Get signature from call results
|
||||
params := callback.Type().Underlying().(*types.Signature).Params()
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
|
||||
for v := range params.Variables() {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(v.Type()))
|
||||
}
|
||||
|
||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||
|
||||
+2
-2
@@ -81,8 +81,8 @@ func (c *compilerContext) getLLVMFunctionType(typ *types.Signature) llvm.Type {
|
||||
paramTypes = append(paramTypes, info.llvmType)
|
||||
}
|
||||
}
|
||||
for i := 0; i < typ.Params().Len(); i++ {
|
||||
subType := c.getLLVMType(typ.Params().At(i).Type())
|
||||
for v := range typ.Params().Variables() {
|
||||
subType := c.getLLVMType(v.Type())
|
||||
for _, info := range c.expandFormalParamType(subType, "", nil) {
|
||||
paramTypes = append(paramTypes, info.llvmType)
|
||||
}
|
||||
|
||||
+4
-8
@@ -5,6 +5,7 @@ package compiler
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"slices"
|
||||
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"tinygo.org/x/go-llvm"
|
||||
@@ -88,7 +89,7 @@ func (b *builder) trackValue(value llvm.Value) {
|
||||
return
|
||||
}
|
||||
numElements := typ.StructElementTypesCount()
|
||||
for i := 0; i < numElements; i++ {
|
||||
for i := range numElements {
|
||||
subValue := b.CreateExtractValue(value, i, "")
|
||||
b.trackValue(subValue)
|
||||
}
|
||||
@@ -97,7 +98,7 @@ func (b *builder) trackValue(value llvm.Value) {
|
||||
return
|
||||
}
|
||||
numElements := typ.ArrayLength()
|
||||
for i := 0; i < numElements; i++ {
|
||||
for i := range numElements {
|
||||
subValue := b.CreateExtractValue(value, i, "")
|
||||
b.trackValue(subValue)
|
||||
}
|
||||
@@ -118,12 +119,7 @@ func typeHasPointers(t llvm.Type) bool {
|
||||
case llvm.PointerTypeKind:
|
||||
return true
|
||||
case llvm.StructTypeKind:
|
||||
for _, subType := range t.StructElementTypes() {
|
||||
if typeHasPointers(subType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.ContainsFunc(t.StructElementTypes(), typeHasPointers)
|
||||
case llvm.ArrayTypeKind:
|
||||
if t.ArrayLength() == 0 {
|
||||
return false
|
||||
|
||||
@@ -414,7 +414,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
|
||||
// Extract parameters from the state object, and call the function
|
||||
// that's being wrapped.
|
||||
var callParams []llvm.Value
|
||||
for i := 0; i < numParams; i++ {
|
||||
for i := range numParams {
|
||||
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
|
||||
|
||||
+12
-10
@@ -146,13 +146,14 @@ func (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error
|
||||
llvmArgs := []llvm.Value{}
|
||||
argTypes := []llvm.Type{}
|
||||
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||
constraints := "={r0}"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={r0}")
|
||||
for i, arg := range args[1:] {
|
||||
arg = arg.(*ssa.MakeInterface).X
|
||||
if i == 0 {
|
||||
constraints += ",0"
|
||||
constraints.WriteString(",0")
|
||||
} else {
|
||||
constraints += ",{r" + strconv.Itoa(i) + "}"
|
||||
constraints.WriteString(",{r" + strconv.Itoa(i) + "}")
|
||||
}
|
||||
llvmValue := b.getValue(arg, pos)
|
||||
llvmArgs = append(llvmArgs, llvmValue)
|
||||
@@ -161,9 +162,9 @@ func (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error
|
||||
// Implement the ARM calling convention by marking r1-r3 as
|
||||
// clobbered. r0 is used as an output register so doesn't have to be
|
||||
// marked as clobbered.
|
||||
constraints += ",~{r1},~{r2},~{r3}"
|
||||
constraints.WriteString(",~{r1},~{r2},~{r3}")
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, false, 0, false)
|
||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
@@ -184,13 +185,14 @@ func (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, err
|
||||
llvmArgs := []llvm.Value{}
|
||||
argTypes := []llvm.Type{}
|
||||
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||
constraints := "={x0}"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={x0}")
|
||||
for i, arg := range args[1:] {
|
||||
arg = arg.(*ssa.MakeInterface).X
|
||||
if i == 0 {
|
||||
constraints += ",0"
|
||||
constraints.WriteString(",0")
|
||||
} else {
|
||||
constraints += ",{x" + strconv.Itoa(i) + "}"
|
||||
constraints.WriteString(",{x" + strconv.Itoa(i) + "}")
|
||||
}
|
||||
llvmValue := b.getValue(arg, pos)
|
||||
llvmArgs = append(llvmArgs, llvmValue)
|
||||
@@ -199,9 +201,9 @@ func (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, err
|
||||
// Implement the ARM64 calling convention by marking x1-x7 as
|
||||
// clobbered. x0 is used as an output register so doesn't have to be
|
||||
// marked as clobbered.
|
||||
constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
|
||||
constraints.WriteString(",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}")
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, false, 0, false)
|
||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
|
||||
+42
-42
@@ -145,8 +145,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||
// For a non-interface type, it returns the number of exported methods.
|
||||
// For an interface type, it returns the number of exported and unexported methods.
|
||||
var numMethods int
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
if isInterface || ms.At(i).Obj().Exported() {
|
||||
for method := range ms.Methods() {
|
||||
if isInterface || method.Obj().Exported() {
|
||||
numMethods++
|
||||
}
|
||||
}
|
||||
@@ -193,8 +193,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||
}
|
||||
// Compute the method set value for types that support methods.
|
||||
var methods []*types.Func
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
methods = append(methods, ms.At(i).Obj().(*types.Func))
|
||||
for method := range ms.Methods() {
|
||||
methods = append(methods, method.Obj().(*types.Func))
|
||||
}
|
||||
methodSetType := types.NewStruct([]*types.Var{
|
||||
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
|
||||
@@ -490,10 +490,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||
c.getTypeMethodSet(typ),
|
||||
}, typeFields...)
|
||||
}
|
||||
alignment := c.targetData.TypeAllocSize(c.dataPtrType)
|
||||
if alignment < 4 {
|
||||
alignment = 4
|
||||
}
|
||||
alignment := max(c.targetData.TypeAllocSize(c.dataPtrType), 4)
|
||||
globalValue := c.ctx.ConstStruct(typeFields, false)
|
||||
global.SetInitializer(globalValue)
|
||||
if isLocal {
|
||||
@@ -783,12 +780,12 @@ func (c *compilerContext) scanLocalTypes(ssaPkg *ssa.Package) {
|
||||
walk(m, false)
|
||||
case *ssa.Type:
|
||||
mset := c.program.MethodSets.MethodSet(m.Type())
|
||||
for i := 0; i < mset.Len(); i++ {
|
||||
walk(c.program.MethodValue(mset.At(i)), false)
|
||||
for method := range mset.Methods() {
|
||||
walk(c.program.MethodValue(method), false)
|
||||
}
|
||||
pmset := c.program.MethodSets.MethodSet(types.NewPointer(m.Type()))
|
||||
for i := 0; i < pmset.Len(); i++ {
|
||||
walk(c.program.MethodValue(pmset.At(i)), false)
|
||||
for method := range pmset.Methods() {
|
||||
walk(c.program.MethodValue(method), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -846,8 +843,8 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
||||
}
|
||||
}
|
||||
targs := t.TypeArgs()
|
||||
for i := 0; i < targs.Len(); i++ {
|
||||
visit(targs.At(i))
|
||||
for t := range targs.Types() {
|
||||
visit(t)
|
||||
}
|
||||
visit(t.Underlying())
|
||||
case *types.Pointer:
|
||||
@@ -862,23 +859,23 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
||||
visit(t.Key())
|
||||
visit(t.Elem())
|
||||
case *types.Struct:
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
visit(t.Field(i).Type())
|
||||
for field := range t.Fields() {
|
||||
visit(field.Type())
|
||||
}
|
||||
case *types.Signature:
|
||||
if p := t.Params(); p != nil {
|
||||
for i := 0; i < p.Len(); i++ {
|
||||
visit(p.At(i).Type())
|
||||
for v := range p.Variables() {
|
||||
visit(v.Type())
|
||||
}
|
||||
}
|
||||
if r := t.Results(); r != nil {
|
||||
for i := 0; i < r.Len(); i++ {
|
||||
visit(r.At(i).Type())
|
||||
for v := range r.Variables() {
|
||||
visit(v.Type())
|
||||
}
|
||||
}
|
||||
case *types.Tuple:
|
||||
for i := 0; i < t.Len(); i++ {
|
||||
visit(t.At(i).Type())
|
||||
for v := range t.Variables() {
|
||||
visit(v.Type())
|
||||
}
|
||||
case *types.Interface:
|
||||
// A synthetic local type can be reachable only through a
|
||||
@@ -887,8 +884,8 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
||||
// the interface's identifier, and the seen map breaks
|
||||
// cycles formed by methods that mention the interface
|
||||
// itself.
|
||||
for i := 0; i < t.NumMethods(); i++ {
|
||||
visit(t.Method(i).Type())
|
||||
for method := range t.Methods() {
|
||||
visit(method.Type())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -939,8 +936,7 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value {
|
||||
|
||||
// Create method set.
|
||||
var signatures, wrappers []llvm.Value
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
method := ms.At(i)
|
||||
for method := range ms.Methods() {
|
||||
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
||||
signatures = append(signatures, signatureGlobal)
|
||||
fn := c.program.MethodValue(method)
|
||||
@@ -1189,8 +1185,8 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
|
||||
if llvmFn.IsNil() {
|
||||
sig := instr.Method.Type().(*types.Signature)
|
||||
var paramTuple []*types.Var
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
paramTuple = append(paramTuple, sig.Params().At(i))
|
||||
for v := range sig.Params().Variables() {
|
||||
paramTuple = append(paramTuple, v)
|
||||
}
|
||||
paramTuple = append(paramTuple, types.NewVar(token.NoPos, nil, "$typecode", types.Typ[types.UnsafePointer]))
|
||||
llvmFnType := c.getLLVMFunctionType(types.NewSignature(sig.Recv(), types.NewTuple(paramTuple...), sig.Results(), false))
|
||||
@@ -1307,34 +1303,38 @@ func methodSignature(method *types.Func) string {
|
||||
// () string
|
||||
// (string, int) (int, error)
|
||||
func signature(sig *types.Signature) string {
|
||||
s := ""
|
||||
var s strings.Builder
|
||||
if sig.Params().Len() == 0 {
|
||||
s += "()"
|
||||
s.WriteString("()")
|
||||
} else {
|
||||
s += "("
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
s.WriteString("(")
|
||||
i := 0
|
||||
for v := range sig.Params().Variables() {
|
||||
if i > 0 {
|
||||
s += ", "
|
||||
s.WriteString(", ")
|
||||
}
|
||||
s += typestring(sig.Params().At(i).Type())
|
||||
s.WriteString(typestring(v.Type()))
|
||||
i++
|
||||
}
|
||||
s += ")"
|
||||
s.WriteString(")")
|
||||
}
|
||||
if sig.Results().Len() == 0 {
|
||||
// keep as-is
|
||||
} else if sig.Results().Len() == 1 {
|
||||
s += " " + typestring(sig.Results().At(0).Type())
|
||||
s.WriteString(" " + typestring(sig.Results().At(0).Type()))
|
||||
} else {
|
||||
s += " ("
|
||||
for i := 0; i < sig.Results().Len(); i++ {
|
||||
s.WriteString(" (")
|
||||
i := 0
|
||||
for v := range sig.Results().Variables() {
|
||||
if i > 0 {
|
||||
s += ", "
|
||||
s.WriteString(", ")
|
||||
}
|
||||
s += typestring(sig.Results().At(i).Type())
|
||||
s.WriteString(typestring(v.Type()))
|
||||
i++
|
||||
}
|
||||
s += ")"
|
||||
s.WriteString(")")
|
||||
}
|
||||
return s
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// typestring returns a stable (human-readable) type string for the given type
|
||||
|
||||
+3
-3
@@ -206,7 +206,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType l
|
||||
globalType := llvm.ArrayType(elementType, len(buf))
|
||||
global := llvm.AddGlobal(c.mod, globalType, name)
|
||||
value := llvm.Undef(globalType)
|
||||
for i := 0; i < len(buf); i++ {
|
||||
for i := range buf {
|
||||
ch := uint64(buf[i])
|
||||
value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, "")
|
||||
}
|
||||
@@ -390,7 +390,7 @@ func (c *compilerContext) buildPointerBitmap(
|
||||
return
|
||||
}
|
||||
elementSize /= ptrAlign
|
||||
for i := 0; i < len; i++ {
|
||||
for i := range len {
|
||||
c.buildPointerBitmap(
|
||||
dst,
|
||||
ptrAlign,
|
||||
@@ -417,7 +417,7 @@ func (c *compilerContext) archFamily() string {
|
||||
// features string is not one for an ARM architecture.
|
||||
func (c *compilerContext) isThumb() bool {
|
||||
var isThumb, isNotThumb bool
|
||||
for _, feature := range strings.Split(c.Features, ",") {
|
||||
for feature := range strings.SplitSeq(c.Features, ",") {
|
||||
if feature == "+thumb-mode" {
|
||||
isThumb = true
|
||||
}
|
||||
|
||||
+6
-4
@@ -7,6 +7,7 @@ import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"strings"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
@@ -293,14 +294,15 @@ func hashmapCanonicalTypeName(t types.Type) string {
|
||||
}
|
||||
return t.String()
|
||||
case *types.Struct:
|
||||
s := "struct{"
|
||||
var s strings.Builder
|
||||
s.WriteString("struct{")
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
if i > 0 {
|
||||
s += "; "
|
||||
s.WriteString("; ")
|
||||
}
|
||||
s += hashmapCanonicalTypeName(t.Field(i).Type())
|
||||
s.WriteString(hashmapCanonicalTypeName(t.Field(i).Type()))
|
||||
}
|
||||
return s + "}"
|
||||
return s.String() + "}"
|
||||
case *types.Array:
|
||||
return fmt.Sprintf("[%d]%s", t.Len(), hashmapCanonicalTypeName(t.Elem()))
|
||||
}
|
||||
|
||||
+1
-2
@@ -29,8 +29,7 @@ func (s *stdSizes) Alignof(T types.Type) int64 {
|
||||
// is the largest of the values unsafe.Alignof(x.f) for each
|
||||
// field f of x, but at least 1."
|
||||
max := int64(1)
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
f := t.Field(i)
|
||||
for f := range t.Fields() {
|
||||
if a := s.Alignof(f.Type()); a > max {
|
||||
max = a
|
||||
}
|
||||
|
||||
+13
-25
@@ -8,6 +8,7 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -85,8 +86,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
||||
retType = c.getLLVMType(fn.Signature.Results().At(0).Type())
|
||||
} else {
|
||||
results := make([]llvm.Type, 0, fn.Signature.Results().Len())
|
||||
for i := 0; i < fn.Signature.Results().Len(); i++ {
|
||||
results = append(results, c.getLLVMType(fn.Signature.Results().At(i).Type()))
|
||||
for v := range fn.Signature.Results().Variables() {
|
||||
results = append(results, c.getLLVMType(v.Type()))
|
||||
}
|
||||
retType = c.ctx.StructType(results, false)
|
||||
}
|
||||
@@ -389,7 +390,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
||||
info.wasmName = info.linkName
|
||||
info.exported = true
|
||||
case "//go:interrupt":
|
||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||
info.interrupt = true
|
||||
}
|
||||
case "//go:wasm-module":
|
||||
@@ -451,14 +452,14 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
||||
// This is a slightly looser requirement than what gc uses: gc
|
||||
// requires the file to import "unsafe", not the package as a
|
||||
// whole.
|
||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||
info.linkName = parts[2]
|
||||
}
|
||||
case "//go:section":
|
||||
// Only enable go:section when the package imports "unsafe".
|
||||
// go:section also implies go:noinline since inlining could
|
||||
// move the code to a different section than that requested.
|
||||
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
|
||||
if len(parts) == 2 && slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||
info.section = parts[1]
|
||||
info.inline = inlineNone
|
||||
}
|
||||
@@ -467,7 +468,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
||||
// runtime functions.
|
||||
// This is somewhat dangerous and thus only imported in packages
|
||||
// that import unsafe.
|
||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||
info.nobounds = true
|
||||
}
|
||||
case "//go:noescape":
|
||||
@@ -567,8 +568,8 @@ func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
|
||||
hasHostLayout = false // package structs added in go1.23
|
||||
}
|
||||
}
|
||||
for i := 0; i < typ.NumFields(); i++ {
|
||||
ftyp := typ.Field(i).Type()
|
||||
for field := range typ.Fields() {
|
||||
ftyp := field.Type()
|
||||
if types.Unalias(ftyp).String() == "structs.HostLayout" {
|
||||
hasHostLayout = true
|
||||
continue
|
||||
@@ -600,8 +601,8 @@ func getParams(sig *types.Signature) []*types.Var {
|
||||
if sig.Recv() != nil {
|
||||
params = append(params, sig.Recv())
|
||||
}
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
params = append(params, sig.Params().At(i))
|
||||
for v := range sig.Params().Variables() {
|
||||
params = append(params, v)
|
||||
}
|
||||
return params
|
||||
}
|
||||
@@ -704,10 +705,7 @@ func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {
|
||||
llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName)
|
||||
|
||||
// Set alignment from the //go:align comment.
|
||||
alignment := c.targetData.ABITypeAlignment(llvmType)
|
||||
if info.align > alignment {
|
||||
alignment = info.align
|
||||
}
|
||||
alignment := max(info.align, c.targetData.ABITypeAlignment(llvmType))
|
||||
if alignment <= 0 || alignment&(alignment-1) != 0 {
|
||||
// Check for power-of-two (or 0).
|
||||
// See: https://stackoverflow.com/a/108360
|
||||
@@ -781,7 +779,7 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext,
|
||||
// This is a slightly looser requirement than what gc uses: gc
|
||||
// requires the file to import "unsafe", not the package as a
|
||||
// whole.
|
||||
if hasUnsafeImport(g.Pkg.Pkg) {
|
||||
if slices.Contains(g.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||
info.linkName = parts[2]
|
||||
}
|
||||
}
|
||||
@@ -797,13 +795,3 @@ func getAllMethods(prog *ssa.Program, typ types.Type) []*types.Selection {
|
||||
}
|
||||
return methods
|
||||
}
|
||||
|
||||
// Return true if this package imports "unsafe", false otherwise.
|
||||
func hasUnsafeImport(pkg *types.Package) bool {
|
||||
for _, imp := range pkg.Imports() {
|
||||
if imp == types.Unsafe {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+32
-27
@@ -26,24 +26,25 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
argTypes := []llvm.Type{b.uintptrType}
|
||||
// Constraints will look something like:
|
||||
// "={rax},0,{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11}"
|
||||
constraints := "={rax},0"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={rax},0")
|
||||
for i, arg := range call.Args[1:] {
|
||||
constraints += "," + [...]string{
|
||||
constraints.WriteString("," + [...]string{
|
||||
"{rdi}",
|
||||
"{rsi}",
|
||||
"{rdx}",
|
||||
"{r10}",
|
||||
"{r8}",
|
||||
"{r9}",
|
||||
}[i]
|
||||
}[i])
|
||||
llvmValue := b.getValue(arg, getPos(call))
|
||||
args = append(args, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
}
|
||||
// rcx and r11 are clobbered by the syscall, so make sure they are not used
|
||||
constraints += ",~{rcx},~{r11}"
|
||||
constraints.WriteString(",~{rcx},~{r11}")
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
||||
target := llvm.InlineAsm(fnType, "syscall", constraints.String(), true, false, llvm.InlineAsmDialectIntel, false)
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
|
||||
case b.GOARCH == "386" && b.GOOS == "linux":
|
||||
@@ -55,22 +56,23 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
argTypes := []llvm.Type{b.uintptrType}
|
||||
// Constraints will look something like:
|
||||
// "={eax},0,{ebx},{ecx},{edx},{esi},{edi},{ebp}"
|
||||
constraints := "={eax},0"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={eax},0")
|
||||
for i, arg := range call.Args[1:] {
|
||||
constraints += "," + [...]string{
|
||||
constraints.WriteString("," + [...]string{
|
||||
"{ebx}",
|
||||
"{ecx}",
|
||||
"{edx}",
|
||||
"{esi}",
|
||||
"{edi}",
|
||||
"{ebp}",
|
||||
}[i]
|
||||
}[i])
|
||||
llvmValue := b.getValue(arg, getPos(call))
|
||||
args = append(args, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
}
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
||||
target := llvm.InlineAsm(fnType, "int 0x80", constraints.String(), true, false, llvm.InlineAsmDialectIntel, false)
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
|
||||
case b.GOARCH == "arm" && b.GOOS == "linux":
|
||||
@@ -88,9 +90,10 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
argTypes := []llvm.Type{}
|
||||
// Constraints will look something like:
|
||||
// ={r0},0,{r1},{r2},{r7},~{r3}
|
||||
constraints := "={r0}"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={r0}")
|
||||
for i, arg := range call.Args[1:] {
|
||||
constraints += "," + [...]string{
|
||||
constraints.WriteString("," + [...]string{
|
||||
"0", // tie to output
|
||||
"{r1}",
|
||||
"{r2}",
|
||||
@@ -98,20 +101,20 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
"{r4}",
|
||||
"{r5}",
|
||||
"{r6}",
|
||||
}[i]
|
||||
}[i])
|
||||
llvmValue := b.getValue(arg, getPos(call))
|
||||
args = append(args, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
}
|
||||
args = append(args, num)
|
||||
argTypes = append(argTypes, b.uintptrType)
|
||||
constraints += ",{r7}" // syscall number
|
||||
constraints.WriteString(",{r7}") // syscall number
|
||||
for i := len(call.Args) - 1; i < 4; i++ {
|
||||
// r0-r3 get clobbered after the syscall returns
|
||||
constraints += ",~{r" + strconv.Itoa(i) + "}"
|
||||
constraints.WriteString(",~{r" + strconv.Itoa(i) + "}")
|
||||
}
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints.String(), true, false, 0, false)
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
|
||||
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
||||
@@ -120,31 +123,32 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
argTypes := []llvm.Type{}
|
||||
// Constraints will look something like:
|
||||
// ={x0},0,{x1},{x2},{x8},~{x3},~{x4},~{x5},~{x6},~{x7},~{x16},~{x17}
|
||||
constraints := "={x0}"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={x0}")
|
||||
for i, arg := range call.Args[1:] {
|
||||
constraints += "," + [...]string{
|
||||
constraints.WriteString("," + [...]string{
|
||||
"0", // tie to output
|
||||
"{x1}",
|
||||
"{x2}",
|
||||
"{x3}",
|
||||
"{x4}",
|
||||
"{x5}",
|
||||
}[i]
|
||||
}[i])
|
||||
llvmValue := b.getValue(arg, getPos(call))
|
||||
args = append(args, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
}
|
||||
args = append(args, num)
|
||||
argTypes = append(argTypes, b.uintptrType)
|
||||
constraints += ",{x8}" // syscall number
|
||||
constraints.WriteString(",{x8}") // syscall number
|
||||
for i := len(call.Args) - 1; i < 8; i++ {
|
||||
// x0-x7 may get clobbered during the syscall following the aarch64
|
||||
// calling convention.
|
||||
constraints += ",~{x" + strconv.Itoa(i) + "}"
|
||||
constraints.WriteString(",~{x" + strconv.Itoa(i) + "}")
|
||||
}
|
||||
constraints += ",~{x16},~{x17}" // scratch registers
|
||||
constraints.WriteString(",~{x16},~{x17}") // scratch registers
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints.String(), true, false, 0, false)
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
|
||||
case (b.GOARCH == "mips" || b.GOARCH == "mipsle") && b.GOOS == "linux":
|
||||
@@ -163,7 +167,8 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
// faster and smaller code.
|
||||
args := []llvm.Value{num}
|
||||
argTypes := []llvm.Type{b.uintptrType}
|
||||
constraints := "={$2},={$7},0"
|
||||
var constraints strings.Builder
|
||||
constraints.WriteString("={$2},={$7},0")
|
||||
syscallParams := call.Args[1:]
|
||||
if len(syscallParams) > 7 {
|
||||
// There is one syscall that uses 7 parameters: sync_file_range.
|
||||
@@ -172,7 +177,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
syscallParams = syscallParams[:7]
|
||||
}
|
||||
for i, arg := range syscallParams {
|
||||
constraints += "," + [...]string{
|
||||
constraints.WriteString("," + [...]string{
|
||||
"{$4}", // arg1
|
||||
"{$5}", // arg2
|
||||
"{$6}", // arg3
|
||||
@@ -180,7 +185,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
"r", // arg5 on the stack
|
||||
"r", // arg6 on the stack
|
||||
"r", // arg7 on the stack
|
||||
}[i]
|
||||
}[i])
|
||||
llvmValue := b.getValue(arg, getPos(call))
|
||||
args = append(args, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
@@ -221,10 +226,10 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||
"addu $$sp, $$sp, 32\n" +
|
||||
".set at\n"
|
||||
}
|
||||
constraints += ",~{$3},~{$4},~{$5},~{$6},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$24},~{$25},~{hi},~{lo},~{memory}"
|
||||
constraints.WriteString(",~{$3},~{$4},~{$5},~{$6},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$24},~{$25},~{hi},~{lo},~{memory}")
|
||||
returnType := b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false)
|
||||
fnType := llvm.FunctionType(returnType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, true, 0, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, true, 0, false)
|
||||
call := b.CreateCall(fnType, target, args, "")
|
||||
resultCode := b.CreateExtractValue(call, 0, "") // r2
|
||||
errorFlag := b.CreateExtractValue(call, 1, "") // r7
|
||||
|
||||
Reference in New Issue
Block a user