Working on the heap and the new type system. Doesn't compile right now.
git-svn-id: http://picoc.googlecode.com/svn/trunk@33 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
df1d001b76
commit
626c29a639
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ CFLAGS=-Wall -g
|
||||||
LIBS=-lm
|
LIBS=-lm
|
||||||
|
|
||||||
TARGET = picoc
|
TARGET = picoc
|
||||||
SRCS = picoc.c table.c str.c parse.c lex.c intrinsic.c
|
SRCS = picoc.c table.c str.c parse.c lex.c intrinsic.c heap.c
|
||||||
OBJS := $(SRCS:%.c=%.o)
|
OBJS := $(SRCS:%.c=%.o)
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
135
heap.c
Normal file
135
heap.c
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
||||||
|
#include <memory.h>
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
#define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */
|
||||||
|
#define SPLIT_MEM_THRESHOLD 16 /* don't split memory which is close in size */
|
||||||
|
|
||||||
|
struct AllocNode
|
||||||
|
{
|
||||||
|
int Size;
|
||||||
|
struct AllocNode *NextFree;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char HeapMemory[HEAP_SIZE]; /* all memory - stack and heap */
|
||||||
|
static void *StackFrame = &HeapMemory; /* the current stack frame */
|
||||||
|
static void *StackTop = &HeapMemory; /* the top of the stack */
|
||||||
|
|
||||||
|
static void *HeapBottom = &HeapMemory[HEAP_SIZE]; /* the bottom of the (downward-growing) heap */
|
||||||
|
static struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */
|
||||||
|
static struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */
|
||||||
|
|
||||||
|
/* initialise the stack and heap storage */
|
||||||
|
void HeapInit()
|
||||||
|
{
|
||||||
|
int Count;
|
||||||
|
|
||||||
|
StackFrame = &HeapMemory;
|
||||||
|
StackTop = &HeapMemory;
|
||||||
|
*(void **)StackFrame = NULL;
|
||||||
|
HeapBottom = &HeapMemory[HEAP_SIZE];
|
||||||
|
FreeListBig = NULL;
|
||||||
|
for (Count = 0; Count < FREELIST_BUCKETS; Count++)
|
||||||
|
FreeListBucket[Count] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate some space on the stack, in the current stack frame
|
||||||
|
* clears memory. can return NULL if out of stack space */
|
||||||
|
void *HeapAllocStack(int Size)
|
||||||
|
{
|
||||||
|
void *NewMem = StackTop;
|
||||||
|
void *NewTop = StackTop + MEM_ALIGN(Size);
|
||||||
|
if (NewTop > HeapBottom)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
StackTop = NewTop;
|
||||||
|
memset(NewMem, '\0', Size);
|
||||||
|
return NewMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push a new stack frame on to the stack */
|
||||||
|
void HeapPushStackFrame()
|
||||||
|
{
|
||||||
|
*(void **)StackTop = StackFrame;
|
||||||
|
StackFrame = StackTop;
|
||||||
|
StackTop += sizeof(void *);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
||||||
|
int HeapPopStackFrame()
|
||||||
|
{
|
||||||
|
if (*(void **)StackFrame == NULL)
|
||||||
|
{
|
||||||
|
StackTop = StackFrame;
|
||||||
|
StackFrame = *(void **)StackFrame;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
||||||
|
void *HeapAlloc(int Size)
|
||||||
|
{
|
||||||
|
struct AllocNode *NewMem = NULL;
|
||||||
|
struct AllocNode **FreeNode;
|
||||||
|
int AllocSize = MEM_ALIGN(Size) + sizeof(NewMem->Size);
|
||||||
|
int Bucket = AllocSize >> 2;
|
||||||
|
|
||||||
|
if (Bucket < FREELIST_BUCKETS && FreeListBucket[Bucket] != NULL)
|
||||||
|
{ /* try to allocate from a freelist bucket first */
|
||||||
|
NewMem = FreeListBucket[Bucket];
|
||||||
|
FreeListBucket[Bucket] = *(struct AllocNode **)NewMem;
|
||||||
|
NewMem->Size = AllocSize;
|
||||||
|
}
|
||||||
|
else if (FreeListBig != NULL)
|
||||||
|
{ /* grab the first item from the "big" freelist we can fit in */
|
||||||
|
for (FreeNode = &FreeListBig; *FreeNode != NULL && (*FreeNode)->Size < AllocSize; FreeNode = &(*FreeNode)->NextFree)
|
||||||
|
{}
|
||||||
|
|
||||||
|
if (*FreeNode != NULL)
|
||||||
|
{
|
||||||
|
if ((*FreeNode)->Size < Size + SPLIT_MEM_THRESHOLD)
|
||||||
|
{ /* close in size - reduce fragmentation by not splitting */
|
||||||
|
NewMem = *FreeNode;
|
||||||
|
*FreeNode = NewMem->NextFree;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* split this big memory chunk */
|
||||||
|
NewMem = *FreeNode + (*FreeNode)->Size - AllocSize;
|
||||||
|
(*FreeNode)->Size -= AllocSize;
|
||||||
|
NewMem->Size = AllocSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewMem == NULL)
|
||||||
|
{ /* couldn't allocate from a freelist - try to increase the size of the heap area */
|
||||||
|
if (HeapBottom - AllocSize < StackTop)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
HeapBottom -= AllocSize;
|
||||||
|
NewMem = HeapBottom;
|
||||||
|
NewMem->Size = AllocSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&NewMem->NextFree, '\0', AllocSize-sizeof(NewMem->Size));
|
||||||
|
return (void *)&NewMem->NextFree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free some dynamically allocated memory */
|
||||||
|
void HeapFree(void *Mem)
|
||||||
|
{
|
||||||
|
int Bucket = ((struct AllocNode *)Mem)->Size >> 2;
|
||||||
|
|
||||||
|
if (Bucket < FREELIST_BUCKETS)
|
||||||
|
{ /* we can fit it in a bucket */
|
||||||
|
*(struct AllocNode **)Mem = FreeListBucket[Bucket];
|
||||||
|
FreeListBucket[Bucket] = (struct AllocNode *)Mem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* put it in the big memory freelist */
|
||||||
|
((struct AllocNode *)Mem)->NextFree = FreeListBig;
|
||||||
|
FreeListBig = (struct AllocNode *)Mem;
|
||||||
|
}
|
||||||
|
}
|
69
picoc.h
69
picoc.h
|
@ -4,13 +4,14 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* configurable options */
|
/* configurable options */
|
||||||
#define USE_MALLOC
|
#define HEAP_SIZE 2048 /* space for the heap and the stack */
|
||||||
#define GLOBAL_TABLE_SIZE 397 /* global variable table */
|
#define GLOBAL_TABLE_SIZE 397 /* global variable table */
|
||||||
#define FUNCTION_STORE_MAX 200 /* maximum number of used-defined functions and macros */
|
#define FUNCTION_STORE_MAX 200 /* maximum number of used-defined functions and macros */
|
||||||
#define STACK_MAX 10 /* maximum function call stack depth */
|
#define STACK_MAX 10 /* maximum function call stack depth */
|
||||||
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */
|
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */
|
||||||
#define LOCAL_TABLE_SIZE 11 /* maximum number of local variables */
|
#define LOCAL_TABLE_SIZE 11 /* maximum number of local variables */
|
||||||
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
|
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
|
||||||
|
#define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */
|
||||||
|
|
||||||
/* handy definitions */
|
/* handy definitions */
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
#define min(x,y) (((x)<(y))?(x):(y))
|
#define min(x,y) (((x)<(y))?(x):(y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MEM_ALIGN(x) (((x) + ARCH_ALIGN_WORDSIZE - 1) & ~(ARCH_ALIGN_WORDSIZE-1))
|
||||||
|
|
||||||
#define LOG10E 0.43429448190325182765
|
#define LOG10E 0.43429448190325182765
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
|
@ -112,27 +115,57 @@ struct FuncDef
|
||||||
};
|
};
|
||||||
|
|
||||||
/* values */
|
/* values */
|
||||||
enum ValueType
|
enum BaseType
|
||||||
{
|
{
|
||||||
TypeVoid,
|
TypeVoid, /* no type */
|
||||||
TypeInt,
|
TypeInt, /* integer */
|
||||||
TypeFP,
|
TypeFP, /* floating point */
|
||||||
TypeString,
|
TypeChar, /* a single character - acts like an integer except in machine memory access */
|
||||||
TypeFunction,
|
TypeString, /* a constant source text string with C string emulation */
|
||||||
TypeMacro
|
TypeFunction, /* a function */
|
||||||
|
TypeMacro, /* a macro */
|
||||||
|
TypePointer, /* a pointer */
|
||||||
|
TypeArray, /* an array of a sub-type */
|
||||||
|
TypeType /* a type (eg. typedef) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueType
|
||||||
|
{
|
||||||
|
enum BaseType Base; /* what kind of type this is */
|
||||||
|
struct ValueType *SubType; /* sub-type for pointer and array types */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArrayValue
|
||||||
|
{
|
||||||
|
unsigned int Size; /* the number of elements in the array */
|
||||||
|
void *Data; /* pointer to the array data */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointerValue
|
||||||
|
{
|
||||||
|
struct Value *Segment; /* array or basic value which this points to, NULL for machine memory access */
|
||||||
|
union s {
|
||||||
|
unsigned int Offset; /* index into an array */
|
||||||
|
void *Memory; /* machine memory pointer for raw memory access */
|
||||||
|
} Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
union AnyValue
|
union AnyValue
|
||||||
{
|
{
|
||||||
int Integer;
|
unsigned char *Character;
|
||||||
double FP;
|
short *ShortInteger;
|
||||||
|
int *Integer;
|
||||||
|
double *FP;
|
||||||
Str String;
|
Str String;
|
||||||
|
struct ArrayValue Array;
|
||||||
|
struct PointerValue Pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Value
|
struct Value
|
||||||
{
|
{
|
||||||
enum ValueType Typ;
|
struct ValueType Typ;
|
||||||
union AnyValue Val;
|
char MustFree;
|
||||||
|
union AnyValue *Val;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* hash table data structure */
|
/* hash table data structure */
|
||||||
|
@ -200,12 +233,20 @@ void LexToEndOfLine(struct LexState *Lexer);
|
||||||
/* parse.c */
|
/* parse.c */
|
||||||
void ParseInit(void);
|
void ParseInit(void);
|
||||||
void Parse(const Str *FileName, const Str *Source, int RunIt);
|
void Parse(const Str *FileName, const Str *Source, int RunIt);
|
||||||
int ParseType(struct LexState *Lexer, enum ValueType *Typ);
|
int ParseType(struct LexState *Lexer, struct ValueType *Typ);
|
||||||
|
|
||||||
/* intrinsic.c */
|
/* intrinsic.c */
|
||||||
void IntrinsicInit(struct Table *GlobalTable);
|
void IntrinsicInit(struct Table *GlobalTable);
|
||||||
void IntrinsicGetLexer(struct LexState *Lexer, int IntrinsicId);
|
void IntrinsicGetLexer(struct LexState *Lexer, int IntrinsicId);
|
||||||
void IntrinsicCall(struct LexState *Lexer, struct Value *Result, enum ValueType ReturnType, int IntrinsicId);
|
void IntrinsicCall(struct LexState *Lexer, struct Value *Result, struct ValueType ReturnType, int IntrinsicId);
|
||||||
|
|
||||||
|
/* heap.c */
|
||||||
|
void HeapInit();
|
||||||
|
void *HeapAllocStack(int Size);
|
||||||
|
void HeapPushStackFrame();
|
||||||
|
int HeapPopStackFrame();
|
||||||
|
void *HeapAlloc(int Size);
|
||||||
|
void HeapFree(void *Mem);
|
||||||
|
|
||||||
#endif /* PICOC_H */
|
#endif /* PICOC_H */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue