mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
169 lines
4.1 KiB
C
169 lines
4.1 KiB
C
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
//#define ROC_PLATFORM_DEBUG
|
|
|
|
void alloc_panic(size_t size);
|
|
|
|
void *roc_alloc(size_t size, unsigned int alignment) {
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("Allocating %llu (alignment %ud) ", (unsigned long long)size,
|
|
alignment);
|
|
#endif
|
|
void *result = malloc(size);
|
|
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("at: %p\n", result);
|
|
#endif
|
|
|
|
if (result == NULL) {
|
|
if (size == 0) { // <- malloc is allowed to 'succeed' with NULL iff size == 0.
|
|
return NULL;
|
|
}
|
|
// Otherwise, it is an indication of failure.
|
|
alloc_panic(size);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void *roc_realloc(void *ptr, size_t new_size, size_t old_size,
|
|
unsigned int alignment) {
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("Rellocating %p (%llu -> %llu) (alignment %ud) ", ptr,
|
|
(unsigned long long)old_size, (unsigned long long)new_size, alignment);
|
|
#endif
|
|
|
|
void *result = realloc(ptr, new_size);
|
|
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("at: %p\n", result);
|
|
#endif
|
|
|
|
if (result == NULL) {
|
|
if (new_size ==
|
|
0) { // <- realloc is allowed to 'succeed' with NULL iff size == 0.
|
|
return NULL;
|
|
}
|
|
// Otherwise, it is an indication of failure.
|
|
alloc_panic(new_size);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void roc_dealloc(void *ptr, unsigned int alignment) {
|
|
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("Deallocating %p (alignment %ud)\n", ptr, alignment);
|
|
#endif
|
|
free(ptr);
|
|
}
|
|
|
|
void roc_panic(void *ptr, unsigned int alignment) {
|
|
char *msg = (char *)ptr;
|
|
fprintf(stderr,
|
|
"Application crashed with message\n\n %s\n\nShutting down\n", msg);
|
|
exit(0);
|
|
}
|
|
|
|
void alloc_panic(size_t size) {
|
|
char msg[100];
|
|
sprintf(msg, "Memory allocation failed. Could not allocate %llu bytes",
|
|
(unsigned long long)size);
|
|
|
|
roc_panic(msg, 0);
|
|
}
|
|
|
|
void *roc_memcpy(void *dest, const void *src, size_t n) {
|
|
#ifdef ROC_PLATFORM_DEBUG
|
|
printf("memcpy %p -> %p (size: %llu)\n", src, dest, (unsigned long long)n);
|
|
#endif
|
|
return memcpy(dest, src, n);
|
|
}
|
|
|
|
void *roc_memmove(void *dest, const void *src, size_t n) {
|
|
return memmove(dest, src, n);
|
|
}
|
|
|
|
void *roc_memset(void *str, int c, size_t n) {
|
|
return memset(str, c, n);
|
|
}
|
|
|
|
int roc_send_signal(int pid, int sig) { return kill(pid, sig); }
|
|
int roc_shm_open(char* name, int oflag, int mode) { return shm_open(name, oflag, mode); }
|
|
void* roc_mmap(void* addr, int length, int prot, int flags, int fd, int offset) { return mmap(addr, length, prot, flags, fd, offset); }
|
|
int roc_getppid() { return getppid(); }
|
|
|
|
struct RocStr {
|
|
char *bytes;
|
|
size_t len;
|
|
size_t capacity;
|
|
};
|
|
|
|
bool is_small_str(struct RocStr str) { return ((ssize_t)str.capacity) < 0; }
|
|
|
|
// Determine the length of the string, taking into
|
|
// account the small string optimization
|
|
size_t roc_str_len(struct RocStr str) {
|
|
char *bytes = (char *)&str;
|
|
char last_byte = bytes[sizeof(str) - 1];
|
|
char last_byte_xored = last_byte ^ 0b10000000;
|
|
size_t small_len = (size_t)(last_byte_xored);
|
|
size_t big_len = str.len;
|
|
|
|
// Avoid branch misprediction costs by always
|
|
// determining both small_len and big_len,
|
|
// so this compiles to a cmov instruction.
|
|
if (is_small_str(str)) {
|
|
return small_len;
|
|
} else {
|
|
return big_len;
|
|
}
|
|
}
|
|
|
|
extern void roc__mainForHost_1_exposed_generic(struct RocStr *string);
|
|
|
|
int main() {
|
|
struct RocStr str;
|
|
roc__mainForHost_1_exposed_generic(&str);
|
|
|
|
// Determine str_len and the str_bytes pointer,
|
|
// taking into account the small string optimization.
|
|
size_t str_len = roc_str_len(str);
|
|
char *str_bytes;
|
|
|
|
if (is_small_str(str)) {
|
|
str_bytes = (char *)&str;
|
|
} else {
|
|
str_bytes = str.bytes;
|
|
}
|
|
|
|
// Write to stdout
|
|
size_t written = fwrite(str_bytes, sizeof(char), str_len, stdout);
|
|
if (fflush(stdout) == 0 && written == str_len) {
|
|
// Writing succeeded!
|
|
|
|
// dealllocate the roc string
|
|
if (!(is_small_str(str))) {
|
|
roc_dealloc(str_bytes - 8, 1);
|
|
}
|
|
|
|
return 0;
|
|
} else {
|
|
printf("Error writing to stdout: %s\n", strerror(errno));
|
|
|
|
// dealllocate the roc string
|
|
if (!(is_small_str(str))) {
|
|
roc_dealloc(str_bytes - 8, 1);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
}
|