// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // TypeData.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 15:12:51 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Tue Jul 12 17:21:49 2016 // Update Count : 50 // #include #include #include #include "Common/utility.h" #include "TypeData.h" #include "SynTree/Type.h" #include "SynTree/Declaration.h" #include "SynTree/Expression.h" #include "SynTree/Statement.h" #include "SynTree/Initializer.h" TypeData::TypeData( Kind k ) : kind( k ), base( 0 ), forall( 0 ) { switch ( kind ) { case Unknown: case Pointer: case EnumConstant: // nothing else to initialize break; case Basic: basic = new Basic_t; break; case Array: array = new Array_t; array->dimension = 0; array->isVarLen = false; array->isStatic = false; break; case Function: function = new Function_t; function->params = 0; function->idList = 0; function->oldDeclList = 0; function->body = 0; function->hasBody = false; function->newStyle = false; break; case Aggregate: aggregate = new Aggregate_t; aggregate->params = 0; aggregate->actuals = 0; aggregate->fields = 0; break; case AggregateInst: aggInst = new AggInst_t; aggInst->aggregate = 0; aggInst->params = 0; break; case Enum: enumeration = new Enumeration_t; enumeration->constants = 0; break; case Symbolic: case SymbolicInst: symbolic = new Symbolic_t; symbolic->params = 0; symbolic->actuals = 0; symbolic->assertions = 0; break; case Variable: variable = new Variable_t; variable->tyClass = DeclarationNode::Type; variable->assertions = 0; break; case Tuple: tuple = new Tuple_t; tuple->members = 0; break; case Typeof: typeexpr = new Typeof_t; typeexpr->expr = 0; break; case Builtin: builtin = new Builtin_t; break; case Attr: attr = new Attr_t; attr->expr = 0; attr->type = 0; break; } // switch } TypeData::~TypeData() { delete base; delete forall; switch ( kind ) { case Unknown: case Pointer: case EnumConstant: // nothing to destroy break; case Basic: delete basic; break; case Array: delete array->dimension; delete array; break; case Function: delete function->params; delete function->idList; delete function->oldDeclList; delete function->body; delete function; break; case Aggregate: delete aggregate->params; delete aggregate->actuals; delete aggregate->fields; delete aggregate; break; case AggregateInst: delete aggInst->aggregate; delete aggInst->params; delete aggInst; break; case Enum: delete enumeration->constants; delete enumeration; break; case Symbolic: case SymbolicInst: delete symbolic->params; delete symbolic->actuals; delete symbolic->assertions; delete symbolic; break; case Variable: delete variable->assertions; delete variable; break; case Tuple: delete tuple->members; delete tuple; break; case Typeof: delete typeexpr->expr; delete typeexpr; break; case Builtin: delete builtin; break; case Attr: delete attr->expr; delete attr->type; delete attr; break; } // switch } TypeData *TypeData::clone() const { TypeData *newtype = new TypeData( kind ); newtype->qualifiers = qualifiers; newtype->base = maybeClone( base ); newtype->forall = maybeClone( forall ); switch ( kind ) { case Unknown: case EnumConstant: case Pointer: // nothing else to copy break; case Basic: newtype->basic->typeSpec = basic->typeSpec; newtype->basic->modifiers = basic->modifiers; break; case Array: newtype->array->dimension = maybeClone( array->dimension ); newtype->array->isVarLen = array->isVarLen; newtype->array->isStatic = array->isStatic; break; case Function: newtype->function->params = maybeClone( function->params ); newtype->function->idList = maybeClone( function->idList ); newtype->function->oldDeclList = maybeClone( function->oldDeclList ); newtype->function->body = maybeClone( function->body ); newtype->function->hasBody = function->hasBody; newtype->function->newStyle = function->newStyle; break; case Aggregate: newtype->aggregate->params = maybeClone( aggregate->params ); newtype->aggregate->actuals = maybeClone( aggregate->actuals ); newtype->aggregate->fields = maybeClone( aggregate->fields ); newtype->aggregate->name = aggregate->name; newtype->aggregate->kind = aggregate->kind; break; case AggregateInst: newtype->aggInst->aggregate = maybeClone( aggInst->aggregate ); newtype->aggInst->params = maybeClone( aggInst->params ); break; case Enum: newtype->enumeration->name = enumeration->name; newtype->enumeration->constants = maybeClone( enumeration->constants ); break; case Symbolic: case SymbolicInst: newtype->symbolic->params = maybeClone( symbolic->params ); newtype->symbolic->actuals = maybeClone( symbolic->actuals ); newtype->symbolic->assertions = maybeClone( symbolic->assertions ); newtype->symbolic->isTypedef = symbolic->isTypedef; newtype->symbolic->name = symbolic->name; break; case Variable: newtype->variable->assertions = maybeClone( variable->assertions ); newtype->variable->name = variable->name; newtype->variable->tyClass = variable->tyClass; break; case Tuple: newtype->tuple->members = maybeClone( tuple->members ); break; case Typeof: newtype->typeexpr->expr = maybeClone( typeexpr->expr ); break; case Builtin: newtype->builtin->type = builtin->type; break; case Attr: newtype->attr->expr = maybeClone( attr->expr ); newtype->attr->type = maybeClone( attr->type ); break; } // switch return newtype; } void TypeData::print( std::ostream &os, int indent ) const { using std::endl; using std::string; printEnums( qualifiers.begin(), qualifiers.end(), DeclarationNode::qualifierName, os ); if ( forall ) { os << "forall " << endl; forall->printList( os, indent + 4 ); } // if switch ( kind ) { case Unknown: os << "entity of unknown type "; break; case Pointer: os << "pointer "; if ( base ) { os << "to "; base->print( os, indent ); } // if break; case EnumConstant: os << "enumeration constant "; break; case Basic: printEnums( basic->modifiers.begin(), basic->modifiers.end(), DeclarationNode::modifierName, os ); printEnums( basic->typeSpec.begin(), basic->typeSpec.end(), DeclarationNode::basicTypeName, os ); break; case Array: if ( array->isStatic ) { os << "static "; } // if if ( array->dimension ) { os << "array of "; array->dimension->printOneLine( os, indent ); } else if ( array->isVarLen ) { os << "variable-length array of "; } else { os << "open array of "; } // if if ( base ) { base->print( os, indent ); } // if break; case Function: os << "function" << endl; if ( function->params ) { os << string( indent + 2, ' ' ) << "with parameters " << endl; function->params->printList( os, indent + 4 ); } else { os << string( indent + 2, ' ' ) << "with no parameters " << endl; } // if if ( function->idList ) { os << string( indent + 2, ' ' ) << "with old-style identifier list " << endl; function->idList->printList( os, indent + 4 ); } // if if ( function->oldDeclList ) { os << string( indent + 2, ' ' ) << "with old-style declaration list " << endl; function->oldDeclList->printList( os, indent + 4 ); } // if os << string( indent + 2, ' ' ) << "returning "; if ( base ) { base->print( os, indent + 4 ); } else { os << "nothing "; } // if os << endl; if ( function->hasBody ) { os << string( indent + 2, ' ' ) << "with body " << endl; } // if if ( function->body ) { function->body->printList( os, indent + 2 ); } // if break; case Aggregate: os << DeclarationNode::aggregateName[ aggregate->kind ] << ' ' << aggregate->name << endl; if ( aggregate->params ) { os << string( indent + 2, ' ' ) << "with type parameters " << endl; aggregate->params->printList( os, indent + 4 ); } // if if ( aggregate->actuals ) { os << string( indent + 2, ' ' ) << "instantiated with actual parameters " << endl; aggregate->actuals->printList( os, indent + 4 ); } // if if ( aggregate->fields ) { os << string( indent + 2, ' ' ) << "with members " << endl; aggregate->fields->printList( os, indent + 4 ); /// } else { /// os << string( indent + 2, ' ' ) << "with no members " << endl; } // if break; case AggregateInst: if ( aggInst->aggregate ) { os << "instance of " ; aggInst->aggregate->print( os, indent ); } else { os << "instance of an unspecified aggregate "; } // if if ( aggInst->params ) { os << string( indent + 2, ' ' ) << "with parameters " << endl; aggInst->params->printList( os, indent + 2 ); } // if break; case Enum: os << "enumeration "; if ( enumeration->constants ) { os << "with constants" << endl; enumeration->constants->printList( os, indent + 2 ); } // if break; case SymbolicInst: os << "instance of type " << symbolic->name; if ( symbolic->actuals ) { os << " with parameters" << endl; symbolic->actuals->printList( os, indent + 2 ); } // if break; case Symbolic: if ( symbolic->isTypedef ) { os << "typedef definition "; } else { os << "type definition "; } // if if ( symbolic->params ) { os << endl << string( indent + 2, ' ' ) << "with parameters" << endl; symbolic->params->printList( os, indent + 2 ); } // if if ( symbolic->assertions ) { os << endl << string( indent + 2, ' ' ) << "with assertions" << endl; symbolic->assertions->printList( os, indent + 4 ); os << string( indent + 2, ' ' ); } // if if ( base ) { os << "for "; base->print( os, indent + 2 ); } // if break; case Variable: os << DeclarationNode::typeClassName[ variable->tyClass ] << " variable "; if ( variable->assertions ) { os << endl << string( indent + 2, ' ' ) << "with assertions" << endl; variable->assertions->printList( os, indent + 4 ); os << string( indent + 2, ' ' ); } // if break; case Tuple: os << "tuple "; if ( tuple->members ) { os << "with members " << endl; tuple->members->printList( os, indent + 2 ); } // if break; case Typeof: os << "type-of expression "; if ( typeexpr->expr ) { typeexpr->expr->print( os, indent + 2 ); } // if break; case Attr: os << "attribute type decl " << attr->name << " applied to "; if ( attr->expr ) { attr->expr->print( os, indent + 2 ); } // if if ( attr->type ) { attr->type->print( os, indent + 2 ); } // if break; case Builtin: os << "gcc builtin type"; break; default: os << "internal error: TypeData::print " << kind << endl; assert( false ); } // switch } TypeData *TypeData::extractAggregate( bool toplevel ) const { TypeData *ret = 0; switch ( kind ) { case Aggregate: if ( ! toplevel && aggregate->fields ) { ret = clone(); ret->qualifiers.clear(); } // if break; case Enum: if ( ! toplevel && enumeration->constants ) { ret = clone(); ret->qualifiers.clear(); } // if break; case AggregateInst: if ( aggInst->aggregate ) { ret = aggInst->aggregate->extractAggregate( false ); } // if break; default: if ( base ) { ret = base->extractAggregate( false ); } // if } // switch return ret; } void buildForall( const DeclarationNode *firstNode, std::list< TypeDecl* > &outputList ) { buildList( firstNode, outputList ); for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) { if ( (*i)->get_kind() == TypeDecl::Any ) { // add assertion parameters to `type' tyvars in reverse order // add dtor: void ^?{}(T *) FunctionType *dtorType = new FunctionType( Type::Qualifiers(), false ); dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); (*i)->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, 0, false, false ) ); // add copy ctor: void ?{}(T *, T) FunctionType *copyCtorType = new FunctionType( Type::Qualifiers(), false ); copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) ); (*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, copyCtorType, 0, false, false ) ); // add default ctor: void ?{}(T *) FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false ); ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); (*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, 0, false, false ) ); // add assignment operator: T * ?=?(T *, T) FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) ); assignType->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) ); (*i)->get_assertions().push_front( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignType, 0, false, false ) ); } // if } // for } Declaration *TypeData::buildDecl( std::string name, DeclarationNode::StorageClass sc, Expression *bitfieldWidth, bool isInline, bool isNoreturn, LinkageSpec::Type linkage, Initializer *init ) const { if ( kind == TypeData::Function ) { FunctionDecl *decl; if ( function->hasBody ) { if ( function->body ) { Statement *stmt = function->body->build(); CompoundStmt *body = dynamic_cast< CompoundStmt* >( stmt ); assert( body ); decl = new FunctionDecl( name, sc, linkage, buildFunction(), body, isInline, isNoreturn ); } else { // std::list