-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathsys.c
163 lines (140 loc) · 4.22 KB
/
sys.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// NOTE: WASM is a 32-bit little-endian system.
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef unsigned long size_t;
// Assume running on 64-bit host system.
typedef uint64_t word_t;
typedef uint8_t byte;
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
#define NULL ((void*) 0)
typedef uint8_t bool;
#define true 1
#define false 0
#define INT32_MAX 0x7FFFFFFF
#define UINT16_MAX 65535
#define UINT32_MAX 4294967295u
#define UINT64_MAX 18446744073709551615ull
#define SIZE_MAX 4294967295ul
#define UINT8_C(c) c
#define INT32_C(c) c
#define INT64_C(c) c ## ll
#define UINT64_C(c) c ## ull
// These will be imported from JS.
void _wasm_import_log(void* args_ptr);
void _wasm_import_error(void* args_ptr);
// Use this to make any function visible to JS.
#define WASM_EXPORT __attribute__((visibility("default")))
// This is used by roaring.c, but let's just ignore assertions.
#define assert(ignore)((void) 0)
// __heap_base is provided by host and its position is the start of the heap area.
extern byte __heap_base;
// Must be initialised by reset() before use.
byte* heap = NULL;
byte* last_alloc = NULL;
// Basic allocator that bumps downwards. Stores bytes allocated in word before allocation for realloc().
// Each query simply resets the bump allocation offset so we are not concerned about moving and freeing memory during execution.
WASM_EXPORT void* malloc(size_t n) {
n += (n % sizeof(word_t)) ? n - (n % sizeof(word_t)) : 0;
// Store length of memory block just before pointer for use when reallocating.
*((word_t*) heap) = n;
heap += sizeof(word_t);
last_alloc = heap;
heap += n;
return last_alloc;
}
// We could optimise this in the future.
int posix_memalign(void **memptr, size_t alignment, size_t size) {
(void) alignment;
*memptr = malloc(size);
return 0;
}
// Other than a trivial memory reclaiming, we do not do any freeing during execution.
void free(void* ptr) {
if (ptr == last_alloc) {
heap = last_alloc;
last_alloc = NULL;
}
}
// The following implementations of standard library functions are not efficient.
// They could be optimised in the future if performance becomes very bad.
static inline void memcpy_dir(void* restrict dest, void const* restrict src, size_t n, bool forwards) {
byte* bdest; byte* bsrc;
if (forwards) {
bdest = (byte*) dest;
bsrc = (byte*) src;
while (n-- > 0) *bdest++ = *bsrc++;
} else {
bdest = (byte*) (dest + n - 1);
bsrc = (byte*) (src + n - 1);
while (n-- > 0) *bdest-- = *bsrc--;
}
}
void* memcpy(void* restrict dest, void const* restrict src, size_t n) {
memcpy_dir(dest, src, n, true);
return dest;
}
void* memmove(void* dest, void const* src, size_t n) {
if (src != dest) {
memcpy_dir(dest, src, n, src < dest);
}
return dest;
}
void* memset(void* s, int c, size_t n) {
byte* bs = (byte*) s;
while (n--) *bs++ = (byte) c;
return s;
}
void* realloc(void* ptr, size_t size) {
size += (size % sizeof(word_t)) ? sizeof(word_t) - (size % sizeof(word_t)) : 0;
// Get original size.
word_t* orig_size_ptr = ((word_t*) ptr) - 1;
word_t orig_size = *orig_size_ptr;
if (size <= orig_size) {
return ptr;
}
if (ptr == last_alloc) {
*orig_size_ptr = size;
heap += size - orig_size;
return ptr;
} else {
void* newptr = malloc(size);
memcpy(newptr, ptr, orig_size);
return newptr;
}
}
void* calloc(size_t nmemb, size_t size) {
size_t bytes = size * nmemb;
void* newptr = malloc(bytes);
memset(newptr, 0, bytes);
return newptr;
}
int memcmp(void const* s1, void const* s2, size_t n) {
byte* bs1 = (byte*) s1;
byte* bs2 = (byte*) s2;
while (n-- > 0) {
byte cmp = (*bs1 > *bs2) - (*bs1 < *bs2);
if (cmp) return cmp;
bs1++; bs2++;
}
return 0;
}
size_t strlen(char const* bytes) {
size_t len = 0;
while (bytes[len]) len++;
return len;
}
// Basic stdio functions, necessary for roaring.c.
#define PRIu32 "u"
#define PRId32 "d"
typedef uint8_t FILE;
FILE stderr_fileno = 2;
FILE* stderr = &stderr_fileno;
int printf(char const* fmt, ...);
int fprintf(FILE* stream, char const* fmt, ...);