tree sub_multiple_elements = a68_multiple_elements (sub_multiple);
tree elements_pointer_type = TREE_TYPE (sub_multiple_elements);
tree elements_type = TREE_TYPE (elements_pointer_type);
+ MOID_T *elements_moid = a68_type_moid (elements_type);
multiple_elements_size = fold_build2 (MULT_EXPR, sizetype,
size_int (num_units),
size_in_bytes (elements_type));
a68_multiple_num_elems (sub_multiple));
multiple_elements = a68_lower_tmpvar ("multiple_elements%",
elements_pointer_type,
- a68_lower_alloca (elements_type,
+ a68_lower_alloca (elements_moid,
multiple_elements_size));
/* We can also now calculate the bounds of the new multiple.
/* First allocate space for the elements. */
tree elements = a68_lower_tmpvar ("elements%",
pointer_to_bool_type,
- a68_lower_alloca (a68_bool_type,
+ a68_lower_alloca (M_BOOL,
fold_build2 (MULT_EXPR,
sizetype,
size_int (bits_size),
#include "a68.h"
-typedef tree (*allocator_t) (tree, tree);
+typedef tree (*allocator_t) (MOID_T*, tree);
/* Lower to code that fill in BOUNDS and elements pointers in the given buffer
pointed by BUFFER at offset OFFSET according to the mode MODE, and evals to
MOID_T *elem_mode = SUB (m);
tree elem_size = fold_convert (sizetype, size_in_bytes (CTYPE (elem_mode)));
tree elems_size = save_expr (fold_build2 (MULT_EXPR, sizetype, elem_size, num_elems));
- tree elemsptr = (*allocator) (CTYPE (elem_mode), elems_size);
+ tree elemsptr = (*allocator) (elem_mode, elems_size);
elemsptr = save_expr (elemsptr);
/* And initialize them. */
gen_mode (MOID_T *m, tree_stmt_iterator *bounds, allocator_t allocator)
{
/* Allocate space for the value and fill it. */
- tree buffer = (*allocator) (CTYPE (m), size_in_bytes (CTYPE (m)));
+ tree buffer = (*allocator) (m, size_in_bytes (CTYPE (m)));
buffer = save_expr (buffer);
return fill_in_buffer (buffer, size_zero_node, bounds, m, allocator);
}
*LOWER_BOUND and *UPPER_BOUND are the bounds for the DIM dimensions. */
tree
-a68_row_malloc (tree type, int dim, tree elems, tree elems_size,
+a68_row_malloc (MOID_T *m, int dim, tree elems, tree elems_size,
tree *lower_bound, tree *upper_bound)
{
+ tree type = CTYPE (m);
tree ptr_to_type = build_pointer_type (type);
a68_push_range (NULL);
/* Allocate space for the descriptor. */
tree ptr_to_multiple = a68_lower_tmpvar ("ptr_to_multiple%", ptr_to_type,
- a68_lower_malloc (type, size_in_bytes (type)));
+ a68_lower_malloc (m, size_in_bytes (type)));
tree multiple = a68_row_value (type, dim,
elems, elems_size,
lower_bound, upper_bound);
tree upper_bound = fold_convert (ssizetype, len);
tree elems_size = fold_build2 (MULT_EXPR, sizetype,
len, size_in_bytes (a68_char_type));
- tree body = a68_row_malloc (CTYPE (M_STRING), 1 /* dim */,
+ tree body = a68_row_malloc (M_STRING, 1 /* dim */,
elems, elems_size,
&lower_bound, &upper_bound);
a68_pop_function_range (body);
tree upper_bound = fold_convert (ssizetype, len);
tree elems_size = fold_build2 (MULT_EXPR, sizetype,
len, size_in_bytes (a68_char_type));
- tree body = a68_row_malloc (CTYPE (M_STRING), 1 /* dim */,
+ tree body = a68_row_malloc (M_STRING, 1 /* dim */,
elems, elems_size,
&lower_bound, &upper_bound);
a68_pop_function_range (body);
DEF_A68_RUNTIME (ASSERT, "_libga68_assert", RT(VOID), P2(CONSTCHARPTR, UINT), ECF_NORETURN)
DEF_A68_RUNTIME (MALLOC, "_libga68_malloc", RT(VOIDPTR), P1(SIZE), ECF_NOTHROW | ECF_LEAF | ECF_MALLOC)
+DEF_A68_RUNTIME (MALLOC_LEAF, "_libga68_malloc_leaf", RT(VOIDPTR), P1(SIZE), ECF_NOTHROW | ECF_LEAF | ECF_MALLOC)
DEF_A68_RUNTIME (DEREFNIL, "_libga68_derefnil", RT(VOID), P2(CONSTCHARPTR, UINT), ECF_NORETURN)
DEF_A68_RUNTIME (UNREACHABLE, "_libga68_unreachable", RT(VOID), P2(CONSTCHARPTR, UINT), ECF_NORETURN)
DEF_A68_RUNTIME (INVALIDCHARERROR, "_libga68_invalidcharerror", RT(VOID), P3(CONSTCHARPTR,UINT,INT), ECF_NORETURN)
size_in_bytes (a68_char_type),
num_elems);
tree elements = a68_lower_tmpvar ("elements%", char_pointer_type,
- a68_lower_malloc (a68_char_type, elements_size));
+ a68_lower_malloc (M_CHAR, elements_size));
/* Copy elements. */
tree to_index = a68_lower_tmpvar ("to_index%", sizetype, size_zero_node);
a68_push_range (M_STRING);
tree elements = a68_lower_tmpvar ("elements%", char_pointer_type,
- a68_lower_malloc (a68_char_type,
+ a68_lower_malloc (M_CHAR,
size_one_node));
a68_add_stmt (fold_build2 (MODIFY_EXPR,
void_type_node,
{
tree ptrtype = CTYPE (orig_sliced_multiple_mode);
tree slice_addr = fold_build1 (ADDR_EXPR, ptrtype, slice);
- tree alloc = a68_lower_malloc (ptrtype, size_in_bytes (TREE_TYPE (slice)));
+ tree alloc = a68_lower_malloc (orig_sliced_multiple_mode, size_in_bytes (TREE_TYPE (slice)));
alloc = save_expr (alloc);
tree copy = a68_lower_memcpy (alloc, slice_addr, size_in_bytes (TREE_TYPE (slice)));
tree element_pointer_type = TREE_TYPE (elements);
tree element_type = TREE_TYPE (element_pointer_type);
tree new_elements_size = save_expr (a68_multiple_elements_size (expr));
+ tree new_elements_type = TREE_TYPE (TREE_TYPE (elements));
+ MOID_T *new_elements_moid = a68_type_moid (new_elements_type);
tree new_elements = a68_lower_tmpvar ("new_elements%",
TREE_TYPE (elements),
(use_heap
- ? a68_lower_malloc (TREE_TYPE (TREE_TYPE (elements)),
+ ? a68_lower_malloc (new_elements_moid,
new_elements_size)
- : a68_lower_alloca (TREE_TYPE (TREE_TYPE (elements)),
+ : a68_lower_alloca (new_elements_moid,
new_elements_size)));
/* Then copy the elements.
pointer to it. */
tree
-a68_lower_alloca (tree type, tree size)
+a68_lower_alloca (MOID_T *m, tree size)
{
+ tree type = CTYPE (m);
tree call = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
call = build_call_expr_loc (UNKNOWN_LOCATION, call, 2,
size,
}
-/* Build a tree that allocates SIZE bytes on the heap and returns a *TYPE
- pointer to it. */
+/* Build a tree that allocates SIZE bytes on the heap and returns a pointer to
+ a tree with type equivalent to mode M. */
tree
-a68_lower_malloc (tree type, tree size)
+a68_lower_malloc (MOID_T *m, tree size)
{
+ tree type = CTYPE (m);
+ a68_libcall_fn libcall
+ = (HAS_REFS (m) || HAS_ROWS (m)) ? A68_LIBCALL_MALLOC : A68_LIBCALL_MALLOC_LEAF;
return fold_convert (build_pointer_type (type),
- a68_build_libcall (A68_LIBCALL_MALLOC, ptr_type_node,
+ a68_build_libcall (libcall, ptr_type_node,
1, size));
}
DIM (new_mode) = dim;
NODE (new_mode) = node;
HAS_ROWS (new_mode) = (att == ROW_SYMBOL);
+ HAS_REFS (new_mode) = (att == REF_SYMBOL);
SUB (new_mode) = sub;
PACK (new_mode) = pack;
NEXT (new_mode) = NO_MOID;
return (HAS_ROWS (m) || IS_ROW (m) || IS_FLEX (m));
}
+/* Whether mode has ref. */
+
+static bool
+is_mode_has_refs (MOID_T *m)
+{
+ if (IS_ROW (m) || IS_FLEX (m))
+ {
+ HAS_REFS (m) = is_mode_has_refs (SUB (m));
+ return HAS_REFS (m);
+ }
+ else if (IS_STRUCT (m) || IS_UNION (m))
+ {
+ bool has_refs = false;
+ for (PACK_T *p = PACK (m); p != NO_PACK; FORWARD (p))
+ {
+ HAS_REFS (MOID (p)) = is_mode_has_refs (MOID (p));
+ has_refs |= HAS_REFS (MOID (p));
+ }
+ return has_refs;
+ }
+ else
+ return HAS_REFS (m);
+}
+
/* Compute derived modes. */
static void
gcc_assert (M_STRING == M_FLEX_ROW_CHAR);
- /* Find out what modes contain rows. */
+ /* Find out what modes contain rows, and refs. */
for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z))
- HAS_ROWS (z) = is_mode_has_row (z);
+ {
+ HAS_ROWS (z) = is_mode_has_row (z);
+ HAS_REFS (z) = is_mode_has_refs (z);
+ }
/* Check flexible modes. */
for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z))
DIM (z) = 0;
USE (z) = false;
HAS_ROWS (z) = false;
+ HAS_REFS (z) = false;
PORTABLE (z) = true;
DERIVATE (z) = false;
NODE (z) = NO_NODE;
HAS_ROWS is true if the mode contains rows somewhere in its internal
structure.
+ HAS_REFS is true if the mode contains refs somewhere in its internal
+ structure.
+
The interpretation of SUB depends on the kind of mode:
- For REF modes it is the referred mode.
- For FLEX modes it is the referred mode.
int number;
int attribute;
int dim;
- bool has_rows, use, portable, derivate;
+ bool has_rows, has_refs, use, portable, derivate;
NODE_T *node;
PACK_T *pack;
MOID_T *sub, *equivalent_mode, *slice, *deflexed_mode, *name, *multiple_mode, *next, *rowed, *trim;
#define GREEN(p) ((p)->green)
#define H(p) ((p)->h)
#define HANDLE(p) ((p)->handle)
+#define HAS_REFS(p) ((p)->has_refs)
#define HAS_ROWS(p) ((p)->has_rows)
#define HEAP(p) ((p)->heap)
#define ID(p) ((p)->id)
tree *lower_bound, tree *upper_bound);
tree a68_row_value_raw (tree type, tree descriptor,
tree elements, tree elements_size);
-tree a68_row_malloc (tree type, int dim,
+tree a68_row_malloc (MOID_T *m, int dim,
tree elements, tree elements_size,
- tree *lower_bound, tree *upper_bound);
+ tree *lower_bound, tree *upper_bound);
tree a68_multiple_slice (NODE_T *p, tree multiple, bool slicing_name,
int num_indexes, tree *indexes);
tree a68_multiple_copy_elems (MOID_T *to_mode, tree to, tree from);
tree a68_get_empty (void);
void a68_ref_counts (tree exp, MOID_T *m, int *num_refs, int *num_pointers);
tree a68_consolidate_ref (MOID_T *m, tree expr);
-tree a68_lower_alloca (tree type, tree size);
-tree a68_lower_malloc (tree type, tree size);
+tree a68_lower_alloca (MOID_T *m, tree size);
+tree a68_lower_malloc (MOID_T *m, tree size);
tree a68_checked_indirect_ref (NODE_T *p, tree exp, MOID_T *exp_mode);
tree a68_low_deref (tree exp, NODE_T *p);
tree a68_low_dup (tree exp, bool use_heap = false);
return res;
}
+void *
+_libga68_malloc_leaf (size_t size)
+{
+ void *res = (void *) GC_MALLOC_ATOMIC (size);
+ if (!res)
+ _libga68_abort ("Virtual memory exhausted\n");
+ return res;
+}
+
#else
void
return res;
}
+void *
+_libga68_malloc_leaf (size_t size)
+{
+ return _libga68_malloc (size);
+}
+
#endif /* !LIBGA68_WITH_GC */
if (nchars > 0)
{
/* Read exactly nchar or until EOF. */
- res = _libga68_malloc (nchars * sizeof (uint32_t));
+ res = _libga68_malloc_leaf (nchars * sizeof (uint32_t));
do
{
uc = _libga68_posixfgetc (fd);
{
/* Read until newline or EOF. */
size_t allocated = 80 * sizeof (uint32_t);
- res = _libga68_malloc (allocated);
+ res = _libga68_malloc_leaf (allocated);
do
{
uc = _libga68_posixfgetc (fd);
if (length + 6 > allocated)
allocated = length + 6;
if (result == resultbuf || result == NULL)
- memory = (uint8_t *) _libga68_malloc (allocated * sizeof (uint8_t));
+ memory = (uint8_t *) _libga68_malloc_leaf (allocated * sizeof (uint8_t));
else
memory =
(uint8_t *) _libga68_realloc (result, allocated * sizeof (uint8_t));
if (result == NULL)
{
/* Return a non-NULL value. NULL means error. */
- result = (uint8_t *) _libga68_malloc (1);
+ result = (uint8_t *) _libga68_malloc_leaf (1);
if (result == NULL)
{
errno = ENOMEM;
if (length + 1 > allocated)
allocated = length + 1;
if (result == resultbuf || result == NULL)
- memory = (uint32_t *) _libga68_malloc (allocated * sizeof (uint32_t));
+ memory = (uint32_t *) _libga68_malloc_leaf (allocated * sizeof (uint32_t));
else
memory =
(uint32_t *) _libga68_realloc (result, allocated * sizeof (uint32_t));
if (result == NULL)
{
/* Return a non-NULL value. NULL means error. */
- result = (uint32_t *) _libga68_malloc (1);
+ result = (uint32_t *) _libga68_malloc_leaf (1);
}
}
else if (result != resultbuf && length < allocated)
void _libga68_init_heap (void) GA68_HIDDEN;
void *_libga68_malloc (size_t size);
+void *_libga68_malloc_leaf (size_t size);
void *_libga68_malloc_internal (size_t size) GA68_HIDDEN;
void *_libga68_realloc (void *ptr, size_t size) GA68_HIDDEN;
void *_libga68_realloc_unchecked (void *ptr, size_t size) GA68_HIDDEN;
_libga68_longrandom;
_libga68_lower_bound;
_libga68_malloc;
+ _libga68_malloc_leaf;
_libga68_posixargc;
_libga68_posixargv;
_libga68_posixclose;