Added a new alignment system which should correspond to the struct alignments of most processors. This means that picoc struct members should match up with native C structs in most cases. I hope.
git-svn-id: http://picoc.googlecode.com/svn/trunk@532 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
4751cfd15c
commit
e44b198946
|
@ -2,7 +2,7 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
/* the picoc version string */
|
/* the picoc version string */
|
||||||
#define PICOC_VERSION "v2.1 beta r" VER
|
#define PICOC_VERSION "v2.1 beta r" VER /* VER is the subversion version number, obtained via the Makefile */
|
||||||
static const char *VersionString = NULL;
|
static const char *VersionString = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -387,7 +387,7 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
|
||||||
if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize)
|
if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize)
|
||||||
AssignFail(Parser, "from an array of size %d to one of size %d", NULL, NULL, DestValue->Typ->ArraySize, SourceValue->Typ->ArraySize, FuncName, ParamNo);
|
AssignFail(Parser, "from an array of size %d to one of size %d", NULL, NULL, DestValue->Typ->ArraySize, SourceValue->Typ->ArraySize, FuncName, ParamNo);
|
||||||
|
|
||||||
memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(DestValue));
|
memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(DestValue, FALSE));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeStruct:
|
case TypeStruct:
|
||||||
|
@ -395,7 +395,7 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
|
||||||
if (DestValue->Typ != SourceValue->Typ)
|
if (DestValue->Typ != SourceValue->Typ)
|
||||||
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
||||||
|
|
||||||
memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(SourceValue));
|
memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(SourceValue, FALSE));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
3
picoc.h
3
picoc.h
|
@ -143,6 +143,7 @@ struct ValueType
|
||||||
enum BaseType Base; /* what kind of type this is */
|
enum BaseType Base; /* what kind of type this is */
|
||||||
int ArraySize; /* the size of an array type */
|
int ArraySize; /* the size of an array type */
|
||||||
int Sizeof; /* the storage required */
|
int Sizeof; /* the storage required */
|
||||||
|
int AlignBytes; /* the alignment boundary of this type */
|
||||||
const char *Identifier; /* the name of a struct or union */
|
const char *Identifier; /* the name of a struct or union */
|
||||||
struct ValueType *FromType; /* the type we're derived from (or NULL) */
|
struct ValueType *FromType; /* the type we're derived from (or NULL) */
|
||||||
struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */
|
struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */
|
||||||
|
@ -363,7 +364,7 @@ double ExpressionCoerceFP(struct Value *Val);
|
||||||
void TypeInit();
|
void TypeInit();
|
||||||
void TypeCleanup();
|
void TypeCleanup();
|
||||||
int TypeSize(struct ValueType *Typ, int ArraySize, int Compact);
|
int TypeSize(struct ValueType *Typ, int ArraySize, int Compact);
|
||||||
int TypeSizeValue(struct Value *Val);
|
int TypeSizeValue(struct Value *Val, int Compact);
|
||||||
int TypeStackSizeValue(struct Value *Val);
|
int TypeStackSizeValue(struct Value *Val);
|
||||||
int TypeLastAccessibleOffset(struct Value *Val);
|
int TypeLastAccessibleOffset(struct Value *Val);
|
||||||
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ);
|
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ);
|
||||||
|
|
101
type.c
101
type.c
|
@ -22,14 +22,18 @@ struct ValueType *CharPtrPtrType;
|
||||||
struct ValueType *CharArrayType;
|
struct ValueType *CharArrayType;
|
||||||
struct ValueType *VoidPtrType;
|
struct ValueType *VoidPtrType;
|
||||||
|
|
||||||
|
static int PointerAlignBytes;
|
||||||
|
static int IntAlignBytes;
|
||||||
|
|
||||||
|
|
||||||
/* add a new type to the set of types we know about */
|
/* add a new type to the set of types we know about */
|
||||||
struct ValueType *TypeAdd(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int Sizeof)
|
struct ValueType *TypeAdd(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int Sizeof, int AlignBytes)
|
||||||
{
|
{
|
||||||
struct ValueType *NewType = VariableAlloc(Parser, sizeof(struct ValueType), TRUE);
|
struct ValueType *NewType = VariableAlloc(Parser, sizeof(struct ValueType), TRUE);
|
||||||
NewType->Base = Base;
|
NewType->Base = Base;
|
||||||
NewType->ArraySize = ArraySize;
|
NewType->ArraySize = ArraySize;
|
||||||
NewType->Sizeof = Sizeof;
|
NewType->Sizeof = Sizeof;
|
||||||
|
NewType->AlignBytes = AlignBytes;
|
||||||
NewType->Identifier = Identifier;
|
NewType->Identifier = Identifier;
|
||||||
NewType->Members = NULL;
|
NewType->Members = NULL;
|
||||||
NewType->FromType = ParentType;
|
NewType->FromType = ParentType;
|
||||||
|
@ -45,6 +49,7 @@ struct ValueType *TypeAdd(struct ParseState *Parser, struct ValueType *ParentTyp
|
||||||
struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier)
|
struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier)
|
||||||
{
|
{
|
||||||
int Sizeof;
|
int Sizeof;
|
||||||
|
int AlignBytes;
|
||||||
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
||||||
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
|
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
|
||||||
ThisType = ThisType->Next;
|
ThisType = ThisType->Next;
|
||||||
|
@ -54,28 +59,28 @@ struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *P
|
||||||
|
|
||||||
switch (Base)
|
switch (Base)
|
||||||
{
|
{
|
||||||
case TypePointer: Sizeof = sizeof(void *); break;
|
case TypePointer: Sizeof = sizeof(void *); AlignBytes = PointerAlignBytes; break;
|
||||||
case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; break;
|
case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break;
|
||||||
case TypeEnum: Sizeof = sizeof(int); break;
|
case TypeEnum: Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break;
|
||||||
default: Sizeof = 0; break; /* structs and unions will get bigger when we add members to them */
|
default: Sizeof = 0; AlignBytes = 0; break; /* structs and unions will get bigger when we add members to them */
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeAdd(Parser, ParentType, Base, ArraySize, Identifier, Sizeof);
|
return TypeAdd(Parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stack space used by a value */
|
/* stack space used by a value */
|
||||||
int TypeStackSizeValue(struct Value *Val)
|
int TypeStackSizeValue(struct Value *Val)
|
||||||
{
|
{
|
||||||
if (Val != NULL && Val->ValOnStack)
|
if (Val != NULL && Val->ValOnStack)
|
||||||
return TypeSizeValue(Val);
|
return TypeSizeValue(Val, FALSE);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* memory used by a value */
|
/* memory used by a value */
|
||||||
int TypeSizeValue(struct Value *Val)
|
int TypeSizeValue(struct Value *Val, int Compact)
|
||||||
{
|
{
|
||||||
if (IS_INTEGER_NUMERIC(Val))
|
if (IS_INTEGER_NUMERIC(Val) && !Compact)
|
||||||
return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */
|
return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */
|
||||||
else if (Val->Typ->Base != TypeArray)
|
else if (Val->Typ->Base != TypeArray)
|
||||||
return Val->Typ->Sizeof;
|
return Val->Typ->Sizeof;
|
||||||
|
@ -94,21 +99,13 @@ int TypeSize(struct ValueType *Typ, int ArraySize, int Compact)
|
||||||
return Typ->FromType->Sizeof * ArraySize;
|
return Typ->FromType->Sizeof * ArraySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* memory used by the base (non-array) type of a type. This is used for alignment. */
|
|
||||||
int TypeSizeAlignment(struct ValueType *Typ)
|
|
||||||
{
|
|
||||||
if (Typ->Base == TypeArray)
|
|
||||||
return sizeof(ALIGN_TYPE);
|
|
||||||
else
|
|
||||||
return Typ->Sizeof;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add a base type */
|
/* add a base type */
|
||||||
void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof)
|
void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof, int AlignBytes)
|
||||||
{
|
{
|
||||||
TypeNode->Base = Base;
|
TypeNode->Base = Base;
|
||||||
TypeNode->ArraySize = 0;
|
TypeNode->ArraySize = 0;
|
||||||
TypeNode->Sizeof = Sizeof;
|
TypeNode->Sizeof = Sizeof;
|
||||||
|
TypeNode->AlignBytes = AlignBytes;
|
||||||
TypeNode->Identifier = StrEmpty;
|
TypeNode->Identifier = StrEmpty;
|
||||||
TypeNode->Members = NULL;
|
TypeNode->Members = NULL;
|
||||||
TypeNode->FromType = NULL;
|
TypeNode->FromType = NULL;
|
||||||
|
@ -121,27 +118,39 @@ void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof)
|
||||||
/* initialise the type system */
|
/* initialise the type system */
|
||||||
void TypeInit()
|
void TypeInit()
|
||||||
{
|
{
|
||||||
UberType.DerivedTypeList = NULL;
|
struct IntAlign { char x; int y; } ia;
|
||||||
TypeAddBaseType(&IntType, TypeInt, sizeof(int));
|
struct ShortAlign { char x; short y; } sa;
|
||||||
TypeAddBaseType(&ShortType, TypeShort, sizeof(short));
|
struct CharAlign { char x; char y; } ca;
|
||||||
TypeAddBaseType(&CharType, TypeChar, sizeof(unsigned char));
|
struct LongAlign { char x; long y; } la;
|
||||||
TypeAddBaseType(&LongType, TypeLong, sizeof(long));
|
|
||||||
TypeAddBaseType(&UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int));
|
|
||||||
TypeAddBaseType(&UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short));
|
|
||||||
TypeAddBaseType(&UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long));
|
|
||||||
TypeAddBaseType(&VoidType, TypeVoid, 0);
|
|
||||||
TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int));
|
|
||||||
TypeAddBaseType(&MacroType, TypeMacro, sizeof(int));
|
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
TypeAddBaseType(&FPType, TypeFP, sizeof(double));
|
struct DoubleAlign { char x; double y; } da;
|
||||||
TypeAddBaseType(&TypeType, Type_Type, sizeof(double)); /* must be large enough to cast to a double */
|
|
||||||
#else
|
|
||||||
TypeAddBaseType(&TypeType, Type_Type, sizeof(struct ValueType *));
|
|
||||||
#endif
|
#endif
|
||||||
CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char));
|
struct PointerAlign { char x; void *y; } pa;
|
||||||
CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(void *));
|
|
||||||
CharPtrPtrType = TypeAdd(NULL, CharPtrType, TypePointer, 0, StrEmpty, sizeof(void *));
|
IntAlignBytes = (char *)&ia.y - &ia.x;
|
||||||
VoidPtrType = TypeAdd(NULL, &VoidType, TypePointer, 0, StrEmpty, sizeof(void *));
|
PointerAlignBytes = (char *)&pa.y - &pa.x;
|
||||||
|
|
||||||
|
UberType.DerivedTypeList = NULL;
|
||||||
|
TypeAddBaseType(&IntType, TypeInt, sizeof(int), IntAlignBytes);
|
||||||
|
TypeAddBaseType(&ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x);
|
||||||
|
TypeAddBaseType(&CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x);
|
||||||
|
TypeAddBaseType(&LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x);
|
||||||
|
TypeAddBaseType(&UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes);
|
||||||
|
TypeAddBaseType(&UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x);
|
||||||
|
TypeAddBaseType(&UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x);
|
||||||
|
TypeAddBaseType(&VoidType, TypeVoid, 0, 0);
|
||||||
|
TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int), IntAlignBytes);
|
||||||
|
TypeAddBaseType(&MacroType, TypeMacro, sizeof(int), IntAlignBytes);
|
||||||
|
#ifndef NO_FP
|
||||||
|
TypeAddBaseType(&FPType, TypeFP, sizeof(double), (char *)&da.y - &da.x);
|
||||||
|
TypeAddBaseType(&TypeType, Type_Type, sizeof(double), (char *)&da.y - &da.x); /* must be large enough to cast to a double */
|
||||||
|
#else
|
||||||
|
TypeAddBaseType(&TypeType, Type_Type, sizeof(struct ValueType *), PointerAlignBytes);
|
||||||
|
#endif
|
||||||
|
CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char), (char *)&ca.y - &ca.x);
|
||||||
|
CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||||
|
CharPtrPtrType = TypeAdd(NULL, CharPtrType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||||
|
VoidPtrType = TypeAdd(NULL, &VoidType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deallocate heap-allocated types */
|
/* deallocate heap-allocated types */
|
||||||
|
@ -218,21 +227,26 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
||||||
if (IsStruct)
|
if (IsStruct)
|
||||||
{
|
{
|
||||||
/* allocate this member's location in the struct */
|
/* allocate this member's location in the struct */
|
||||||
AlignBoundary = TypeSizeAlignment(MemberValue->Typ);
|
AlignBoundary = MemberValue->Typ->AlignBytes;
|
||||||
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0)
|
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0)
|
||||||
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||||
|
|
||||||
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
||||||
(*Typ)->Sizeof += TypeSizeValue(MemberValue);
|
(*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* union members always start at 0, make sure it's big enough to hold the largest member */
|
/* union members always start at 0, make sure it's big enough to hold the largest member */
|
||||||
MemberValue->Val->Integer = 0;
|
MemberValue->Val->Integer = 0;
|
||||||
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
||||||
(*Typ)->Sizeof = TypeSizeValue(MemberValue);
|
(*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* make sure to align to the size of the largest member's alignment */
|
||||||
|
if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes)
|
||||||
|
(*Typ)->AlignBytes = MemberValue->Typ->AlignBytes;
|
||||||
|
|
||||||
|
/* define it */
|
||||||
if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->Line, Parser->CharacterPos))
|
if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->Line, Parser->CharacterPos))
|
||||||
ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier);
|
ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier);
|
||||||
|
|
||||||
|
@ -241,6 +255,11 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
||||||
|
|
||||||
} while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace);
|
} while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace);
|
||||||
|
|
||||||
|
/* now align the structure to the size of its largest member's alignment */
|
||||||
|
AlignBoundary = (*Typ)->AlignBytes;
|
||||||
|
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0)
|
||||||
|
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||||
|
|
||||||
LexGetToken(Parser, NULL, TRUE);
|
LexGetToken(Parser, NULL, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value
|
||||||
struct ValueType *DType = FromValue->Typ;
|
struct ValueType *DType = FromValue->Typ;
|
||||||
struct Value *NewValue;
|
struct Value *NewValue;
|
||||||
char TmpBuf[MAX_TMP_COPY_BUF];
|
char TmpBuf[MAX_TMP_COPY_BUF];
|
||||||
int CopySize = TypeSizeValue(FromValue);
|
int CopySize = TypeSizeValue(FromValue, TRUE);
|
||||||
|
|
||||||
assert(CopySize <= MAX_TMP_COPY_BUF);
|
assert(CopySize <= MAX_TMP_COPY_BUF);
|
||||||
memcpy((void *)&TmpBuf[0], (void *)FromValue->Val, CopySize);
|
memcpy((void *)&TmpBuf[0], (void *)FromValue->Val, CopySize);
|
||||||
|
@ -223,7 +223,7 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
||||||
|
|
||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
if (Var->ValOnStack)
|
if (Var->ValOnStack)
|
||||||
printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(Var)), (unsigned long)Var);
|
printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(Var, FALSE)), (unsigned long)Var);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Var->ValOnHeap)
|
if (Var->ValOnHeap)
|
||||||
|
@ -234,7 +234,7 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
||||||
Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */
|
Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */
|
||||||
}
|
}
|
||||||
else if (Var->ValOnStack)
|
else if (Var->ValOnStack)
|
||||||
Success = HeapPopStack(Var, sizeof(struct Value) + TypeSizeValue(Var)); /* free from stack */
|
Success = HeapPopStack(Var, sizeof(struct Value) + TypeSizeValue(Var, FALSE)); /* free from stack */
|
||||||
else
|
else
|
||||||
Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */
|
Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue