1 package loader
2 3 // Moxie type unification.
4 //
5 // Moxie defines int as always 32 bits on all targets. This file patches
6 // Go's type checker to agree: int becomes type-identical to int32, and
7 // uint becomes type-identical to uint32. This eliminates the need for
8 // int32(len(...)) casts throughout all Moxie code.
9 //
10 // The patch works by overwriting the kind field of types.Typ[Int] and
11 // types.Typ[Uint] via unsafe. The Basic struct layout is:
12 // {kind BasicKind, info BasicInfo, name string}
13 // with kind at offset 0. Type identity in go/types uses kind comparison
14 // (x.kind == y.kind), so after patching, Identical(int, int32) returns true.
15 //
16 // On 64-bit targets, slice headers still use uintptr-sized (i64) len/cap
17 // internally. The compiler inserts trunc/ext at the int boundary (len/cap
18 // builtins, make, indexing). Max addressable length is 2^31-1.
19 20 import (
21 "go/types"
22 "unsafe"
23 )
24 25 // patchIntTypes makes int≡int32 and uint≡uint32 in the type checker.
26 // Applied unconditionally on all targets. Must be called before any type
27 // checking begins. Idempotent — safe to call multiple times.
28 func patchIntTypes() {
29 // Already patched — idempotent guard.
30 if types.Typ[types.Int].Kind() == types.Int32 {
31 return
32 }
33 34 // Patch int.kind from Int(2) to Int32(5).
35 kindPtr := (*types.BasicKind)(unsafe.Pointer(types.Typ[types.Int]))
36 *kindPtr = types.Int32
37 38 // Patch uint.kind from Uint(7) to Uint32(10).
39 kindPtr = (*types.BasicKind)(unsafe.Pointer(types.Typ[types.Uint]))
40 *kindPtr = types.Uint32
41 }
42