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  }