packages feed

ddc-code-0.4.3.1: sea/primitive/Primitive.h

// Primitive operations that generated C code uses.
//   These should all be static inlined so we can compile programs without
//   linking against external code. Operations that need manifest object
//   code should be defined somewhere else, and preferably imported
//   by the foreign-function interface.
#pragma once
#include <stdio.h>
#include "Runtime.h"

// Error Primops --------------------------------------------------------------
// Fail ungracefully.
//   Called when we find an internal runtime error.
static inline 
void _FAIL(void)
{       abort();
}


// Store Primops --------------------------------------------------------------
extern addr_t _DDC__heapTop;
extern addr_t _DDC__heapMax;


// Create the initial store.
static inline
void    _CREATE (nat_t bytes)
{
        _DDC__heapTop   = malloc (bytes);
        _DDC__heapMax   = _DDC__heapTop + bytes;        
}


// Allocate some space in the store
static inline 
addr_t _ALLOC (nat_t bytes) 
{       
        addr_t obj      = _DDC__heapTop;
        _DDC__heapTop   = _DDC__heapTop + bytes;
        return obj;
}       


// Check whether there is enough space on the heap to allocate 
//  an object of the given size in bytes.
static inline
bool_t  _CHECK (nat_t bytes)
{
        return (_DDC__heapTop + bytes < _DDC__heapMax);
}


// Get the size of a type.
#define _SIZE(type) \
        sizeof(type)


// Get the log2 of the size of a type.
#define _SIZE2(type) \
         (sizeof(unsigned int) * 8 - __builtin_clz (sizeof(type)))


// Read from a field of an Object.
//   We use an explicit macro to make it easier to see what is happening in
//   the generated code.
#define _READ(type,addr,offset) \
        (*((type *)(addr + offset)))


// Write to a field of an Object.
//   We use an explicit macro to make it easier to see what is happening in
//   the generated code.
#define _WRITE(type,addr,offset,val) \
        ((*((type *)(addr + offset))) = val)


// Add two addresses.
#define _PLUSADDR(addr,offset) \
        (addr + offset)


// Read from a pointer plus an offset in bytes.
#define _PEEK(type,ptr,offset) \
        (*(type *)(((uint8_t *) ptr) + offset))


// Write to a pointer plus an offset in bytes.
#define _POKE(type,ptr,offset,val) \
        (*((type *)( ((uint8_t*)ptr) + offset)) = val)


// Add an offset in bytes to a pointer.
#define _PLUSPTR(type,ptr,offset) \
        ((type *)( ((uint8_t *)ptr) + offset))


// Subtract an offset in bytes from a pointer.
#define _MINUSPTR(type,ptr,offset) \
        ((type *)( ((uint8_t *)ptr) - offset))


// Pointer to address conversions.
#define _MAKEPTR(type,addr) \
        ((type *)addr)


#define _TAKEPTR(type,ptr) \
        ((addr_t)ptr)


#define _CASTPTR(dstType,srcType,ptr) \
        ((dstType*)ptr)


// Other primitives -----------------------------------------------------------
// These are defined in C land and linked into the runtime library.
extern string_t* primShowInt    (int   i);
extern string_t* primShowNat    (nat_t i);
extern void      primPutTextLit (string_t* str);
extern void      primPutString  (string_t* str);