stdlib.c 8.3 KB

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