stdlib.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. // clang --target=wasm32 -c -emit-llvm -O3 -ffreestanding -fno-builtin -Wall stdlib.c
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include <stdbool.h>
  5. #include "stdlib.h"
  6. /*
  7. */
  8. void __memset8(void *_dest, uint64_t val, size_t length)
  9. {
  10. uint64_t *dest = _dest;
  11. do
  12. {
  13. *dest++ = val;
  14. } while (--length);
  15. }
  16. void __memset(void *_dest, uint8_t val, size_t length)
  17. {
  18. uint8_t *dest = _dest;
  19. do
  20. {
  21. *dest++ = val;
  22. } while (--length);
  23. }
  24. /*
  25. * Our memcpy can only deal with multiples of 8 bytes. This is enough for
  26. * simple allocator below.
  27. */
  28. void __memcpy8(void *_dest, void *_src, size_t length)
  29. {
  30. uint64_t *dest = _dest;
  31. uint64_t *src = _src;
  32. do
  33. {
  34. *dest++ = *src++;
  35. } while (--length);
  36. }
  37. void __memcpy(void *_dest, const void *_src, size_t length)
  38. {
  39. uint8_t *dest = _dest;
  40. const uint8_t *src = _src;
  41. while (length--)
  42. {
  43. *dest++ = *src++;
  44. }
  45. }
  46. /*
  47. * Fast-ish clear, 8 bytes at a time.
  48. */
  49. void __bzero8(void *_dest, size_t length)
  50. {
  51. uint64_t *dest = _dest;
  52. do
  53. *dest++ = 0;
  54. while (--length);
  55. }
  56. /*
  57. * Fast-ish set, 8 bytes at a time.
  58. */
  59. void __bset8(void *_dest, size_t length)
  60. {
  61. int64_t *dest = _dest;
  62. do
  63. *dest++ = -1;
  64. while (--length);
  65. }
  66. /*
  67. There are many tradeoffs in heaps. I think for Solidity, we want:
  68. - small code size to reduce code length
  69. - not many malloc objects
  70. - not much memory
  71. So I think we should avoid fragmentation by neighbour merging. The most
  72. costly is walking the doubly linked list looking for free space.
  73. */
  74. struct chunk
  75. {
  76. struct chunk *next, *prev;
  77. size_t length;
  78. size_t allocated;
  79. };
  80. void __init_heap()
  81. {
  82. struct chunk *first = (struct chunk *)0x10000;
  83. first->next = first->prev = NULL;
  84. first->allocated = false;
  85. first->length = (size_t)(__builtin_wasm_memory_size(0) * 0x10000 -
  86. (size_t)first - sizeof(struct chunk));
  87. }
  88. void __attribute__((noinline)) __free(void *m)
  89. {
  90. struct chunk *cur = m;
  91. cur--;
  92. if (m)
  93. {
  94. cur->allocated = false;
  95. struct chunk *next = cur->next;
  96. if (next && !next->allocated)
  97. {
  98. // merge with next
  99. if ((cur->next = next->next) != NULL)
  100. cur->next->prev = cur;
  101. cur->length += next->length + sizeof(struct chunk);
  102. next = cur->next;
  103. }
  104. struct chunk *prev = cur->prev;
  105. if (prev && !prev->allocated)
  106. {
  107. // merge with previous
  108. prev->next = next;
  109. next->prev = prev;
  110. prev->length += cur->length + sizeof(struct chunk);
  111. }
  112. }
  113. }
  114. static void shrink_chunk(struct chunk *cur, size_t size)
  115. {
  116. // round up to nearest 8 bytes
  117. size = (size + 7) & ~7;
  118. if (cur->length - size >= (8 + sizeof(struct chunk)))
  119. {
  120. // split and return
  121. void *data = (cur + 1);
  122. struct chunk *new = data + size;
  123. if ((new->next = cur->next) != NULL)
  124. new->next->prev = new;
  125. cur->next = new;
  126. new->prev = cur;
  127. new->allocated = false;
  128. new->length = cur->length - size - sizeof(struct chunk);
  129. cur->length = size;
  130. }
  131. }
  132. void *__attribute__((noinline)) __malloc(size_t size)
  133. {
  134. struct chunk *cur = (struct chunk *)0x10000;
  135. while (cur && (cur->allocated || size > cur->length))
  136. cur = cur->next;
  137. if (cur)
  138. {
  139. shrink_chunk(cur, size);
  140. cur->allocated = true;
  141. return ++cur;
  142. }
  143. else
  144. {
  145. // go bang
  146. __builtin_unreachable();
  147. }
  148. }
  149. void *__realloc(void *m, size_t size)
  150. {
  151. struct chunk *cur = m;
  152. cur--;
  153. struct chunk *next = cur->next;
  154. if (next && !next->allocated && size <= (cur->length + next->length + sizeof(struct chunk)))
  155. {
  156. // merge with next
  157. cur->next = next->next;
  158. cur->next->prev = cur;
  159. cur->length += next->length + sizeof(struct chunk);
  160. // resplit ..
  161. shrink_chunk(cur, size);
  162. return m;
  163. }
  164. else
  165. {
  166. void *n = __malloc(size);
  167. __memcpy8(n, m, size / 8);
  168. __free(m);
  169. return n;
  170. }
  171. }
  172. // This function is used for abi decoding integers.
  173. // ABI encoding is big endian, and can have integers of 8 to 256 bits
  174. // (1 to 32 bytes). This function copies length bytes and reverses the
  175. // order since wasm is little endian.
  176. void __be32toleN(uint8_t *from, uint8_t *to, uint32_t length)
  177. {
  178. from += 31;
  179. do
  180. {
  181. *to++ = *from--;
  182. } while (--length);
  183. }
  184. void __beNtoleN(uint8_t *from, uint8_t *to, uint32_t length)
  185. {
  186. from += length;
  187. do
  188. {
  189. *to++ = *--from;
  190. } while (--length);
  191. }
  192. // This function is for used for abi encoding integers
  193. // ABI encoding is big endian.
  194. void __leNtobe32(uint8_t *from, uint8_t *to, uint32_t length)
  195. {
  196. to += 31;
  197. do
  198. {
  199. *to-- = *from++;
  200. } while (--length);
  201. }
  202. void __leNtobeN(uint8_t *from, uint8_t *to, uint32_t length)
  203. {
  204. to += length;
  205. do
  206. {
  207. *--to = *from++;
  208. } while (--length);
  209. }
  210. /*
  211. In wasm, the instruction for multiplying two 64 bit values results in a 64 bit value. In
  212. other words, the result is truncated. The largest values we can multiply without truncation
  213. is 32 bit (by casting to 64 bit and doing a 64 bit multiplication). So, we divvy the work
  214. up into a 32 bit multiplications.
  215. No overflow checking is done.
  216. 0 0 0 r5 r4 r3 r2 r1
  217. 0 0 0 0 l4 l3 l2 l1 *
  218. ------------------------------------------------------------
  219. 0 0 0 r5*l1 r4*l1 r3*l1 r2*l1 r1*l1
  220. 0 0 r5*l2 r4*l2 r3*l2 r2*l2 r1*l2 0
  221. 0 r5*l3 r4*l3 r3*l3 r2*l3 r1*l3 0 0
  222. r5*l4 r4*l4 r3*l4 r2*l4 r1*l4 0 0 0 +
  223. ------------------------------------------------------------
  224. */
  225. void __mul32(uint32_t left[], uint32_t right[], uint32_t out[], int len)
  226. {
  227. uint64_t val1 = 0, carry = 0;
  228. int left_len = len, right_len = len;
  229. while (left_len > 0 && !left[left_len - 1])
  230. left_len--;
  231. while (right_len > 0 && !right[right_len - 1])
  232. right_len--;
  233. int right_start = 0, right_end = 0;
  234. int left_start = 0;
  235. for (int l = 0; l < len; l++)
  236. {
  237. int i = 0;
  238. if (l >= left_len)
  239. right_start++;
  240. if (l >= right_len)
  241. left_start++;
  242. if (right_end < right_len)
  243. right_end++;
  244. for (int r = right_end - 1; r >= right_start; r--)
  245. {
  246. uint64_t m = (uint64_t)left[left_start + i] * (uint64_t)right[r];
  247. i++;
  248. if (__builtin_add_overflow(val1, m, &val1))
  249. carry += 0x100000000;
  250. }
  251. out[l] = val1;
  252. val1 = (val1 >> 32) | carry;
  253. carry = 0;
  254. }
  255. }
  256. // Some compiler runtime builtins we need.
  257. // 128 bit shift left.
  258. typedef union
  259. {
  260. __uint128_t all;
  261. struct
  262. {
  263. uint64_t low;
  264. uint64_t high;
  265. };
  266. } two64;
  267. // This assumes r >= 0 && r <= 127
  268. __uint128_t __ashlti3(__uint128_t val, int r)
  269. {
  270. two64 in;
  271. two64 result;
  272. in.all = val;
  273. if (r == 0)
  274. {
  275. // nothing to do
  276. result.all = in.all;
  277. }
  278. else if (r & 64)
  279. {
  280. // Shift more than or equal 64
  281. result.low = 0;
  282. result.high = in.low << (r & 63);
  283. }
  284. else
  285. {
  286. // Shift less than 64
  287. result.low = in.low << r;
  288. result.high = (in.high << r) | (in.low >> (64 - r));
  289. }
  290. return result.all;
  291. }
  292. // This assumes r >= 0 && r <= 127
  293. __uint128_t __lshrti3(__uint128_t val, int r)
  294. {
  295. two64 in;
  296. two64 result;
  297. in.all = val;
  298. if (r == 0)
  299. {
  300. // nothing to do
  301. result.all = in.all;
  302. }
  303. else if (r & 64)
  304. {
  305. // Shift more than or equal 64
  306. result.low = in.high >> (r & 63);
  307. result.high = 0;
  308. }
  309. else
  310. {
  311. // Shift less than 64
  312. result.low = (in.low >> r) | (in.high << (64 - r));
  313. result.high = in.high >> r;
  314. }
  315. return result.all;
  316. }
  317. // sabre wants the storage keys as a hex string. Convert the uint256 pointed
  318. // to be by v into a hex string
  319. char *__u256ptohex(uint8_t *v, char *str)
  320. {
  321. // the uint256 will be stored little endian so fill it in reverse
  322. str += 63;
  323. for (int i = 0; i < 32; i++)
  324. {
  325. uint8_t l = (v[i] & 0x0f);
  326. *str-- = l > 9 ? l + 'a' : '0' + l;
  327. uint8_t h = (v[i] >> 4);
  328. *str-- = h > 9 ? h + 'a' : '0' + h;
  329. }
  330. return str;
  331. }
  332. // Create a new vector. If initial is -1 then clear the data. This is done since a null pointer valid in wasm
  333. struct vector *vector_new(uint32_t members, uint32_t size, uint8_t *initial)
  334. {
  335. struct vector *v;
  336. size_t size_array = members * size;
  337. v = __malloc(sizeof(*v) + size_array);
  338. v->len = members;
  339. v->size = members;
  340. uint8_t *data = v->data;
  341. if ((int)initial != -1)
  342. {
  343. while (size_array--)
  344. {
  345. *data++ = *initial++;
  346. }
  347. }
  348. else
  349. {
  350. while (size_array--)
  351. {
  352. *data++ = 0;
  353. }
  354. }
  355. return v;
  356. }
  357. bool __memcmp(uint8_t *left, uint32_t left_len, uint8_t *right, uint32_t right_len)
  358. {
  359. if (left_len != right_len)
  360. return false;
  361. while (left_len--)
  362. {
  363. if (*left++ != *right++)
  364. return false;
  365. }
  366. return true;
  367. }
  368. struct vector *concat(uint8_t *left, uint32_t left_len, uint8_t *right, uint32_t right_len)
  369. {
  370. size_t size_array = left_len + right_len;
  371. struct vector *v = __malloc(sizeof(*v) + size_array);
  372. v->len = size_array;
  373. v->size = size_array;
  374. uint8_t *data = v->data;
  375. while (left_len--)
  376. {
  377. *data++ = *left++;
  378. }
  379. while (right_len--)
  380. {
  381. *data++ = *right++;
  382. }
  383. return v;
  384. }