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  `