github.com/gotranspile/cxgo@v0.3.7/libs/builtin.go (about) 1 package libs 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "sync/atomic" 8 9 "github.com/gotranspile/cxgo/runtime/libc" 10 "github.com/gotranspile/cxgo/runtime/stdio" 11 "github.com/gotranspile/cxgo/types" 12 ) 13 14 // TODO: spec URL 15 16 const ( 17 BuiltinH = `cxgo_builtin.h` 18 19 typeFixedIntPref = "_cxgo_" 20 21 RuntimeOrg = "github.com/gotranspile" 22 RuntimePackage = RuntimeOrg + "/cxgo" 23 RuntimePackageVers = "main" 24 RuntimePrefix = RuntimePackage + "/runtime/" 25 RuntimeLibc = RuntimePrefix + "libc" 26 ) 27 28 func buildinFixedIntName(sz int, unsigned bool) string { 29 return typeFixedIntPref + goIntName(sz, unsigned) 30 } 31 32 func goIntName(sz int, unsigned bool) string { 33 name := "sint" 34 if unsigned { 35 name = "uint" 36 } 37 return name + strconv.Itoa(sz) 38 } 39 40 func init() { 41 RegisterLibrary(BuiltinH, func(c *Env) *Library { 42 int32T := types.IntT(4) 43 charP := c.C().String() 44 lsz := c.C().Long().Sizeof() 45 psz := c.PtrT(nil).Sizeof() 46 47 // builtin variable arguments list 48 ifaceT := c.Go().Any() 49 sliceT := c.Go().SliceOfAny() 50 valistPtr := c.PtrT(nil) 51 valistT := types.NamedTGo("__builtin_va_list", "libc.ArgList", c.MethStructT(map[string]*types.FuncType{ 52 "Start": c.FuncTT(nil, ifaceT, sliceT), 53 "Arg": c.FuncTT(ifaceT), 54 "End": c.FuncTT(nil), 55 })) 56 valistPtr.SetElem(valistT) 57 58 // memory model 59 pre := "" 60 switch { 61 case lsz == 4 && psz == 8: 62 pre += ` 63 #define __LLP64__ 1 64 #define _LLP64_ 1 65 ` 66 case lsz == 8 && psz == 8: 67 pre += ` 68 #define __LP64__ 1 69 #define _LP64_ 1 70 ` 71 case psz == 4: 72 pre += ` 73 #define __ILP32__ 1 74 #define _ILP32_ 1 75 ` 76 } 77 var post strings.Builder 78 maxIntTypeDefs(&post, "ptr", c.PtrSize()*8) 79 post.WriteString(` 80 #define NULL 0 81 typedef intptr_t ptrdiff_t; 82 typedef uintptr_t size_t; 83 `) 84 85 l := &Library{ 86 Header: pre + ` 87 #define __ORDER_BIG_ENDIAN__ 4321 88 #define __ORDER_LITTLE_ENDIAN__ 1234 89 #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ 90 91 #define __CXGO__ 92 #define __linux__ 93 #define _CXGO_WINAPI 94 95 #define __SIZEOF_INT8__ 1 96 #define __SIZEOF_INT16__ 2 97 #define __SIZEOF_INT32__ 4 98 #define __SIZEOF_INT64__ 8 99 100 #define _cxgo_int8 __int8 101 #define _cxgo_int16 __int16 102 #define _cxgo_int32 __int32 103 #define _cxgo_int64 __int64 104 105 #define _cxgo_sint8 signed __int8 106 #define _cxgo_sint16 signed __int16 107 #define _cxgo_sint32 signed __int32 108 #define _cxgo_sint64 signed __int64 109 110 #define _cxgo_uint8 unsigned __int8 111 #define _cxgo_uint16 unsigned __int16 112 #define _cxgo_uint32 unsigned __int32 113 #define _cxgo_uint64 unsigned __int64 114 115 #define _cxgo_float32 float 116 #define _cxgo_float64 double 117 118 typedef _Bool _cxgo_go_bool; 119 typedef _cxgo_uint8 _cxgo_go_byte; 120 typedef _cxgo_int32 _cxgo_go_rune; 121 typedef signed int _cxgo_go_int; 122 typedef unsigned int _cxgo_go_uint; 123 typedef unsigned int _cxgo_go_uintptr; 124 typedef void* _cxgo_go_unsafeptr; 125 126 typedef struct { 127 _cxgo_go_unsafeptr ptr; 128 _cxgo_go_uintptr len_; 129 } _cxgo_go_string; 130 131 #define _cxgo_go_slice_t(type) struct { type _cxgo_go_slice_data; }* 132 133 typedef struct{ 134 _cxgo_go_uintptr typ; 135 _cxgo_go_unsafeptr ptr; 136 } _cxgo_go_any; 137 #define _cxgo_go_iface _cxgo_go_any 138 139 #define _cxgo_go_slice_any _cxgo_go_slice_t(_cxgo_go_any) 140 #define _cxgo_go_iface_slice _cxgo_go_slice_any 141 142 typedef struct __builtin_va_list __builtin_va_list; 143 typedef struct __builtin_va_list { 144 void (*Start) (_cxgo_go_uint n, _cxgo_go_slice_any rest); 145 _cxgo_go_any (*Arg) (); 146 void (*End) (); 147 } __builtin_va_list; 148 #define __gnuc_va_list __builtin_va_list 149 150 // a hack for C parser to resolve macro references to _rest arg 151 _cxgo_go_slice_any _rest; 152 153 void* malloc(_cxgo_go_int); 154 155 ` + post.String() + includeHacks, 156 Idents: map[string]*types.Ident{ 157 "malloc": c.C().MallocFunc(), 158 }, 159 Imports: map[string]string{ 160 "libc": RuntimeLibc, 161 "stdio": RuntimePrefix + "stdio", // for printf 162 "atomic": "sync/atomic", 163 }, 164 Types: map[string]types.Type{ 165 "__builtin_va_list": valistT, 166 "intptr_t": c.IntPtrT(), 167 "uintptr_t": c.UintPtrT(), 168 }, 169 ForceMacros: map[string]bool{ 170 "NULL": true, 171 }, 172 } 173 for _, t := range c.Go().Types() { 174 if nt, ok := t.(types.Named); ok { 175 l.Types[nt.Name().Name] = nt 176 } 177 } 178 l.Declare( 179 c.Go().LenFunc(), 180 c.Go().CapFunc(), 181 c.Go().SliceFunc(), 182 c.Go().AppendFunc(), 183 c.Go().CopyFunc(), 184 c.Go().MakeFunc(), 185 c.Go().PanicFunc(), 186 c.C().MallocFunc(), 187 c.C().MemmoveFunc(), 188 c.C().MemcpyFunc(), 189 c.C().MemsetFunc(), 190 c.C().StrdupFunc(), 191 c.C().StrndupFunc(), 192 c.NewIdent("_cxgo_func_name", "libc.FuncName", libc.FuncName, c.FuncTT(c.Go().String())), 193 c.NewIdent("__builtin_strcpy", "libc.StrCpy", libc.StrCpy, c.FuncTT(charP, charP, charP)), 194 c.NewIdent("__sync_lock_test_and_set", "atomic.SwapInt32", atomic.SwapInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 195 c.NewIdent("__sync_fetch_and_add", "libc.LoadAddInt32", libc.LoadAddInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 196 c.NewIdent("__sync_fetch_and_sub", "libc.LoadSubInt32", libc.LoadSubInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 197 c.NewIdent("__sync_fetch_and_or", "libc.LoadOrInt32", libc.LoadOrInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 198 c.NewIdent("__sync_fetch_and_and", "libc.LoadAndInt32", libc.LoadAndInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 199 c.NewIdent("__sync_fetch_and_xor", "libc.LoadXorInt32", libc.LoadXorInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 200 c.NewIdent("__sync_fetch_and_nand", "libc.LoadNandInt32", libc.LoadNandInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), 201 c.NewIdent("__builtin_printf", "stdio.Printf", stdio.Printf, c.VarFuncTT(c.Go().Int(), c.Go().String())), 202 c.NewIdent("_cxgo_va_copy", "libc.ArgCopy", libc.ArgCopy, c.FuncTT(nil, valistPtr, valistPtr)), 203 c.NewIdent("printf", "stdio.Printf", stdio.Printf, c.VarFuncTT(c.Go().Int(), c.Go().String())), 204 ) 205 l.Header += ` 206 #define _cxgo_go_make(type, ...) _cxgo_go_make_impl((type)(0x1), __VA_ARGS__) 207 #define _cxgo_go_make_same(arr, ...) _cxgo_go_make_impl(arr, __VA_ARGS__) 208 209 _cxgo_go_int _cxgo_offsetof(_cxgo_go_any, _cxgo_go_string); 210 #define __builtin_offsetof(type, member) _cxgo_offsetof((type)0, "#member") 211 #define offsetof(type, member) _cxgo_offsetof((type)0, "#member") 212 213 #define __builtin_abort() _cxgo_go_panic("abort") 214 #define __builtin_trap() _cxgo_go_panic("trap") 215 #define __builtin_unreachable() _cxgo_go_panic("unreachable") 216 #define memcpy __builtin_memcpy 217 #define memset __builtin_memset 218 #define malloc __builtin_malloc 219 220 #define __sync_fetch_and_sub(p, v) __sync_fetch_and_add(p, -(v)) 221 222 #define __builtin_va_start(va, t) va.Start(t, _rest) 223 #define __builtin_va_arg(va, typ) ((typ)(va.Arg())) 224 #define __builtin_va_end(va) va.End() 225 #define __builtin_va_copy(dst, src) _cxgo_va_copy(&dst, &src) 226 void __builtin_va_arg_pack(); 227 228 #define _Static_assert(x, y) /* x, y */ 229 #define __builtin_expect(x, y) ((x) == (y)) 230 231 #define NULL 0 232 ` 233 l.Header += fmt.Sprintf("#define __SIZE_TYPE__ _cxgo_uint%d\n", c.PtrSize()*8) 234 l.Header += fmt.Sprintf("#define __PTRDIFF_TYPE__ _cxgo_int%d\n", c.PtrSize()*8) 235 l.Header += fmt.Sprintf("#define __INTPTR_TYPE__ _cxgo_int%d\n", c.PtrSize()*8) 236 return l 237 }) 238 } 239 240 const includeHacks = ` 241 #define __func__ _cxgo_func_name() 242 #define __FUNCTION__ _cxgo_func_name() 243 #define __PRETTY_FUNCTION__ _cxgo_func_name() 244 245 #define __aligned(x) /* x */ 246 #define __packed 247 #define _asm int 248 249 // asm volatile("xxx") 250 #define volatile(x) (x) 251 `