detached f389379

all: use range-over-int in counting loops (#503)

Go 1.22 added range over an integer, which reads better than the
three-clause form and evaluates the limit once rather than on every
iteration. Convert the loops that translate directly, most of them
walking reflect fields or function arguments.

The calls used as limits (NumIn, NumField, Len, NumCPU, numABIFields)
are all pure, so evaluating them once does not change behavior.

Loops that a range cannot express are left as they are: the 8-byte
strides in copyStruct8ByteChunks, placeStack and addStruct, the field
scan in getStruct on amd64 whose index is read after the loop, the
compound condition in setStruct, and the one-based loops in objc that
skip the self and _cmd arguments.

wincallback.go generates the zcallback_*.s files; regenerating with
the converted loops reproduces all eight of them byte for byte.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
commit
f389379c2c90cd438fbb31fb68636ada958a9fcb
author
Hajime Hoshi · · 2026-08-29 11:17 UTC
committer
GitHub · · 2026-08-29 11:17 UTC
parent
749871c
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
13 files · +37 -37
M func.go +5 -5
@@ -151,14 +151,14 @@ func RegisterFunc(fptr any, cfn uintptr) {
151151 floatArgRegs := numOfFloatRegisters()
152152 ptrSize := unsafe.Sizeof(uintptr(0))
153153 var stack int
154- for i := 0; i < ty.NumIn(); i++ {
154+ for i := range ty.NumIn() {
155155 arg := ty.In(i)
156156 switch arg.Kind() {
157157 case reflect.Func:
158158 // This only does preliminary testing to ensure the CDecl argument
159159 // is the first argument. Full testing is done when the callback is actually
160160 // created in NewCallback.
161- for j := 0; j < arg.NumIn(); j++ {
161+ for j := range arg.NumIn() {
162162 in := arg.In(j)
163163 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {
164164 continue
@@ -607,7 +607,7 @@ func isAllSameFloat(ty reflect.Type) (allFloats bool, numFields int) {
607607 if first != reflect.Float32 && first != reflect.Float64 {
608608 allFloats = false
609609 }
610- for i := 0; i < ty.NumField(); i++ {
610+ for i := range ty.NumField() {
611611 if !isABIField(ty.Field(i)) {
612612 continue
613613 }
@@ -627,7 +627,7 @@ func isAllSameFloat(ty reflect.Type) (allFloats bool, numFields int) {
627627 }
628628
629629 func checkStructFieldsSupported(ty reflect.Type) {
630- for i := 0; i < ty.NumField(); i++ {
630+ for i := range ty.NumField() {
631631 if !isABIField(ty.Field(i)) {
632632 continue
633633 }
@@ -732,7 +732,7 @@ func estimateStackBytes(ty reflect.Type) int {
732732 var numInts, numFloats int
733733 var stackBytes int
734734
735- for i := 0; i < ty.NumIn(); i++ {
735+ for i := range ty.NumIn() {
736736 arg := ty.In(i)
737737 size := int(arg.Size())
738738
@@ -151,14 +151,14 @@ func RegisterFunc(fptr any, cfn uintptr) {
151 floatArgRegs := numOfFloatRegisters()151 floatArgRegs := numOfFloatRegisters()
152 ptrSize := unsafe.Sizeof(uintptr(0))152 ptrSize := unsafe.Sizeof(uintptr(0))
153 var stack int153 var stack int
154- for i := 0; i < ty.NumIn(); i++ {154+ for i := range ty.NumIn() {
155 arg := ty.In(i)155 arg := ty.In(i)
156 switch arg.Kind() {156 switch arg.Kind() {
157 case reflect.Func:157 case reflect.Func:
158 // This only does preliminary testing to ensure the CDecl argument158 // This only does preliminary testing to ensure the CDecl argument
159 // is the first argument. Full testing is done when the callback is actually159 // is the first argument. Full testing is done when the callback is actually
160 // created in NewCallback.160 // created in NewCallback.
161- for j := 0; j < arg.NumIn(); j++ {161+ for j := range arg.NumIn() {
162 in := arg.In(j)162 in := arg.In(j)
163 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {163 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {
164 continue164 continue
@@ -607,7 +607,7 @@ func isAllSameFloat(ty reflect.Type) (allFloats bool, numFields int) {
607 if first != reflect.Float32 && first != reflect.Float64 {607 if first != reflect.Float32 && first != reflect.Float64 {
608 allFloats = false608 allFloats = false
609 }609 }
610- for i := 0; i < ty.NumField(); i++ {610+ for i := range ty.NumField() {
611 if !isABIField(ty.Field(i)) {611 if !isABIField(ty.Field(i)) {
612 continue612 continue
613 }613 }
@@ -627,7 +627,7 @@ func isAllSameFloat(ty reflect.Type) (allFloats bool, numFields int) {
627 }627 }
628 628
629 func checkStructFieldsSupported(ty reflect.Type) {629 func checkStructFieldsSupported(ty reflect.Type) {
630- for i := 0; i < ty.NumField(); i++ {630+ for i := range ty.NumField() {
631 if !isABIField(ty.Field(i)) {631 if !isABIField(ty.Field(i)) {
632 continue632 continue
633 }633 }
@@ -732,7 +732,7 @@ func estimateStackBytes(ty reflect.Type) int {
732 var numInts, numFloats int732 var numInts, numFloats int
733 var stackBytes int733 var stackBytes int
734 734
735- for i := 0; i < ty.NumIn(); i++ {735+ for i := range ty.NumIn() {
736 arg := ty.In(i)736 arg := ty.In(i)
737 size := int(arg.Size())737 size := int(arg.Size())
738 738
M func_test.go +1 -1
@@ -60,7 +60,7 @@ func TestRegisterFunc_ConcurrentPointerReturn(t *testing.T) {
6060
6161 var wg sync.WaitGroup
6262
63- for i := 0; i < runtime.NumCPU(); i++ {
63+ for i := range runtime.NumCPU() {
6464 wg.Add(1)
6565 go func(id int) {
6666 defer wg.Done()
@@ -60,7 +60,7 @@ func TestRegisterFunc_ConcurrentPointerReturn(t *testing.T) {
60 60
61 var wg sync.WaitGroup61 var wg sync.WaitGroup
62 62
63- for i := 0; i < runtime.NumCPU(); i++ {63+ for i := range runtime.NumCPU() {
64 wg.Add(1)64 wg.Add(1)
65 go func(id int) {65 go func(id int) {
66 defer wg.Done()66 defer wg.Done()
M internal/fakecgo/go_libinit.go +1 -1
@@ -52,7 +52,7 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe
5252 tries := ts.Nsec
5353 var err int
5454
55- for tries = 0; tries < 20; tries++ {
55+ for tries = range 20 {
5656 // inlined this call because it ran out of stack when inlining was disabled
5757 err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0))
5858 if err == 0 {
@@ -52,7 +52,7 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe
52 tries := ts.Nsec52 tries := ts.Nsec
53 var err int53 var err int
54 54
55- for tries = 0; tries < 20; tries++ {55+ for tries = range 20 {
56 // inlined this call because it ran out of stack when inlining was disabled56 // inlined this call because it ran out of stack when inlining was disabled
57 err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0))57 err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0))
58 if err == 0 {58 if err == 0 {
M objc/objc_runtime_darwin.go +1 -1
@@ -472,7 +472,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) {
472472 encoding.WriteString(encStructBegin)
473473 encoding.WriteString(typ.Name())
474474 encoding.WriteString("=")
475- for i := 0; i < typ.NumField(); i++ {
475+ for i := range typ.NumField() {
476476 f := typ.Field(i)
477477 if f.Type.ConvertibleTo(hostLayoutType) {
478478 // The structs.HostLayout marker is a signal to the Go compiler
@@ -472,7 +472,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) {
472 encoding.WriteString(encStructBegin)472 encoding.WriteString(encStructBegin)
473 encoding.WriteString(typ.Name())473 encoding.WriteString(typ.Name())
474 encoding.WriteString("=")474 encoding.WriteString("=")
475- for i := 0; i < typ.NumField(); i++ {475+ for i := range typ.NumField() {
476 f := typ.Field(i)476 f := typ.Field(i)
477 if f.Type.ConvertibleTo(hostLayoutType) {477 if f.Type.ConvertibleTo(hostLayoutType) {
478 // The structs.HostLayout marker is a signal to the Go compiler478 // The structs.HostLayout marker is a signal to the Go compiler
M struct_amd64.go +6 -6
@@ -100,7 +100,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
100100 }
101101
102102 func isAllFloats(ty reflect.Type) bool {
103- for i := 0; i < ty.NumField(); i++ {
103+ for i := range ty.NumField() {
104104 f := ty.Field(i)
105105 if !isABIField(f) {
106106 continue
@@ -220,7 +220,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp
220220 numFields = v.Type().Len()
221221 }
222222
223- for i := 0; i < numFields; i++ {
223+ for i := range numFields {
224224 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(i)) {
225225 continue
226226 }
@@ -390,7 +390,7 @@ func getCallbackStruct(inType reflect.Type, frame unsafe.Pointer, floatsN *int,
390390
391391 // Count how many integer and SSE registers this struct needs.
392392 var needInts, needFloats int
393- for i := 0; i < numEightbytes; i++ {
393+ for i := range numEightbytes {
394394 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)
395395 if class == _SSE {
396396 needFloats++
@@ -408,7 +408,7 @@ func getCallbackStruct(inType reflect.Type, frame unsafe.Pointer, floatsN *int,
408408
409409 // Read each eightbyte from its appropriate register class.
410410 var r1, r2 uintptr
411- for i := 0; i < numEightbytes; i++ {
411+ for i := range numEightbytes {
412412 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)
413413 if class == _SSE {
414414 if i == 0 {
@@ -490,7 +490,7 @@ func doClassifyEightbyte(t reflect.Type, base, start, end uintptr) int {
490490 switch t.Kind() {
491491 case reflect.Struct:
492492 class := _NO_CLASS
493- for i := 0; i < t.NumField(); i++ {
493+ for i := range t.NumField() {
494494 f := t.Field(i)
495495 class |= doClassifyEightbyte(f.Type, base+f.Offset, start, end)
496496 }
@@ -498,7 +498,7 @@ func doClassifyEightbyte(t reflect.Type, base, start, end uintptr) int {
498498 case reflect.Array:
499499 class := _NO_CLASS
500500 elemSize := t.Elem().Size()
501- for i := 0; i < t.Len(); i++ {
501+ for i := range t.Len() {
502502 class |= doClassifyEightbyte(t.Elem(), base+uintptr(i)*elemSize, start, end)
503503 }
504504 return class
@@ -100,7 +100,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
100 }100 }
101 101
102 func isAllFloats(ty reflect.Type) bool {102 func isAllFloats(ty reflect.Type) bool {
103- for i := 0; i < ty.NumField(); i++ {103+ for i := range ty.NumField() {
104 f := ty.Field(i)104 f := ty.Field(i)
105 if !isABIField(f) {105 if !isABIField(f) {
106 continue106 continue
@@ -220,7 +220,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp
220 numFields = v.Type().Len()220 numFields = v.Type().Len()
221 }221 }
222 222
223- for i := 0; i < numFields; i++ {223+ for i := range numFields {
224 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(i)) {224 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(i)) {
225 continue225 continue
226 }226 }
@@ -390,7 +390,7 @@ func getCallbackStruct(inType reflect.Type, frame unsafe.Pointer, floatsN *int,
390 390
391 // Count how many integer and SSE registers this struct needs.391 // Count how many integer and SSE registers this struct needs.
392 var needInts, needFloats int392 var needInts, needFloats int
393- for i := 0; i < numEightbytes; i++ {393+ for i := range numEightbytes {
394 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)394 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)
395 if class == _SSE {395 if class == _SSE {
396 needFloats++396 needFloats++
@@ -408,7 +408,7 @@ func getCallbackStruct(inType reflect.Type, frame unsafe.Pointer, floatsN *int,
408 408
409 // Read each eightbyte from its appropriate register class.409 // Read each eightbyte from its appropriate register class.
410 var r1, r2 uintptr410 var r1, r2 uintptr
411- for i := 0; i < numEightbytes; i++ {411+ for i := range numEightbytes {
412 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)412 class := classifyEightbyte(inType, uintptr(i)*8, uintptr(i)*8+8)
413 if class == _SSE {413 if class == _SSE {
414 if i == 0 {414 if i == 0 {
@@ -490,7 +490,7 @@ func doClassifyEightbyte(t reflect.Type, base, start, end uintptr) int {
490 switch t.Kind() {490 switch t.Kind() {
491 case reflect.Struct:491 case reflect.Struct:
492 class := _NO_CLASS492 class := _NO_CLASS
493- for i := 0; i < t.NumField(); i++ {493+ for i := range t.NumField() {
494 f := t.Field(i)494 f := t.Field(i)
495 class |= doClassifyEightbyte(f.Type, base+f.Offset, start, end)495 class |= doClassifyEightbyte(f.Type, base+f.Offset, start, end)
496 }496 }
@@ -498,7 +498,7 @@ func doClassifyEightbyte(t reflect.Type, base, start, end uintptr) int {
498 case reflect.Array:498 case reflect.Array:
499 class := _NO_CLASS499 class := _NO_CLASS
500 elemSize := t.Elem().Size()500 elemSize := t.Elem().Size()
501- for i := 0; i < t.Len(); i++ {501+ for i := range t.Len() {
502 class |= doClassifyEightbyte(t.Elem(), base+uintptr(i)*elemSize, start, end)502 class |= doClassifyEightbyte(t.Elem(), base+uintptr(i)*elemSize, start, end)
503 }503 }
504 return class504 return class
M struct_arm64.go +5 -5
@@ -119,7 +119,7 @@ func placeRegistersArm64(v reflect.Value, addFloat func(uintptr), addInt func(ui
119119 } else {
120120 numFields = v.Type().Len()
121121 }
122- for k := 0; k < numFields; k++ {
122+ for k := range numFields {
123123 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(k)) {
124124 continue
125125 }
@@ -249,7 +249,7 @@ func isHFA(t reflect.Type) bool {
249249 switch first.Type.Kind() {
250250 case reflect.Float32, reflect.Float64:
251251 firstKind := first.Type.Kind()
252- for i := 0; i < numFields; i++ {
252+ for i := range numFields {
253253 if abiField(t, i).Type.Kind() != firstKind {
254254 return false
255255 }
@@ -263,7 +263,7 @@ func isHFA(t reflect.Type) bool {
263263 return false
264264 }
265265 case reflect.Struct:
266- for i := 0; i < numABIFields(first.Type); i++ {
266+ for range numABIFields(first.Type) {
267267 if !isHFA(first.Type) {
268268 return false
269269 }
@@ -292,7 +292,7 @@ func isHVA(t reflect.Type) bool {
292292 switch first.Type.Kind() {
293293 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
294294 firstKind := first.Type.Kind()
295- for i := 0; i < numFields; i++ {
295+ for i := range numFields {
296296 if abiField(t, i).Type.Kind() != firstKind {
297297 return false
298298 }
@@ -546,7 +546,7 @@ func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
546546
547547 // Set values (skip padding fields)
548548 argIndex := 0
549- for j := 0; j < structInstance.NumField(); j++ {
549+ for j := range structInstance.NumField() {
550550 fieldName := structType.Field(j).Name
551551 if stdstrings.HasPrefix(fieldName, paddingFieldPrefix) {
552552 continue
@@ -119,7 +119,7 @@ func placeRegistersArm64(v reflect.Value, addFloat func(uintptr), addInt func(ui
119 } else {119 } else {
120 numFields = v.Type().Len()120 numFields = v.Type().Len()
121 }121 }
122- for k := 0; k < numFields; k++ {122+ for k := range numFields {
123 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(k)) {123 if v.Kind() == reflect.Struct && !isABIField(v.Type().Field(k)) {
124 continue124 continue
125 }125 }
@@ -249,7 +249,7 @@ func isHFA(t reflect.Type) bool {
249 switch first.Type.Kind() {249 switch first.Type.Kind() {
250 case reflect.Float32, reflect.Float64:250 case reflect.Float32, reflect.Float64:
251 firstKind := first.Type.Kind()251 firstKind := first.Type.Kind()
252- for i := 0; i < numFields; i++ {252+ for i := range numFields {
253 if abiField(t, i).Type.Kind() != firstKind {253 if abiField(t, i).Type.Kind() != firstKind {
254 return false254 return false
255 }255 }
@@ -263,7 +263,7 @@ func isHFA(t reflect.Type) bool {
263 return false263 return false
264 }264 }
265 case reflect.Struct:265 case reflect.Struct:
266- for i := 0; i < numABIFields(first.Type); i++ {266+ for range numABIFields(first.Type) {
267 if !isHFA(first.Type) {267 if !isHFA(first.Type) {
268 return false268 return false
269 }269 }
@@ -292,7 +292,7 @@ func isHVA(t reflect.Type) bool {
292 switch first.Type.Kind() {292 switch first.Type.Kind() {
293 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:293 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
294 firstKind := first.Type.Kind()294 firstKind := first.Type.Kind()
295- for i := 0; i < numFields; i++ {295+ for i := range numFields {
296 if abiField(t, i).Type.Kind() != firstKind {296 if abiField(t, i).Type.Kind() != firstKind {
297 return false297 return false
298 }298 }
@@ -546,7 +546,7 @@ func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
546 546
547 // Set values (skip padding fields)547 // Set values (skip padding fields)
548 argIndex := 0548 argIndex := 0
549- for j := 0; j < structInstance.NumField(); j++ {549+ for j := range structInstance.NumField() {
550 fieldName := structType.Field(j).Name550 fieldName := structType.Field(j).Name
551 if stdstrings.HasPrefix(fieldName, paddingFieldPrefix) {551 if stdstrings.HasPrefix(fieldName, paddingFieldPrefix) {
552 continue552 continue
M struct_riscv64.go +1 -1
@@ -37,7 +37,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
3737 if abiField(outType, 0).Type.Kind() == reflect.Float32 {
3838 // float32 values are NaN-boxed in FP regs; use low 32 bits only
3939 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
40- for i := 0; i < numFields; i++ {
40+ for i := range numFields {
4141 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
4242 }
4343 } else {
@@ -37,7 +37,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
37 if abiField(outType, 0).Type.Kind() == reflect.Float32 {37 if abiField(outType, 0).Type.Kind() == reflect.Float32 {
38 // float32 values are NaN-boxed in FP regs; use low 32 bits only38 // float32 values are NaN-boxed in FP regs; use low 32 bits only
39 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}39 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
40- for i := 0; i < numFields; i++ {40+ for i := range numFields {
41 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])41 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
42 }42 }
43 } else {43 } else {
M struct_s390x.go +1 -1
@@ -37,7 +37,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
3737 if abiField(outType, 0).Type.Kind() == reflect.Float32 {
3838 // float32 values in FP regs
3939 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
40- for i := 0; i < numFields; i++ {
40+ for i := range numFields {
4141 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
4242 }
4343 } else {
@@ -37,7 +37,7 @@ func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
37 if abiField(outType, 0).Type.Kind() == reflect.Float32 {37 if abiField(outType, 0).Type.Kind() == reflect.Float32 {
38 // float32 values in FP regs38 // float32 values in FP regs
39 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}39 f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
40- for i := 0; i < numFields; i++ {40+ for i := range numFields {
41 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])41 *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
42 }42 }
43 } else {43 } else {
M syscall_bench_test.go +3 -3
@@ -116,7 +116,7 @@ func BenchmarkCallingMethods(b *testing.B) {
116116 args := int64sToUintptrs(tc.args)
117117 var result uintptr
118118 b.ResetTimer()
119- for i := 0; i < b.N; i++ {
119+ for range b.N {
120120 result, _, _ = purego.SyscallN(tc.goFnPtr, args...)
121121 }
122122 b.StopTimer()
@@ -135,7 +135,7 @@ func BenchmarkCallingMethods(b *testing.B) {
135135 args := int64sToUintptrs(tc.args)
136136 var result uintptr
137137 b.ResetTimer()
138- for i := 0; i < b.N; i++ {
138+ for range b.N {
139139 result, _, _ = purego.SyscallN(tc.cFnPtr, args...)
140140 }
141141 b.StopTimer()
@@ -165,7 +165,7 @@ func BenchmarkCallingMethods(b *testing.B) {
165165
166166 var result uintptr
167167 b.ResetTimer()
168- for i := 0; i < b.N; i++ {
168+ for range b.N {
169169 result, _, _ = purego.SyscallN(tc.cCallbackPtr, callbackArgs...)
170170 }
171171 b.StopTimer()
@@ -116,7 +116,7 @@ func BenchmarkCallingMethods(b *testing.B) {
116 args := int64sToUintptrs(tc.args)116 args := int64sToUintptrs(tc.args)
117 var result uintptr117 var result uintptr
118 b.ResetTimer()118 b.ResetTimer()
119- for i := 0; i < b.N; i++ {119+ for range b.N {
120 result, _, _ = purego.SyscallN(tc.goFnPtr, args...)120 result, _, _ = purego.SyscallN(tc.goFnPtr, args...)
121 }121 }
122 b.StopTimer()122 b.StopTimer()
@@ -135,7 +135,7 @@ func BenchmarkCallingMethods(b *testing.B) {
135 args := int64sToUintptrs(tc.args)135 args := int64sToUintptrs(tc.args)
136 var result uintptr136 var result uintptr
137 b.ResetTimer()137 b.ResetTimer()
138- for i := 0; i < b.N; i++ {138+ for range b.N {
139 result, _, _ = purego.SyscallN(tc.cFnPtr, args...)139 result, _, _ = purego.SyscallN(tc.cFnPtr, args...)
140 }140 }
141 b.StopTimer()141 b.StopTimer()
@@ -165,7 +165,7 @@ func BenchmarkCallingMethods(b *testing.B) {
165 165
166 var result uintptr166 var result uintptr
167 b.ResetTimer()167 b.ResetTimer()
168- for i := 0; i < b.N; i++ {168+ for range b.N {
169 result, _, _ = purego.SyscallN(tc.cCallbackPtr, callbackArgs...)169 result, _, _ = purego.SyscallN(tc.cCallbackPtr, callbackArgs...)
170 }170 }
171 b.StopTimer()171 b.StopTimer()
M syscall_linux_test.go +2 -2
@@ -192,12 +192,12 @@ func TestDlopenThenAllThreadsSyscall(t *testing.T) {
192192 }
193193
194194 cb := purego.NewCallback(goFunc)
195- for i := 0; i < 10; i++ {
195+ for range 10 {
196196 callCallback(cb, "hello")
197197 }
198198
199199 // Step 2: Generate thread churn + AllThreadsSyscall (via Setuid).
200- for i := 0; i < 20; i++ {
200+ for range 20 {
201201 c := make(chan struct{})
202202 go func() {
203203 runtime.LockOSThread()
@@ -192,12 +192,12 @@ func TestDlopenThenAllThreadsSyscall(t *testing.T) {
192 }192 }
193 193
194 cb := purego.NewCallback(goFunc)194 cb := purego.NewCallback(goFunc)
195- for i := 0; i < 10; i++ {195+ for range 10 {
196 callCallback(cb, "hello")196 callCallback(cb, "hello")
197 }197 }
198 198
199 // Step 2: Generate thread churn + AllThreadsSyscall (via Setuid).199 // Step 2: Generate thread churn + AllThreadsSyscall (via Setuid).
200- for i := 0; i < 20; i++ {200+ for range 20 {
201 c := make(chan struct{})201 c := make(chan struct{})
202 go func() {202 go func() {
203 runtime.LockOSThread()203 runtime.LockOSThread()
M syscall_unix.go +2 -2
@@ -27,7 +27,7 @@ func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
2727 // provides similar functionality to windows.NewCallback it is distinct.
2828 func NewCallback(fn any) uintptr {
2929 ty := reflect.TypeOf(fn)
30- for i := 0; i < ty.NumIn(); i++ {
30+ for i := range ty.NumIn() {
3131 in := ty.In(i)
3232 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {
3333 continue
@@ -58,7 +58,7 @@ func compileCallback(fn any) uintptr {
5858 panic("purego: function must not be nil")
5959 }
6060 ty := val.Type()
61- for i := 0; i < ty.NumIn(); i++ {
61+ for i := range ty.NumIn() {
6262 in := ty.In(i)
6363 switch in.Kind() {
6464 case reflect.Struct:
@@ -27,7 +27,7 @@ func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
27 // provides similar functionality to windows.NewCallback it is distinct.27 // provides similar functionality to windows.NewCallback it is distinct.
28 func NewCallback(fn any) uintptr {28 func NewCallback(fn any) uintptr {
29 ty := reflect.TypeOf(fn)29 ty := reflect.TypeOf(fn)
30- for i := 0; i < ty.NumIn(); i++ {30+ for i := range ty.NumIn() {
31 in := ty.In(i)31 in := ty.In(i)
32 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {32 if !in.AssignableTo(reflect.TypeFor[CDecl]()) {
33 continue33 continue
@@ -58,7 +58,7 @@ func compileCallback(fn any) uintptr {
58 panic("purego: function must not be nil")58 panic("purego: function must not be nil")
59 }59 }
60 ty := val.Type()60 ty := val.Type()
61- for i := 0; i < ty.NumIn(); i++ {61+ for i := range ty.NumIn() {
62 in := ty.In(i)62 in := ty.In(i)
63 switch in.Kind() {63 switch in.Kind() {
64 case reflect.Struct:64 case reflect.Struct:
M syscall_windows.go +1 -1
@@ -26,7 +26,7 @@ func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
2626 func NewCallback(fn any) uintptr {
2727 isCDecl := false
2828 ty := reflect.TypeOf(fn)
29- for i := 0; i < ty.NumIn(); i++ {
29+ for i := range ty.NumIn() {
3030 in := ty.In(i)
3131 if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
3232 continue
@@ -26,7 +26,7 @@ func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
26 func NewCallback(fn any) uintptr {26 func NewCallback(fn any) uintptr {
27 isCDecl := false27 isCDecl := false
28 ty := reflect.TypeOf(fn)28 ty := reflect.TypeOf(fn)
29- for i := 0; i < ty.NumIn(); i++ {29+ for i := range ty.NumIn() {
30 in := ty.In(i)30 in := ty.In(i)
31 if !in.AssignableTo(reflect.TypeOf(CDecl{})) {31 if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
32 continue32 continue
M wincallback.go +8 -8
@@ -35,7 +35,7 @@ func genasm386() {
3535
3636 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
3737 `)
38- for i := 0; i < maxCallback; i++ {
38+ for i := range maxCallback {
3939 fmt.Fprintf(&buf, "\tMOVL $%d, CX\n", i)
4040 buf.WriteString("\tJMP callbackasm1(SB)\n")
4141 }
@@ -63,7 +63,7 @@ func genasmAmd64() {
6363
6464 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
6565 `)
66- for i := 0; i < maxCallback; i++ {
66+ for range maxCallback {
6767 buf.WriteString("\tCALL callbackasm1(SB)\n")
6868 }
6969 if err := os.WriteFile("zcallback_amd64.s", buf.Bytes(), 0644); err != nil {
@@ -90,7 +90,7 @@ func genasmArm() {
9090
9191 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
9292 `)
93- for i := 0; i < maxCallback; i++ {
93+ for i := range maxCallback {
9494 fmt.Fprintf(&buf, "\tMOVW $%d, R12\n", i)
9595 buf.WriteString("\tB callbackasm1(SB)\n")
9696 }
@@ -118,7 +118,7 @@ func genasmArm64() {
118118
119119 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
120120 `)
121- for i := 0; i < maxCallback; i++ {
121+ for i := range maxCallback {
122122 fmt.Fprintf(&buf, "\tMOVD $%d, R12\n", i)
123123 buf.WriteString("\tB callbackasm1(SB)\n")
124124 }
@@ -146,7 +146,7 @@ func genasmLoong64() {
146146
147147 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
148148 `)
149- for i := 0; i < maxCallback; i++ {
149+ for i := range maxCallback {
150150 fmt.Fprintf(&buf, "\tMOVV $%d, R12\n", i)
151151 buf.WriteString("\tJMP callbackasm1(SB)\n")
152152 }
@@ -174,7 +174,7 @@ func genasmPpc64le() {
174174
175175 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
176176 `)
177- for i := 0; i < maxCallback; i++ {
177+ for i := range maxCallback {
178178 fmt.Fprintf(&buf, "\tMOVD $%d, R11\n", i)
179179 buf.WriteString("\tBR callbackasm1(SB)\n")
180180 }
@@ -206,7 +206,7 @@ func genasmRiscv64() {
206206
207207 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
208208 `)
209- for i := 0; i < maxCallback; i++ {
209+ for i := range maxCallback {
210210 space := " "
211211 if i <= 32 {
212212 fmt.Fprintf(&buf, "\tPCALIGN $8\n")
@@ -240,7 +240,7 @@ func genasmS390x() {
240240
241241 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
242242 `)
243- for i := 0; i < maxCallback; i++ {
243+ for i := range maxCallback {
244244 fmt.Fprintf(&buf, "\tMOVD $%d, R0\n", i)
245245 buf.WriteString("\tBR callbackasm1(SB)\n")
246246 }
@@ -35,7 +35,7 @@ func genasm386() {
35 35
36 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $036 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
37 `)37 `)
38- for i := 0; i < maxCallback; i++ {38+ for i := range maxCallback {
39 fmt.Fprintf(&buf, "\tMOVL $%d, CX\n", i)39 fmt.Fprintf(&buf, "\tMOVL $%d, CX\n", i)
40 buf.WriteString("\tJMP callbackasm1(SB)\n")40 buf.WriteString("\tJMP callbackasm1(SB)\n")
41 }41 }
@@ -63,7 +63,7 @@ func genasmAmd64() {
63 63
64 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $064 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
65 `)65 `)
66- for i := 0; i < maxCallback; i++ {66+ for range maxCallback {
67 buf.WriteString("\tCALL callbackasm1(SB)\n")67 buf.WriteString("\tCALL callbackasm1(SB)\n")
68 }68 }
69 if err := os.WriteFile("zcallback_amd64.s", buf.Bytes(), 0644); err != nil {69 if err := os.WriteFile("zcallback_amd64.s", buf.Bytes(), 0644); err != nil {
@@ -90,7 +90,7 @@ func genasmArm() {
90 90
91 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $091 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
92 `)92 `)
93- for i := 0; i < maxCallback; i++ {93+ for i := range maxCallback {
94 fmt.Fprintf(&buf, "\tMOVW $%d, R12\n", i)94 fmt.Fprintf(&buf, "\tMOVW $%d, R12\n", i)
95 buf.WriteString("\tB callbackasm1(SB)\n")95 buf.WriteString("\tB callbackasm1(SB)\n")
96 }96 }
@@ -118,7 +118,7 @@ func genasmArm64() {
118 118
119 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0119 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
120 `)120 `)
121- for i := 0; i < maxCallback; i++ {121+ for i := range maxCallback {
122 fmt.Fprintf(&buf, "\tMOVD $%d, R12\n", i)122 fmt.Fprintf(&buf, "\tMOVD $%d, R12\n", i)
123 buf.WriteString("\tB callbackasm1(SB)\n")123 buf.WriteString("\tB callbackasm1(SB)\n")
124 }124 }
@@ -146,7 +146,7 @@ func genasmLoong64() {
146 146
147 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0147 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
148 `)148 `)
149- for i := 0; i < maxCallback; i++ {149+ for i := range maxCallback {
150 fmt.Fprintf(&buf, "\tMOVV $%d, R12\n", i)150 fmt.Fprintf(&buf, "\tMOVV $%d, R12\n", i)
151 buf.WriteString("\tJMP callbackasm1(SB)\n")151 buf.WriteString("\tJMP callbackasm1(SB)\n")
152 }152 }
@@ -174,7 +174,7 @@ func genasmPpc64le() {
174 174
175 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0175 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
176 `)176 `)
177- for i := 0; i < maxCallback; i++ {177+ for i := range maxCallback {
178 fmt.Fprintf(&buf, "\tMOVD $%d, R11\n", i)178 fmt.Fprintf(&buf, "\tMOVD $%d, R11\n", i)
179 buf.WriteString("\tBR callbackasm1(SB)\n")179 buf.WriteString("\tBR callbackasm1(SB)\n")
180 }180 }
@@ -206,7 +206,7 @@ func genasmRiscv64() {
206 206
207 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0207 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
208 `)208 `)
209- for i := 0; i < maxCallback; i++ {209+ for i := range maxCallback {
210 space := " "210 space := " "
211 if i <= 32 {211 if i <= 32 {
212 fmt.Fprintf(&buf, "\tPCALIGN $8\n")212 fmt.Fprintf(&buf, "\tPCALIGN $8\n")
@@ -240,7 +240,7 @@ func genasmS390x() {
240 240
241 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0241 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
242 `)242 `)
243- for i := 0; i < maxCallback; i++ {243+ for i := range maxCallback {
244 fmt.Fprintf(&buf, "\tMOVD $%d, R0\n", i)244 fmt.Fprintf(&buf, "\tMOVD $%d, R0\n", i)
245 buf.WriteString("\tBR callbackasm1(SB)\n")245 buf.WriteString("\tBR callbackasm1(SB)\n")
246 }246 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close