github.com/DQNEO/babygo@v0.0.3/src/runtime/runtime.go (about)

     1  // runtime for 2nd generation compiler
     2  package runtime
     3  
     4  import "unsafe"
     5  
     6  const heapSize uintptr = 620205360
     7  
     8  var heapHead uintptr
     9  var heapCurrent uintptr
    10  var heapTail uintptr
    11  
    12  const SYS_BRK int = 12
    13  const SYS_EXIT int = 60
    14  
    15  var __argv__ []*uint8 // C argv
    16  
    17  // Environment variables
    18  var envp uintptr
    19  var envlines []string // []{"FOO=BAR\0", "HOME=/home/...\0", ..}
    20  
    21  type envEntry struct {
    22  	key   string
    23  	value string
    24  }
    25  
    26  var Envs []*envEntry
    27  
    28  func heapInit() {
    29  	heapHead = brk(0)
    30  	heapTail = brk(heapHead + heapSize)
    31  	heapCurrent = heapHead
    32  }
    33  
    34  // Inital stack layout is illustrated in this page
    35  // http://asm.sourceforge.net/articles/startup.html#st
    36  func envInit() {
    37  	var p uintptr // **byte
    38  
    39  	for p = envp; true; p = p + 8 {
    40  		var bpp **byte = (**byte)(unsafe.Pointer(p))
    41  		if *bpp == nil {
    42  			break
    43  		}
    44  		envlines = append(envlines, cstring2string(*bpp))
    45  	}
    46  
    47  	for _, envline := range envlines {
    48  		var i int
    49  		var c byte
    50  		for i, c = range []byte(envline) {
    51  			if c == '=' {
    52  				break
    53  			}
    54  		}
    55  		key := envline[:i]
    56  		value := envline[i+1:]
    57  
    58  		entry := &envEntry{
    59  			key:   key,
    60  			value: value,
    61  		}
    62  		Envs = append(Envs, entry)
    63  
    64  	}
    65  }
    66  
    67  func runtime_getenv(key string) string {
    68  	for _, e := range Envs {
    69  		if e.key == key {
    70  			return e.value
    71  		}
    72  	}
    73  
    74  	return ""
    75  }
    76  
    77  func cstring2string(b *uint8) string {
    78  	var buf []uint8
    79  	for {
    80  		if b == nil || *b == 0 {
    81  			break
    82  		}
    83  		buf = append(buf, *b)
    84  		var p uintptr = uintptr(unsafe.Pointer(b)) + 1
    85  		b = (*uint8)(unsafe.Pointer(p))
    86  	}
    87  	return string(buf)
    88  }
    89  
    90  // create os.Args
    91  func runtime_args() []string {
    92  	var a *uint8
    93  	var r []string
    94  	for _, a = range __argv__ {
    95  		var s string = cstring2string(a)
    96  		r = append(r, s)
    97  	}
    98  
    99  	return r
   100  }
   101  
   102  func brk(addr uintptr) uintptr {
   103  	var ret uintptr
   104  	ret = Syscall(uintptr(SYS_BRK), addr, uintptr(0), uintptr(0))
   105  	return ret
   106  }
   107  
   108  func panic(ifc interface{}) {
   109  	switch x := ifc.(type) {
   110  	case string:
   111  		var s = "panic: " + x + "\n\n"
   112  		Write(2, []uint8(s))
   113  		Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0))
   114  	default:
   115  		var s = "panic: " + "Unknown type" + "\n\n"
   116  		Write(2, []uint8(s))
   117  		Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0))
   118  	}
   119  }
   120  
   121  func memzeropad(addr1 uintptr, size uintptr) {
   122  	var p *uint8 = (*uint8)(unsafe.Pointer(addr1))
   123  	var isize int = int(size)
   124  	var i int
   125  	var up uintptr
   126  	for i = 0; i < isize; i++ {
   127  		*p = 0
   128  		up = uintptr(unsafe.Pointer(p)) + 1
   129  		p = (*uint8)(unsafe.Pointer(up))
   130  	}
   131  }
   132  
   133  func memcopy(src uintptr, dst uintptr, length int) {
   134  	var i int
   135  	var srcp *uint8
   136  	var dstp *uint8
   137  	for i = 0; i < length; i++ {
   138  		srcp = (*uint8)(unsafe.Pointer(src + uintptr(i)))
   139  		dstp = (*uint8)(unsafe.Pointer(dst + uintptr(i)))
   140  		*dstp = *srcp
   141  	}
   142  }
   143  
   144  func malloc(size uintptr) uintptr {
   145  	if heapCurrent+size > heapTail {
   146  		Write(2, []uint8("malloc exceeded heap max"))
   147  		Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0))
   148  		return 0
   149  	}
   150  	var r uintptr
   151  	r = heapCurrent
   152  	heapCurrent = heapCurrent + size
   153  	memzeropad(r, size)
   154  	return r
   155  }
   156  
   157  func makeSlice(elmSize int, slen int, scap int) (uintptr, int, int) {
   158  	var size uintptr = uintptr(elmSize * scap)
   159  	var addr uintptr = malloc(size)
   160  	return addr, slen, scap
   161  }
   162  
   163  func append1(old []uint8, elm uint8) (uintptr, int, int) {
   164  	var new_ []uint8
   165  	var elmSize int = 1
   166  
   167  	var oldlen int = len(old)
   168  	var newlen int = oldlen + 1
   169  
   170  	if cap(old) >= newlen {
   171  		new_ = old[0:newlen]
   172  	} else {
   173  		var newcap int
   174  		if oldlen == 0 {
   175  			newcap = 1
   176  		} else {
   177  			newcap = oldlen * 2
   178  		}
   179  		new_ = makeSlice1(elmSize, newlen, newcap)
   180  		var oldSize int = oldlen * elmSize
   181  		if oldlen > 0 {
   182  			memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize)
   183  		}
   184  	}
   185  
   186  	new_[oldlen] = elm
   187  	return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_)
   188  }
   189  
   190  func append8(old []int, elm int) (uintptr, int, int) {
   191  	var new_ []int
   192  	var elmSize int = 8
   193  
   194  	var oldlen int = len(old)
   195  	var newlen int = oldlen + 1
   196  
   197  	if cap(old) >= newlen {
   198  		new_ = old[0:newlen]
   199  	} else {
   200  		var newcap int
   201  		if oldlen == 0 {
   202  			newcap = 1
   203  		} else {
   204  			newcap = oldlen * 2
   205  		}
   206  		new_ = makeSlice8(elmSize, newlen, newcap)
   207  		var oldSize int = oldlen * elmSize
   208  		if oldlen > 0 {
   209  			memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize)
   210  		}
   211  	}
   212  
   213  	new_[oldlen] = elm
   214  	return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_)
   215  }
   216  
   217  func append16(old []string, elm string) (uintptr, int, int) {
   218  	var new_ []string
   219  	var elmSize int = 16
   220  
   221  	var oldlen int = len(old)
   222  	var newlen int = oldlen + 1
   223  
   224  	if cap(old) >= newlen {
   225  		new_ = old[0:newlen]
   226  	} else {
   227  		var newcap int
   228  		if oldlen == 0 {
   229  			newcap = 1
   230  		} else {
   231  			newcap = oldlen * 2
   232  		}
   233  		new_ = makeSlice16(elmSize, newlen, newcap)
   234  		var oldSize int = oldlen * elmSize
   235  		if oldlen > 0 {
   236  			memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize)
   237  		}
   238  	}
   239  
   240  	new_[oldlen] = elm
   241  	return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_)
   242  }
   243  
   244  func append24(old [][]int, elm []int) (uintptr, int, int) {
   245  	var new_ [][]int
   246  	var elmSize int = 24
   247  
   248  	var oldlen int = len(old)
   249  	var newlen int = oldlen + 1
   250  
   251  	if cap(old) >= newlen {
   252  		new_ = old[0:newlen]
   253  	} else {
   254  		var newcap int
   255  		if oldlen == 0 {
   256  			newcap = 1
   257  		} else {
   258  			newcap = oldlen * 2
   259  		}
   260  		new_ = makeSlice24(elmSize, newlen, newcap)
   261  		var oldSize int = oldlen * elmSize
   262  		if oldlen > 0 {
   263  			memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize)
   264  		}
   265  	}
   266  
   267  	new_[oldlen] = elm
   268  	return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_)
   269  }
   270  
   271  func catstrings(a string, b string) string {
   272  	var totallen = len(a) + len(b)
   273  	var r = make([]uint8, totallen, totallen+1) // +1 is a workaround for syscall.Open. see runtime.s
   274  	var i int
   275  	for i = 0; i < len(a); i = i + 1 {
   276  		r[i] = a[i]
   277  	}
   278  	var j int
   279  	for j = 0; j < len(b); j = j + 1 {
   280  		r[i+j] = b[j]
   281  	}
   282  	return string(r)
   283  }
   284  
   285  func cmpstrings(a string, b string) bool {
   286  	if len(a) != len(b) {
   287  		return false
   288  	}
   289  	var i int
   290  	for i = 0; i < len(a); i++ {
   291  		if a[i] != b[i] {
   292  			return false
   293  		}
   294  	}
   295  	return true
   296  }
   297  
   298  // Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.
   299  func cmpinterface(a uintptr, b uintptr, c uintptr, d uintptr) bool {
   300  	if a == c && b == d {
   301  		return true
   302  	}
   303  	return false
   304  }
   305  
   306  func Write(fd int, p []byte) int
   307  func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) uintptr
   308  
   309  // Actually this is an alias to makeSlice
   310  func makeSlice1(elmSize int, slen int, scap int) []uint8
   311  func makeSlice8(elmSize int, slen int, scap int) []int
   312  func makeSlice16(elmSize int, slen int, scap int) []string
   313  func makeSlice24(elmSize int, slen int, scap int) [][]int