Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/prism/compiler/noreturn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @file compiler/noreturn.h
*/
#ifndef PRISM_COMPILER_NORETURN_H
#define PRISM_COMPILER_NORETURN_H

/**
* Mark a function as never returning to its caller, so that the compiler can
* treat the code after a call to it as unreachable. Every form of this goes
* before the declaration.
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
# define PRISM_NORETURN [[noreturn]]
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
# define PRISM_NORETURN _Noreturn
#elif defined(__GNUC__) || defined(__clang__)
# define PRISM_NORETURN __attribute__((__noreturn__))
#elif defined(_MSC_VER)
# define PRISM_NORETURN __declspec(noreturn)
#else
# define PRISM_NORETURN
#endif

#endif
63 changes: 62 additions & 1 deletion include/prism/internal/arena.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
#ifndef PRISM_INTERNAL_ARENA_H
#define PRISM_INTERNAL_ARENA_H

#include "prism/compiler/exported.h"
#include "prism/compiler/align.h"
#include "prism/compiler/branch.h"
#include "prism/compiler/flex_array.h"
#include "prism/compiler/force_inline.h"
#include "prism/compiler/inline.h"
#include "prism/compiler/noreturn.h"

#include "prism/arena.h"

#include <stddef.h>
#include <stdint.h>
#include <string.h>

/*
Expand Down Expand Up @@ -70,6 +73,13 @@ void pm_arena_reserve(pm_arena_t *arena, size_t capacity);
*/
void * pm_arena_alloc_slow(pm_arena_t *arena, size_t size);

/*
* Report an array allocation whose total size does not fit in a size_t. This
* goes through PRISM_OOM like any other allocation failure, and lives out of
* line so this header does not need the headers PRISM_OOM depends on.
*/
PRISM_NORETURN void pm_arena_alloc_overflow(void);

/*
* Allocate memory from the arena. The returned memory is NOT zeroed. This
* function is infallible — it aborts on allocation failure.
Expand Down Expand Up @@ -99,6 +109,28 @@ pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) {
*/
void * pm_arena_alloc_aligned(pm_arena_t *arena, size_t size, size_t alignment);

/*
* Allocate memory for a single element of type T_ from the arena.
*/
#define PM_ARENA_ALLOC(arena_, T_) \
((T_ *) pm_arena_alloc(arena_, sizeof(T_), PRISM_ALIGNOF(T_)))

/*
* Allocate an array of elements from the arena. The returned memory is NOT
* zeroed. This function is infallible — it aborts on allocation failure.
*/
static PRISM_INLINE void *
pm_arena_alloc_array(pm_arena_t *arena, size_t count, size_t size, size_t alignment) {
if (PRISM_UNLIKELY(count > SIZE_MAX / size)) pm_arena_alloc_overflow();
return pm_arena_alloc(arena, count * size, alignment);
}

/*
* Allocate an array of elements of type T_ from the arena.
*/
#define PM_ARENA_ALLOC_ARRAY(arena_, T_, count_) \
((T_ *) pm_arena_alloc_array(arena_, count_, sizeof(T_), PRISM_ALIGNOF(T_)))

/*
* Allocate zero-initialized memory from the arena. This function is infallible
* — it aborts on allocation failure.
Expand All @@ -110,6 +142,29 @@ pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) {
return ptr;
}

/*
* Allocate a zero-initialized element of type T_ from the arena.
*/
#define PM_ARENA_ZALLOC(arena_, T_) \
((T_ *) pm_arena_zalloc(arena_, sizeof(T_), PRISM_ALIGNOF(T_)))

/*
* Allocate a zero-initialized array of elements from the arena. This function
* is infallible — it aborts on allocation failure.
*/
static PRISM_INLINE void *
pm_arena_zalloc_array(pm_arena_t *arena, size_t count, size_t size, size_t alignment) {
void *ptr = pm_arena_alloc_array(arena, count, size, alignment);
memset(ptr, 0, count * size);
return ptr;
}

/*
* Allocate a zero-initialized array of elements of type T_ from the arena.
*/
#define PM_ARENA_ZALLOC_ARRAY(arena_, T_, count_) \
((T_ *) pm_arena_zalloc_array(arena_, count_, sizeof(T_), PRISM_ALIGNOF(T_)))

