github.com/gotranspile/cxgo@v0.3.7/libs/stdint.go (about) 1 package libs 2 3 import ( 4 "fmt" 5 "math" 6 "strconv" 7 "strings" 8 9 "github.com/gotranspile/cxgo/types" 10 ) 11 12 const ( 13 stdintH = "stdint.h" 14 ) 15 16 func init() { 17 RegisterLibrary(stdintH, func(c *Env) *Library { 18 idents := make(map[string]*types.Ident) 19 return &Library{ 20 Idents: idents, 21 Header: incStdInt(c.Env, idents), 22 Types: typesStdInt(c.Env), 23 } 24 }) 25 } 26 27 func fixedIntTypeDefs(buf *strings.Builder, part string) { 28 for _, unsigned := range []bool{false, true} { 29 name := "int" 30 if unsigned { 31 name = "uint" 32 } 33 for _, sz := range intSizes { 34 _, _ = fmt.Fprintf(buf, "#define %s%s%d_t %s\n", 35 name, part, sz, 36 buildinFixedIntName(sz, unsigned), 37 ) 38 } 39 buf.WriteByte('\n') 40 } 41 } 42 43 func fixedIntTypes() string { 44 var buf strings.Builder 45 fixedIntTypeDefs(&buf, "") 46 fixedIntTypeDefs(&buf, "_least") 47 fixedIntTypeDefs(&buf, "_fast") 48 return buf.String() 49 } 50 51 func maxIntTypeDefs(buf *strings.Builder, part string, sz int) { 52 for _, unsigned := range []bool{false, true} { 53 name := "int" 54 if unsigned { 55 name = "uint" 56 } 57 _, _ = fmt.Fprintf(buf, "typedef %s %s%s_t;\n", 58 buildinFixedIntName(sz, unsigned), 59 name, part, 60 ) 61 } 62 buf.WriteByte('\n') 63 } 64 65 func maxIntTypes(e *types.Env) string { 66 var buf strings.Builder 67 maxIntTypeDefs(&buf, "ptr", e.PtrSize()*8) 68 maxIntTypeDefs(&buf, "max", intSizes[len(intSizes)-1]) 69 return buf.String() 70 } 71 72 func intLimitsDef(buf *strings.Builder, m map[string]*types.Ident, part string, min, max int64, umax uint64, size int) { 73 intMinMax(buf, m, "INT"+part, "Int", min, max, size) 74 uintMax(buf, m, "UINT"+part, "Uint", umax, size) 75 } 76 77 func intLimitsDefs(buf *strings.Builder, m map[string]*types.Ident, part string) { 78 for i, sz := range intSizes { 79 intLimitsDef(buf, m, part+strconv.Itoa(sz), minInts[i], maxInts[i], maxUints[i], sz) 80 } 81 buf.WriteByte('\n') 82 } 83 84 func intLimits(m map[string]*types.Ident) string { 85 var buf strings.Builder 86 intLimitsDefs(&buf, m, "") 87 intLimitsDefs(&buf, m, "_LEAST") 88 intLimitsDefs(&buf, m, "_FAST") 89 return buf.String() 90 } 91 92 func intSizeInd(sz int) int { 93 switch sz { 94 case 0, 1: 95 return 0 96 case 2: 97 return 1 98 case 4: 99 return 2 100 case 8: 101 return 3 102 default: 103 panic(sz) 104 } 105 } 106 107 func maxIntLimits(e *types.Env, m map[string]*types.Ident) string { 108 var buf strings.Builder 109 i := intSizeInd(e.PtrSize()) 110 intLimitsDef(&buf, m, "PTR", minInts[i], maxInts[i], maxUints[i], e.PtrSize()*8) 111 buf.WriteByte('\n') 112 113 i = len(intSizes) - 1 114 intLimitsDef(&buf, m, "MAX", minInts[i], maxInts[i], maxUints[i], e.PtrSize()*8) 115 buf.WriteByte('\n') 116 return buf.String() 117 } 118 119 func otherLimits(e *types.Env, m map[string]*types.Ident) string { 120 var buf strings.Builder 121 122 i := intSizeInd(e.PtrSize()) 123 intMinMax(&buf, m, "PTRDIFF", "Int", minInts[i], maxInts[i], e.PtrSize()*8) 124 buf.WriteByte('\n') 125 126 // TODO: SIG_ATOMIC 127 128 i = intSizeInd(e.PtrSize()) 129 uintMax(&buf, m, "SIZE", "Uint", maxUints[i], e.PtrSize()*8) 130 buf.WriteByte('\n') 131 132 i = intSizeInd(e.C().WCharSize()) 133 if e.C().WCharSigned() { 134 intMinMax(&buf, m, "WCHAR", "Int", minInts[i], maxInts[i], e.C().WCharSize()*8) 135 } else { 136 intMinMax(&buf, m, "WCHAR", "Uint", 0, int64(maxUints[i]), e.C().WCharSize()*8) 137 } 138 buf.WriteByte('\n') 139 140 i = intSizeInd(e.C().WIntSize()) 141 if e.C().WCharSigned() { 142 intMinMax(&buf, m, "WINT", "Int", minInts[i], maxInts[i], e.C().WIntSize()*8) 143 } else { 144 intMinMax(&buf, m, "WINT", "Uint", 0, int64(maxUints[i]), e.C().WIntSize()*8) 145 } 146 buf.WriteByte('\n') 147 return buf.String() 148 } 149 150 var ( 151 intSizes = []int{8, 16, 32, 64} 152 minInts = []int64{math.MinInt8, math.MinInt16, math.MinInt32, math.MinInt64} 153 maxInts = []int64{math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64} 154 maxUints = []uint64{math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64} 155 ) 156 157 func incStdInt(e *types.Env, m map[string]*types.Ident) string { 158 var buf strings.Builder 159 buf.WriteString("#include <" + BuiltinH + ">\n") 160 buf.WriteString(fixedIntTypes()) 161 buf.WriteString(maxIntTypes(e)) 162 buf.WriteString(intLimits(m)) 163 buf.WriteString(maxIntLimits(e, m)) 164 buf.WriteString(otherLimits(e, m)) 165 return buf.String() 166 } 167 168 func typesStdInt(e *types.Env) map[string]types.Type { 169 m := make(map[string]types.Type, 2*len(intSizes)) 170 for _, unsigned := range []bool{false, true} { 171 for _, sz := range intSizes { 172 name := buildinFixedIntName(sz, unsigned) 173 if unsigned { 174 m[name] = types.UintT(sz / 8) 175 } else { 176 m[name] = types.IntT(sz / 8) 177 } 178 } 179 } 180 m["intptr_t"] = e.IntPtrT() 181 m["uintptr_t"] = e.UintPtrT() 182 max := intSizes[len(intSizes)-1] / 8 183 m["intmax_t"] = types.IntT(max) 184 m["uintmax_t"] = types.UintT(max) 185 return m 186 }