URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Type.cpp] - Rev 48
Compare with Previous | Blame | View Log
// ============================================================================ // __ // \\__/ o\ (C) 2012-2018 Robert Finch, Waterloo // \ __ / All rights reserved. // \/_// robfinch<remove>@finitron.ca // || // // CC64 - 'C' derived language compiler // - 64 bit CPU // // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This source file is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // ============================================================================ // #include "stdafx.h" extern int64_t initbyte(); extern int64_t initchar(); extern int64_t initshort(); extern int64_t initlong(); extern int64_t initquad(); extern int64_t initfloat(); extern int64_t inittriple(); int64_t InitializePointer(); bool TYP::IsScalar() { return type == bt_byte || type == bt_char || type == bt_short || type == bt_long || type == bt_ubyte || type == bt_uchar || type == bt_ushort || type == bt_ulong || type == bt_enum || type == bt_exception || type == bt_unsigned; } TYP *TYP::GetBtp() { if (btp==0) return nullptr; return &compiler.typeTable[btp]; }; TYP *TYP::GetPtr(int n) { if (n==0) return nullptr; return &compiler.typeTable[n]; }; int TYP::GetIndex() { return this - &compiler.typeTable[0]; }; TYP *TYP::Copy(TYP *src) { TYP *dst = nullptr; dfs.printf("<TYP__Copy>\n"); if (src) { dst = allocTYP(); // if (dst==nullptr) // throw gcnew C64::C64Exception(); memcpy(dst,src,sizeof(TYP)); dfs.printf("A"); if (src->btp && src->GetBtp()) { dfs.printf("B"); dst->btp = Copy(src->GetBtp())->GetIndex(); } dfs.printf("C"); // We want to keep any base type indicator so Clear() isn't called. dst->lst.head = 0; dst->lst.tail = 0; dst->sname = new std::string(*src->sname); dfs.printf("D"); TABLE::CopySymbolTable(&dst->lst,&src->lst); } dfs.printf("</TYP__Copy>\n"); return dst; } TYP *TYP::Make(int bt, int siz) { TYP *tp; dfs.puts("<TYP__Make>\n"); tp = allocTYP(); if (tp == nullptr) return nullptr; tp->val_flag = 0; tp->isArray = FALSE; tp->size = siz; tp->type = (e_bt)bt; tp->typeno = bt; tp->precision = siz * 8; if (bt == bt_pointer) tp->isUnsigned = TRUE; dfs.puts("</TYP__Make>\n"); return tp; } // Given just a type number return the size int TYP::GetSize(int num) { if (num == 0) return 0; return compiler.typeTable[num].size; } // Basic type is one of the built in types supported by the compiler. // Returns the basic type number for the type. The basic type number does // not include complex types like struct, union, or class. For a struct, // union, or class one of bt_struct, bt_union or bt_class is returned. int TYP::GetBasicType(int num) { if (num==0) return 0; return compiler.typeTable[num].type; } int TYP::GetHash() { int n; TYP *p, *p1; n = 0; p = this; if (p==nullptr) throw new C64PException(ERR_NULLPOINTER,2); do { if (p->type==bt_pointer) n+=20000; p1 = p; p = p->GetBtp(); } while (p); n += p1->typeno; return n; } int TYP::GetElementSize() { int n; TYP *p, *p1; n = 0; p = this; do { p1 = p; p = p->GetBtp(); } while (p); switch(p1->type) { case bt_byte: case bt_ubyte: return 1; case bt_char: case bt_uchar: return 2; case bt_short: case bt_ushort: return 4; case bt_long: case bt_ulong: case bt_pointer: return 8; case bt_float: case bt_double: return 8; case bt_struct: case bt_class: return p1->size; default: return 8; } return n; } void TYP::put_ty() { switch(type) { case bt_exception: lfs.printf("Exception"); break; case bt_byte: lfs.printf("Byte"); break; case bt_ubyte: lfs.printf("Unsigned Byte"); break; case bt_char: lfs.printf("Char"); break; case bt_short: lfs.printf("Short"); break; case bt_enum: lfs.printf("enum "); goto ucont; case bt_long: lfs.printf("Long"); break; case bt_unsigned: lfs.printf("unsigned long"); break; case bt_float: lfs.printf("Float"); break; case bt_double: lfs.printf("Double"); break; case bt_pointer: if( val_flag == 0) lfs.printf("Pointer to "); else lfs.printf("Array of "); GetBtp()->put_ty(); break; case bt_class: lfs.printf("class "); goto ucont; case bt_union: lfs.printf("union "); goto ucont; case bt_struct: lfs.printf("struct "); ucont: if(sname->length() == 0) lfs.printf("<no name> "); else lfs.printf("%s ",(char *)sname->c_str()); break; case bt_ifunc: case bt_func: lfs.printf("Function returning "); GetBtp()->put_ty(); break; } } bool TYP::IsSameType(TYP *a, TYP *b, bool exact) { if (a == b) return (true); switch (a->type) { case bt_float: if (b->type == bt_float) return (true); if (b->type == bt_double) return (true); return (false); case bt_double: if (b->type == bt_float) return (true); if (b->type == bt_double) return (true); return (false); case bt_long: if (b->type == bt_long) return (true); if (!exact) { if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_char) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_ulong: if (b->type == bt_ulong) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_char) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_short: if (b->type == bt_short) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_char) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_ushort: if (b->type == bt_ushort) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_char) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_uchar: if (b->type == bt_uchar) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_char) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_char: if (b->type == bt_char) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_byte: if (b->type == bt_byte) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_char) return (true); if (b->type == bt_ubyte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_ubyte: if (b->type == bt_ubyte) return (true); if (!exact) { if (b->type == bt_long) return (true); if (b->type == bt_ulong) return (true); if (b->type == bt_short) return (true); if (b->type == bt_ushort) return (true); if (b->type == bt_uchar) return (true); if (b->type == bt_char) return (true); if (b->type == bt_byte) return (true); if (b->type == bt_enum) return (true); } return (false); case bt_pointer: if (a->type != b->type) return (false); if (a->GetBtp() == b->GetBtp()) return (true); if (a->GetBtp() && b->GetBtp()) return (TYP::IsSameType(a->GetBtp(), b->GetBtp(), exact)); return (false); case bt_struct: case bt_union: case bt_class: if (a->type != b->type) return (false); if (a->GetBtp() == b->GetBtp()) return (true); if (a->GetBtp() && b->GetBtp()) return (TYP::IsSameType(a->GetBtp(), b->GetBtp(), exact)); return (false); case bt_enum: if (a->typeno == b->typeno) return (true); if (!exact) { if (b->type == bt_long || b->type == bt_ulong || b->type == bt_short || b->type == bt_ushort || b->type == bt_char || b->type == bt_uchar || b->type == bt_enum ) return (true); } return (false); } return (false); } // Initialize the type. Unions can't be initialized. int64_t TYP::Initialize() { int64_t nbytes; switch (type) { case bt_ubyte: case bt_byte: nbytes = initbyte(); break; case bt_uchar: case bt_char: case bt_enum: nbytes = initchar(); break; case bt_ushort: case bt_short: nbytes = initshort(); break; case bt_pointer: if (val_flag) nbytes = InitializeArray(); else nbytes = InitializePointer(); break; case bt_exception: case bt_ulong: case bt_long: nbytes = initlong(); break; case bt_struct: nbytes = InitializeStruct(); break; case bt_union: nbytes = InitializeUnion(); break; case bt_quad: nbytes = initquad(); break; case bt_float: case bt_double: nbytes = initfloat(); break; case bt_triple: nbytes = inittriple(); break; default: error(ERR_NOINIT); nbytes = 0; } return (nbytes); } int64_t TYP::InitializeArray() { int64_t nbytes; char *p; nbytes = 0; if (lastst == begin) { NextToken(); /* skip past the brace */ while (lastst != end) { // Allow char array initialization like { "something", "somethingelse" } if (lastst == sconst && (GetBtp()->type == bt_char || GetBtp()->type == bt_uchar)) { nbytes = strlen(laststr) * 2 + 2; p = laststr; while (*p) GenerateChar(*p++); GenerateChar(0); NextToken(); } else nbytes += GetBtp()->Initialize(); if (lastst == comma) NextToken(); else if (lastst != end) error(ERR_PUNCT); } NextToken(); /* skip closing brace */ } else if (lastst == sconst && (GetBtp()->type == bt_char || GetBtp()->type == bt_uchar)) { nbytes = strlen(laststr) * 2 + 2; p = laststr; while (*p) GenerateChar(*p++); GenerateChar(0); NextToken(); } else if (lastst != semicolon) error(ERR_ILLINIT); if (nbytes < size) { genstorage(size - nbytes); nbytes = size; } else if (size != 0 && nbytes > size) error(ERR_INITSIZE); /* too many initializers */ return (nbytes); } int64_t TYP::InitializeStruct() { SYM *sp; int64_t nbytes; needpunc(begin, 25); nbytes = 0; sp = sp->GetPtr(lst.GetHead()); /* start at top of symbol table */ while (sp != 0) { while (nbytes < sp->value.i) { /* align properly */ // nbytes += GenerateByte(0); GenerateByte(0); // nbytes++; } nbytes += sp->tp->Initialize(); if (lastst == comma) NextToken(); else if (lastst == end) break; else error(ERR_PUNCT); sp = sp->GetNextPtr(); } if (nbytes < size) genstorage(size - nbytes); needpunc(end, 26); return (size); } int64_t TYP::InitializeUnion() { SYM *sp; int64_t nbytes; int64_t val; ENODE *node = nullptr; bool found = false; nbytes = 0; val = GetConstExpression(&node); if (node == nullptr) // syntax error in GetConstExpression() return (0); sp = sp->GetPtr(lst.GetHead()); /* start at top of symbol table */ while (sp != 0) { if (IsSameType(sp->tp, node->tp, false)) { nbytes = node->esize; switch (sp->tp->type) { case bt_byte: nbytes = 1; GenerateByte(val); break; case bt_ubyte: nbytes = 1; GenerateByte(val); break; case bt_char: nbytes = 2; GenerateChar(val); break; case bt_uchar: nbytes = 2; GenerateChar(val); break; case bt_short: nbytes = 4; GenerateWord(val); break; case bt_ushort: nbytes = 4; GenerateWord(val); break; case bt_long: nbytes = 8; GenerateLong(val); break; case bt_ulong: nbytes = 8; GenerateLong(val); break; case bt_float: nbytes = 8; GenerateFloat((Float128 *)val); break; case bt_double: nbytes = 8; GenerateFloat((Float128 *)val); break; case bt_quad: nbytes = 16; GenerateQuad((Float128 *)val); break; } found = true; break; } sp = sp->GetNextPtr(); } if (!found) error(ERR_INIT_UNION); if (lastst != semicolon) error(ERR_PUNCT); if (nbytes < size) genstorage(size - nbytes); return (size); } // GC support bool TYP::FindPointerInStruct() { SYM *sp; sp = sp->GetPtr(lst.GetHead()); // start at top of symbol table while (sp != 0) { if (sp->tp->FindPointer()) return (true); sp = sp->GetNextPtr(); } return (false); } bool TYP::FindPointer() { switch (type) { case bt_pointer: return (val_flag == FALSE); // array ? case bt_struct: return (FindPointerInStruct()); case bt_union: return (FindPointerInStruct()); case bt_class: return (FindPointerInStruct()); } return (false); } // Return whether or not the type might be able to be skipped over by the GC. bool TYP::IsSkippable() { switch (type) { case bt_struct: return(true); case bt_union: return(true); case bt_class: return(true); case bt_pointer: if (val_flag == TRUE) return (true); return(false); } // For now primitive types are not skipped over. They would need to be // grouped for skipping. return (false); } // The problem is there are two trees of information. The LHS and the RHS. // The RHS is a tree of nodes containing expressions and data to load. // The nodes in the RHS have to be matched up against the structure elements // of the target LHS. // This little bit of code is dead code. But it might be useful to match // the expression trees at some point. ENODE *TYP::BuildEnodeTree() { ENODE *ep1, *ep2, *ep3; SYM *thead, *first; first = thead = SYM::GetPtr(lst.GetHead()); ep1 = ep2 = nullptr; while (thead) { if (thead->tp->IsStructType()) { ep3 = thead->tp->BuildEnodeTree(); } else ep3 = nullptr; ep1 = makenode(en_void, ep2, ep1); ep1->SetType(thead->tp); ep1->p[2] = ep3; thead = SYM::GetPtr(thead->next); } return (ep1); } // Get the natural alignment for a given type. int TYP::Alignment() { //printf("DIAG: type NULL in alignment()\r\n"); if (this == NULL) return AL_BYTE; switch (type) { case bt_byte: case bt_ubyte: return AL_BYTE; case bt_char: case bt_uchar: return AL_CHAR; case bt_short: case bt_ushort: return AL_SHORT; case bt_long: case bt_ulong: return AL_LONG; case bt_enum: return AL_CHAR; case bt_pointer: if (val_flag) return (GetBtp()->Alignment()); else return (sizeOfPtr);//isShort ? AL_SHORT : AL_POINTER); case bt_float: return AL_FLOAT; case bt_double: return AL_DOUBLE; case bt_triple: return AL_TRIPLE; case bt_class: case bt_struct: case bt_union: return (alignment) ? alignment : AL_STRUCT; default: return AL_CHAR; } } // Figure out the worst alignment required. int TYP::walignment() { SYM *sp; //printf("DIAG: type NULL in alignment()\r\n"); if (this == NULL) return imax(AL_BYTE, worstAlignment); switch (type) { case bt_byte: case bt_ubyte: return imax(AL_BYTE, worstAlignment); case bt_char: case bt_uchar: return imax(AL_CHAR, worstAlignment); case bt_short: case bt_ushort: return imax(AL_SHORT, worstAlignment); case bt_long: case bt_ulong: return imax(AL_LONG, worstAlignment); case bt_enum: return imax(AL_CHAR, worstAlignment); case bt_pointer: if (val_flag) return imax(GetBtp()->Alignment(), worstAlignment); else { return (imax(sizeOfPtr, worstAlignment)); // return (imax(AL_POINTER,worstAlignment)); } case bt_float: return imax(AL_FLOAT, worstAlignment); case bt_double: return imax(AL_DOUBLE, worstAlignment); case bt_triple: return imax(AL_TRIPLE, worstAlignment); case bt_class: case bt_struct: case bt_union: sp = (SYM *)sp->GetPtr(lst.GetHead()); worstAlignment = alignment; while (sp != NULL) { if (sp->tp && sp->tp->alignment) { worstAlignment = imax(worstAlignment, sp->tp->alignment); } else worstAlignment = imax(worstAlignment, sp->tp->walignment()); sp = sp->GetNextPtr(); } return (worstAlignment); default: return (imax(AL_CHAR, worstAlignment)); } } int TYP::roundAlignment() { worstAlignment = 0; if (type == bt_struct || type == bt_union || type == bt_class) { return walignment(); } return Alignment(); } // Round the size of the type up according to the worst alignment. int TYP::roundSize() { int sz; int wa; worstAlignment = 0; if (type == bt_struct || type == bt_union || type == bt_class) { wa = walignment(); sz = size; if (sz == 0) return (0); if (sz % wa) sz += (wa - (sz % wa)); //while (sz % wa) // sz++; return (sz); } // return ((tp->precision+7)/8); return (size); }