/*
* Allocate memory from the arena and copy the given data into it. This is a
* convenience wrapper around pm_arena_alloc + memcpy.
Expand Down Expand Up @@ -149,4 +204,10 @@ pm_arena_realloc(pm_arena_t *arena, void *ptr, size_t new_size, size_t old_size,
return result;
}

/*
* Reallocate an element of type T_ from the arena.
*/
#define PM_ARENA_REALLOC(arena_, ptr_, new_size_, old_size_, T_) \
((T_ *) pm_arena_realloc(arena_, ptr_, new_size_, old_size_, PRISM_ALIGNOF(T_)))

#endif
1 change: 1 addition & 0 deletions prism.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Gem::Specification.new do |spec|
"include/prism/compiler/lifetimebound.hpp",
"include/prism/compiler/nodiscard.h",
"include/prism/compiler/nonnull.h",
"include/prism/compiler/noreturn.h",
"include/prism/compiler/stack.h",
"include/prism/compiler/unused.h",
"include/prism/internal/allocator.h",
Expand Down
11 changes: 11 additions & 0 deletions src/arena.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ pm_arena_alloc_aligned(pm_arena_t *arena, size_t size, size_t alignment) {
return (void *) aligned;
}

/**
* Report an array allocation whose total size does not fit in a size_t. A
* consumer's PRISM_OOM is not required to stop execution, so this aborts after
* it to keep the promise that it never returns.
*/
void
pm_arena_alloc_overflow(void) {
PRISM_OOM();
abort();
}

/**
* Returns a newly allocated and initialized arena.
*/
Expand Down
18 changes: 9 additions & 9 deletions src/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,35 +264,35 @@ pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t lengt
switch (byte) {
case '\a':
if (escaping == PM_BUFFER_ESCAPING_RUBY) {
pm_buffer_append_string(buffer, "\\a", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\a");
} else {
pm_buffer_append_format(buffer, "\\u%04X", byte);
}
break;
case '\b':
pm_buffer_append_string(buffer, "\\b", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\b");
break;
case '\t':
pm_buffer_append_string(buffer, "\\t", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\t");
break;
case '\n':
pm_buffer_append_string(buffer, "\\n", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\n");
break;
case '\v':
if (escaping == PM_BUFFER_ESCAPING_RUBY) {
pm_buffer_append_string(buffer, "\\v", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\v");
} else {
pm_buffer_append_format(buffer, "\\u%04X", byte);
}
break;
case '\f':
pm_buffer_append_string(buffer, "\\f", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\f");
break;
case '\r':
pm_buffer_append_string(buffer, "\\r", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\r");
break;
case '"':
pm_buffer_append_string(buffer, "\\\"", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\\"");
break;
case '#': {
if (escaping == PM_BUFFER_ESCAPING_RUBY && index + 1 < length) {
Expand All @@ -306,7 +306,7 @@ pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t lengt
break;
}
case '\\':
pm_buffer_append_string(buffer, "\\\\", 2);
PM_BUFFER_APPEND_LITERAL(buffer, "\\\\");
break;
default:
pm_buffer_append_byte(buffer, byte);
Expand Down
14 changes: 7 additions & 7 deletions src/comments.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pm_comments_compare(const void *left, const void *right) {
*/
static const pm_comment_t **
pm_comments_sort(pm_parser_t *parser, uint32_t size) {
pm_comment_t **comments = (pm_comment_t **) pm_arena_alloc(&parser->metadata_arena, sizeof(pm_comment_t *) * size, PRISM_ALIGNOF(pm_comment_t *));
pm_comment_t **comments = PM_ARENA_ALLOC_ARRAY(&parser->metadata_arena, pm_comment_t *, size);

uint32_t index = 0;
for (pm_list_node_t *node = parser->comment_list.head; node != NULL; node = node->next) {
Expand Down Expand Up @@ -232,7 +232,7 @@ pm_comments_push(const pm_node_t *node, void *data) {

if (walk->stack.size == walk->stack.capacity) {
size_t capacity = walk->stack.capacity == 0 ? 64 : walk->stack.capacity * 2;
const pm_node_t **nodes = (const pm_node_t **) pm_arena_alloc(walk->arena, sizeof(pm_node_t *) * capacity, PRISM_ALIGNOF(pm_node_t *));
const pm_node_t **nodes = PM_ARENA_ALLOC_ARRAY(walk->arena, const pm_node_t *, capacity);
if (walk->stack.size > 0) memcpy((void *) nodes, (const void *) walk->stack.nodes, sizeof(pm_node_t *) * walk->stack.size);

walk->stack.nodes = nodes;
Expand Down Expand Up @@ -398,9 +398,9 @@ pm_comments_attach(pm_parser_t *parser, const pm_node_t *root) {
.source = parser->start,
.comments = pm_comments_sort(parser, size),
.size = size,
.starts = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * size, PRISM_ALIGNOF(uint32_t)),
.attached = (const pm_node_t **) pm_arena_zalloc(arena, sizeof(pm_node_t *) * size, PRISM_ALIGNOF(pm_node_t *)),
.unclaimed = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * (size + 1), PRISM_ALIGNOF(uint32_t))
.starts = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, size),
.attached = PM_ARENA_ZALLOC_ARRAY(arena, const pm_node_t *, size),
.unclaimed = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, size + 1)
};

for (uint32_t index = 0; index < size; index++) walk.starts[index] = walk.comments[index]->location.start;
Expand All @@ -427,8 +427,8 @@ pm_comments_attach(pm_parser_t *parser, const pm_node_t *root) {

/* The ranges only extend to the largest node id that owns a comment, since
* none of the nodes after it own any. */
pm_comment_range_t *ranges = (pm_comment_range_t *) pm_arena_zalloc(&parser->metadata_arena, sizeof(pm_comment_range_t) * ranges_size, PRISM_ALIGNOF(pm_comment_range_t));
uint32_t *attachments = (uint32_t *) pm_arena_alloc(&parser->metadata_arena, sizeof(uint32_t) * size, PRISM_ALIGNOF(uint32_t));
pm_comment_range_t *ranges = PM_ARENA_ZALLOC_ARRAY(&parser->metadata_arena, pm_comment_range_t, ranges_size);
uint32_t *attachments = PM_ARENA_ALLOC_ARRAY(&parser->metadata_arena, uint32_t, size);

for (uint32_t index = 0; index < size; index++) {
ranges[walk.attached[index]->node_id].length++;
Expand Down
17 changes: 9 additions & 8 deletions src/constant_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
void
pm_constant_id_list_init(pm_arena_t *arena, pm_constant_id_list_t *list, uint32_t size) {
if (size) {
list->ids = (pm_constant_id_t *) pm_arena_zalloc(arena, size * sizeof(pm_constant_id_t), PRISM_ALIGNOF(pm_constant_id_t));
list->ids = PM_ARENA_ZALLOC_ARRAY(arena, pm_constant_id_t, size);
} else {
list->ids = NULL;
}
Expand All @@ -29,10 +29,10 @@ pm_constant_id_list_init(pm_arena_t *arena, pm_constant_id_list_t *list, uint32_
void
pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id) {
if (list->size == 0) {
list->ids = (pm_constant_id_t *) pm_arena_alloc(arena, sizeof(pm_constant_id_t), PRISM_ALIGNOF(pm_constant_id_t));
list->ids = PM_ARENA_ALLOC(arena, pm_constant_id_t);
list->ids[list->size++] = id;
} else {
list->ids =(pm_constant_id_t *) pm_arena_realloc(arena, list->ids, sizeof(pm_constant_id_t) * (list->size + 1), sizeof(pm_constant_id_t) * list->size, PRISM_ALIGNOF(pm_constant_id_t));
list->ids = PM_ARENA_REALLOC(arena, list->ids, sizeof(pm_constant_id_t) * (list->size + 1), sizeof(pm_constant_id_t) * list->size, pm_constant_id_t);
list->ids[list->size++] = id;
}
}
Expand Down Expand Up @@ -83,7 +83,7 @@ pm_constant_id_set_insert(pm_arena_t *arena, pm_constant_id_set_t *set, pm_const
pm_constant_id_set_t grown = {
.size = set->size,
.capacity = capacity,
.ids = (pm_constant_id_t *) pm_arena_zalloc(arena, capacity * sizeof(pm_constant_id_t), PRISM_ALIGNOF(pm_constant_id_t))
.ids = PM_ARENA_ZALLOC_ARRAY(arena, pm_constant_id_t, capacity)
};

for (size_t index = 0; index < set->capacity; index++) {
Expand Down Expand Up @@ -231,9 +231,9 @@ pm_constant_pool_resize(pm_arena_t *arena, pm_constant_pool_t *pool) {
* in the arena. */
size_t constants_size = pm_constant_pool_constants_capacity(pool->capacity) * sizeof(pm_constant_t);
size_t next_constants_size = pm_constant_pool_constants_capacity(next_capacity) * sizeof(pm_constant_t);
pool->constants = (pm_constant_t *) pm_arena_realloc(arena, pool->constants, next_constants_size, constants_size, PRISM_ALIGNOF(pm_constant_t));
pool->constants = PM_ARENA_REALLOC(arena, pool->constants, next_constants_size, constants_size, pm_constant_t);

pm_constant_pool_bucket_t *next_buckets = (pm_constant_pool_bucket_t *) pm_arena_zalloc(arena, next_capacity * sizeof(pm_constant_pool_bucket_t), PRISM_ALIGNOF(pm_constant_pool_bucket_t));
pm_constant_pool_bucket_t *next_buckets = PM_ARENA_ZALLOC_ARRAY(arena, pm_constant_pool_bucket_t, next_capacity);

// For each bucket in the current constant pool, find the index in the
// next constant pool, and insert it.
Expand Down Expand Up @@ -268,8 +268,9 @@ pm_constant_pool_resize(pm_arena_t *arena, pm_constant_pool_t *pool) {
void
pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity) {
capacity = next_power_of_two(capacity);
pool->buckets = (pm_constant_pool_bucket_t *) pm_arena_zalloc(arena, capacity * sizeof(pm_constant_pool_bucket_t), PRISM_ALIGNOF(pm_constant_pool_bucket_t));
pool->constants = (pm_constant_t *) pm_arena_alloc(arena, pm_constant_pool_constants_capacity(capacity) * sizeof(pm_constant_t), PRISM_ALIGNOF(pm_constant_t));

pool->buckets = PM_ARENA_ZALLOC_ARRAY(arena, pm_constant_pool_bucket_t, capacity);
pool->constants = PM_ARENA_ALLOC_ARRAY(arena, pm_constant_t, pm_constant_pool_constants_capacity(capacity));
pool->size = 0;
pool->capacity = capacity;
}
Expand Down
8 changes: 4 additions & 4 deletions src/integer.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pm_integer_parse_powof2(pm_arena_t *arena, pm_integer_t *integer, uint32_t base,
uint32_t length = (uint32_t) (((uint64_t) (digits - 1) * bit + leading_bits + 31) / 32);
assert(length > 2);

uint32_t *words = pm_arena_zalloc(arena, sizeof(uint32_t) * length, PRISM_ALIGNOF(uint32_t));
uint32_t *words = PM_ARENA_ZALLOC_ARRAY(arena, uint32_t, length);
uint64_t bit_position = 0;

for (const uint8_t *cursor = end; cursor > start;) {
Expand Down Expand Up @@ -217,7 +217,7 @@ pm_integer_parse_decimal_divide(pm_arena_t *arena, pm_integer_t *integer, uint32

pm_bignum_t result = {
.length = 0,
.words = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * capacity, PRISM_ALIGNOF(uint32_t))
.words = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, capacity)
};

/* The scratch space is about 12 times the number of chunks, which can
Expand Down Expand Up @@ -288,7 +288,7 @@ pm_integer_parse_decimal_schoolbook(pm_arena_t *arena, pm_integer_t *integer, ui
uint32_t capacity = pm_integer_decimal_words(digits);
pm_bignum_t bignum = {
.length = 0,
.words = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * capacity, PRISM_ALIGNOF(uint32_t))
.words = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, capacity)
};

uint32_t chunk_size = digits % 9 == 0 ? 9 : digits % 9;
Expand Down Expand Up @@ -457,7 +457,7 @@ pm_integer_parse_rational(pm_arena_t *arena, pm_integer_t *numerator, pm_integer

pm_bignum_t bignum = {
.length = 1,
.words = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * capacity, PRISM_ALIGNOF(uint32_t))
.words = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, capacity)
};
bignum.words[0] = 1;

Expand Down
4 changes: 2 additions & 2 deletions src/line_offset_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
void
pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) {
list->offsets = (uint32_t *) pm_arena_alloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
list->offsets = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, capacity);

// The first line always has offset 0.
list->offsets[0] = 0;
Expand All @@ -32,7 +32,7 @@ pm_line_offset_list_clear(pm_line_offset_list_t *list) {
void
pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) {
size_t new_capacity = (list->capacity * 3) / 2;
uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
uint32_t *new_offsets = PM_ARENA_ALLOC_ARRAY(arena, uint32_t, new_capacity);

memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t));

Expand Down
Loading
Loading