Changeset 8d182b1 for src/CodeGen/GenType.cc
- Timestamp:
- Nov 14, 2023, 12:19:09 PM (23 months ago)
- Branches:
- master
- Children:
- 1ccae59, 89a8bab
- Parents:
- df8ba61a (diff), 5625427 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/GenType.cc
rdf8ba61a r8d182b1 21 21 #include "AST/Print.hpp" // for print 22 22 #include "AST/Vector.hpp" // for vector 23 #include "CodeGenerator.h" // for CodeGenerator 24 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new 25 #include "SynTree/Declaration.h" // for DeclarationWithType 26 #include "SynTree/Expression.h" // for Expression 27 #include "SynTree/Type.h" // for PointerType, Type, FunctionType 28 #include "SynTree/Visitor.h" // for Visitor 23 #include "CodeGeneratorNew.hpp" // for CodeGenerator 24 #include "Common/UniqueName.h" // for UniqueName 29 25 30 26 namespace CodeGen { 31 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {32 std::string typeString;33 GenType( const std::string &typeString, const Options &options );34 35 void previsit( BaseSyntaxNode * );36 void postvisit( BaseSyntaxNode * );37 38 void postvisit( FunctionType * funcType );39 void postvisit( VoidType * voidType );40 void postvisit( BasicType * basicType );41 void postvisit( PointerType * pointerType );42 void postvisit( ArrayType * arrayType );43 void postvisit( ReferenceType * refType );44 void postvisit( StructInstType * structInst );45 void postvisit( UnionInstType * unionInst );46 void postvisit( EnumInstType * enumInst );47 void postvisit( TypeInstType * typeInst );48 void postvisit( TupleType * tupleType );49 void postvisit( VarArgsType * varArgsType );50 void postvisit( ZeroType * zeroType );51 void postvisit( OneType * oneType );52 void postvisit( GlobalScopeType * globalType );53 void postvisit( TraitInstType * inst );54 void postvisit( TypeofType * typeof );55 void postvisit( VTableType * vtable );56 void postvisit( QualifiedType * qualType );57 58 private:59 void handleQualifiers( Type *type );60 std::string handleGeneric( ReferenceToType * refType );61 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );62 63 Options options;64 };65 66 std::string genType( Type *type, const std::string &baseString, const Options &options ) {67 PassVisitor<GenType> gt( baseString, options );68 std::ostringstream os;69 70 if ( ! type->get_attributes().empty() ) {71 PassVisitor<CodeGenerator> cg( os, options );72 cg.pass.genAttributes( type->get_attributes() );73 } // if74 75 type->accept( gt );76 return os.str() + gt.pass.typeString;77 }78 79 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {80 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );81 }82 83 std::string genPrettyType( Type * type, const std::string & baseString ) {84 return genType( type, baseString, true, false );85 }86 87 GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}88 89 // *** BaseSyntaxNode90 void GenType::previsit( BaseSyntaxNode * ) {91 // turn off automatic recursion for all nodes, to allow each visitor to92 // precisely control the order in which its children are visited.93 visit_children = false;94 }95 96 void GenType::postvisit( BaseSyntaxNode * node ) {97 std::stringstream ss;98 node->print( ss );99 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );100 }101 102 void GenType::postvisit( VoidType * voidType ) {103 typeString = "void " + typeString;104 handleQualifiers( voidType );105 }106 107 void GenType::postvisit( BasicType * basicType ) {108 BasicType::Kind kind = basicType->kind;109 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );110 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;111 handleQualifiers( basicType );112 }113 114 void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) {115 std::ostringstream os;116 if ( typeString != "" ) {117 if ( typeString[ 0 ] == '*' ) {118 os << "(" << typeString << ")";119 } else {120 os << typeString;121 } // if122 } // if123 os << "[";124 125 if ( isStatic ) {126 os << "static ";127 } // if128 if ( qualifiers.is_const ) {129 os << "const ";130 } // if131 if ( qualifiers.is_volatile ) {132 os << "volatile ";133 } // if134 if ( qualifiers.is_restrict ) {135 os << "__restrict ";136 } // if137 if ( qualifiers.is_atomic ) {138 os << "_Atomic ";139 } // if140 if ( dimension != 0 ) {141 PassVisitor<CodeGenerator> cg( os, options );142 dimension->accept( cg );143 } else if ( isVarLen ) {144 // no dimension expression on a VLA means it came in with the * token145 os << "*";146 } // if147 os << "]";148 149 typeString = os.str();150 151 base->accept( *visitor );152 }153 154 void GenType::postvisit( PointerType * pointerType ) {155 assert( pointerType->base != 0);156 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {157 genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );158 } else {159 handleQualifiers( pointerType );160 if ( typeString[ 0 ] == '?' ) {161 typeString = "* " + typeString;162 } else {163 typeString = "*" + typeString;164 } // if165 pointerType->base->accept( *visitor );166 } // if167 }168 169 void GenType::postvisit( ArrayType * arrayType ) {170 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );171 }172 173 void GenType::postvisit( ReferenceType * refType ) {174 assert( 0 != refType->base );175 assertf( ! options.genC, "Reference types should not reach code generation." );176 handleQualifiers( refType );177 typeString = "&" + typeString;178 refType->base->accept( *visitor );179 }180 181 void GenType::postvisit( FunctionType * funcType ) {182 std::ostringstream os;183 184 if ( typeString != "" ) {185 if ( typeString[ 0 ] == '*' ) {186 os << "(" << typeString << ")";187 } else {188 os << typeString;189 } // if190 } // if191 192 /************* parameters ***************/193 194 const std::list<DeclarationWithType *> &pars = funcType->parameters;195 196 if ( pars.empty() ) {197 if ( funcType->get_isVarArgs() ) {198 os << "()";199 } else {200 os << "(void)";201 } // if202 } else {203 PassVisitor<CodeGenerator> cg( os, options );204 os << "(" ;205 206 cg.pass.genCommaList( pars.begin(), pars.end() );207 208 if ( funcType->get_isVarArgs() ) {209 os << ", ...";210 } // if211 os << ")";212 } // if213 214 typeString = os.str();215 216 if ( funcType->returnVals.size() == 0 ) {217 typeString = "void " + typeString;218 } else {219 funcType->returnVals.front()->get_type()->accept( *visitor );220 } // if221 222 // add forall223 if( ! funcType->forall.empty() && ! options.genC ) {224 // assertf( ! genC, "Aggregate type parameters should not reach code generation." );225 std::ostringstream os;226 PassVisitor<CodeGenerator> cg( os, options );227 os << "forall(";228 cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );229 os << ")" << std::endl;230 typeString = os.str() + typeString;231 }232 }233 234 std::string GenType::handleGeneric( ReferenceToType * refType ) {235 if ( ! refType->parameters.empty() ) {236 std::ostringstream os;237 PassVisitor<CodeGenerator> cg( os, options );238 os << "(";239 cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );240 os << ") ";241 return os.str();242 }243 return "";244 }245 246 void GenType::postvisit( StructInstType * structInst ) {247 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;248 if ( options.genC ) typeString = "struct " + typeString;249 handleQualifiers( structInst );250 }251 252 void GenType::postvisit( UnionInstType * unionInst ) {253 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;254 if ( options.genC ) typeString = "union " + typeString;255 handleQualifiers( unionInst );256 }257 258 void GenType::postvisit( EnumInstType * enumInst ) {259 if ( enumInst->baseEnum && enumInst->baseEnum->base ) {260 typeString = genType(enumInst->baseEnum->base, typeString, options);261 } else {262 typeString = enumInst->name + " " + typeString;263 if ( options.genC ) {264 typeString = "enum " + typeString;265 }266 }267 handleQualifiers( enumInst );268 }269 270 void GenType::postvisit( TypeInstType * typeInst ) {271 assertf( ! options.genC, "Type instance types should not reach code generation." );272 typeString = typeInst->name + " " + typeString;273 handleQualifiers( typeInst );274 }275 276 void GenType::postvisit( TupleType * tupleType ) {277 assertf( ! options.genC, "Tuple types should not reach code generation." );278 unsigned int i = 0;279 std::ostringstream os;280 os << "[";281 for ( Type * t : *tupleType ) {282 i++;283 os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");284 }285 os << "] ";286 typeString = os.str() + typeString;287 }288 289 void GenType::postvisit( VarArgsType * varArgsType ) {290 typeString = "__builtin_va_list " + typeString;291 handleQualifiers( varArgsType );292 }293 294 void GenType::postvisit( ZeroType * zeroType ) {295 // ideally these wouldn't hit codegen at all, but should be safe to make them ints296 typeString = (options.pretty ? "zero_t " : "long int ") + typeString;297 handleQualifiers( zeroType );298 }299 300 void GenType::postvisit( OneType * oneType ) {301 // ideally these wouldn't hit codegen at all, but should be safe to make them ints302 typeString = (options.pretty ? "one_t " : "long int ") + typeString;303 handleQualifiers( oneType );304 }305 306 void GenType::postvisit( GlobalScopeType * globalType ) {307 assertf( ! options.genC, "Global scope type should not reach code generation." );308 handleQualifiers( globalType );309 }310 311 void GenType::postvisit( TraitInstType * inst ) {312 assertf( ! options.genC, "Trait types should not reach code generation." );313 typeString = inst->name + " " + typeString;314 handleQualifiers( inst );315 }316 317 void GenType::postvisit( TypeofType * typeof ) {318 std::ostringstream os;319 PassVisitor<CodeGenerator> cg( os, options );320 os << "typeof(";321 typeof->expr->accept( cg );322 os << ") " << typeString;323 typeString = os.str();324 handleQualifiers( typeof );325 }326 327 void GenType::postvisit( VTableType * vtable ) {328 assertf( ! options.genC, "Virtual table types should not reach code generation." );329 std::ostringstream os;330 os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString;331 typeString = os.str();332 handleQualifiers( vtable );333 }334 335 void GenType::postvisit( QualifiedType * qualType ) {336 assertf( ! options.genC, "Qualified types should not reach code generation." );337 std::ostringstream os;338 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString;339 typeString = os.str();340 handleQualifiers( qualType );341 }342 343 void GenType::handleQualifiers( Type * type ) {344 if ( type->get_const() ) {345 typeString = "const " + typeString;346 } // if347 if ( type->get_volatile() ) {348 typeString = "volatile " + typeString;349 } // if350 if ( type->get_restrict() ) {351 typeString = "__restrict " + typeString;352 } // if353 if ( type->get_atomic() ) {354 typeString = "_Atomic " + typeString;355 } // if356 }357 27 358 28 namespace { 359 29 360 #warning Remove the _new when old version is removed. 361 struct GenType_new : 30 struct GenType final : 362 31 public ast::WithShortCircuiting, 363 public ast::WithVisitorRef<GenType _new> {32 public ast::WithVisitorRef<GenType> { 364 33 std::string result; 365 GenType _new( const std::string &typeString, const Options &options );34 GenType( const std::string &typeString, const Options &options ); 366 35 367 36 void previsit( ast::Node const * ); … … 397 66 }; 398 67 399 GenType _new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}400 401 void GenType _new::previsit( ast::Node const * ) {68 GenType::GenType( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {} 69 70 void GenType::previsit( ast::Node const * ) { 402 71 // Turn off automatic recursion for all nodes, to allow each visitor to 403 72 // precisely control the order in which its children are visited. … … 405 74 } 406 75 407 void GenType _new::postvisit( ast::Node const * node ) {76 void GenType::postvisit( ast::Node const * node ) { 408 77 std::stringstream ss; 409 78 ast::print( ss, node ); … … 411 80 } 412 81 413 void GenType _new::postvisit( ast::VoidType const * type ) {82 void GenType::postvisit( ast::VoidType const * type ) { 414 83 result = "void " + result; 415 84 handleQualifiers( type ); 416 85 } 417 86 418 void GenType _new::postvisit( ast::BasicType const * type ) {87 void GenType::postvisit( ast::BasicType const * type ) { 419 88 ast::BasicType::Kind kind = type->kind; 420 89 assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES ); … … 423 92 } 424 93 425 void GenType _new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {94 void GenType::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) { 426 95 std::ostringstream os; 427 96 if ( result != "" ) { … … 449 118 } 450 119 if ( dimension != 0 ) { 451 ast::Pass<CodeGenerator _new>::read( dimension, os, options );120 ast::Pass<CodeGenerator>::read( dimension, os, options ); 452 121 } else if ( isVarLen ) { 453 122 // no dimension expression on a VLA means it came in with the * token … … 461 130 } 462 131 463 void GenType _new::postvisit( ast::PointerType const * type ) {132 void GenType::postvisit( ast::PointerType const * type ) { 464 133 if ( type->isStatic || type->isVarLen || type->dimension ) { 465 134 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); … … 475 144 } 476 145 477 void GenType _new::postvisit( ast::ArrayType const * type ) {146 void GenType::postvisit( ast::ArrayType const * type ) { 478 147 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 479 148 } 480 149 481 void GenType _new::postvisit( ast::ReferenceType const * type ) {150 void GenType::postvisit( ast::ReferenceType const * type ) { 482 151 assertf( !options.genC, "Reference types should not reach code generation." ); 483 152 handleQualifiers( type ); … … 486 155 } 487 156 488 void GenType _new::postvisit( ast::FunctionType const * type ) {157 void GenType::postvisit( ast::FunctionType const * type ) { 489 158 std::ostringstream os; 490 159 … … 526 195 //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." ); 527 196 std::ostringstream os; 528 ast::Pass<CodeGenerator _new> cg( os, options );197 ast::Pass<CodeGenerator> cg( os, options ); 529 198 os << "forall("; 530 199 cg.core.genCommaList( type->forall ); … … 534 203 } 535 204 536 std::string GenType _new::handleGeneric( ast::BaseInstType const * type ) {205 std::string GenType::handleGeneric( ast::BaseInstType const * type ) { 537 206 if ( !type->params.empty() ) { 538 207 std::ostringstream os; 539 ast::Pass<CodeGenerator _new> cg( os, options );208 ast::Pass<CodeGenerator> cg( os, options ); 540 209 os << "("; 541 210 cg.core.genCommaList( type->params ); … … 546 215 } 547 216 548 void GenType _new::postvisit( ast::StructInstType const * type ) {217 void GenType::postvisit( ast::StructInstType const * type ) { 549 218 result = type->name + handleGeneric( type ) + " " + result; 550 219 if ( options.genC ) result = "struct " + result; … … 552 221 } 553 222 554 void GenType _new::postvisit( ast::UnionInstType const * type ) {223 void GenType::postvisit( ast::UnionInstType const * type ) { 555 224 result = type->name + handleGeneric( type ) + " " + result; 556 225 if ( options.genC ) result = "union " + result; … … 558 227 } 559 228 560 void GenType _new::postvisit( ast::EnumInstType const * type ) {229 void GenType::postvisit( ast::EnumInstType const * type ) { 561 230 if ( type->base && type->base->base ) { 562 231 result = genType( type->base->base, result, options ); … … 570 239 } 571 240 572 void GenType _new::postvisit( ast::TypeInstType const * type ) {241 void GenType::postvisit( ast::TypeInstType const * type ) { 573 242 assertf( !options.genC, "TypeInstType should not reach code generation." ); 574 243 result = type->name + " " + result; … … 576 245 } 577 246 578 void GenType _new::postvisit( ast::TupleType const * type ) {247 void GenType::postvisit( ast::TupleType const * type ) { 579 248 assertf( !options.genC, "TupleType should not reach code generation." ); 580 249 unsigned int i = 0; … … 589 258 } 590 259 591 void GenType _new::postvisit( ast::VarArgsType const * type ) {260 void GenType::postvisit( ast::VarArgsType const * type ) { 592 261 result = "__builtin_va_list " + result; 593 262 handleQualifiers( type ); 594 263 } 595 264 596 void GenType _new::postvisit( ast::ZeroType const * type ) {265 void GenType::postvisit( ast::ZeroType const * type ) { 597 266 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 598 267 result = (options.pretty ? "zero_t " : "long int ") + result; … … 600 269 } 601 270 602 void GenType _new::postvisit( ast::OneType const * type ) {271 void GenType::postvisit( ast::OneType const * type ) { 603 272 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 604 273 result = (options.pretty ? "one_t " : "long int ") + result; … … 606 275 } 607 276 608 void GenType _new::postvisit( ast::GlobalScopeType const * type ) {277 void GenType::postvisit( ast::GlobalScopeType const * type ) { 609 278 assertf( !options.genC, "GlobalScopeType should not reach code generation." ); 610 279 handleQualifiers( type ); 611 280 } 612 281 613 void GenType _new::postvisit( ast::TraitInstType const * type ) {282 void GenType::postvisit( ast::TraitInstType const * type ) { 614 283 assertf( !options.genC, "TraitInstType should not reach code generation." ); 615 284 result = type->name + " " + result; … … 617 286 } 618 287 619 void GenType _new::postvisit( ast::TypeofType const * type ) {288 void GenType::postvisit( ast::TypeofType const * type ) { 620 289 std::ostringstream os; 621 290 os << "typeof("; 622 ast::Pass<CodeGenerator _new>::read( type, os, options );291 ast::Pass<CodeGenerator>::read( type, os, options ); 623 292 os << ") " << result; 624 293 result = os.str(); … … 626 295 } 627 296 628 void GenType _new::postvisit( ast::VTableType const * type ) {297 void GenType::postvisit( ast::VTableType const * type ) { 629 298 assertf( !options.genC, "Virtual table types should not reach code generation." ); 630 299 std::ostringstream os; … … 634 303 } 635 304 636 void GenType _new::postvisit( ast::QualifiedType const * type ) {305 void GenType::postvisit( ast::QualifiedType const * type ) { 637 306 assertf( !options.genC, "QualifiedType should not reach code generation." ); 638 307 std::ostringstream os; … … 642 311 } 643 312 644 void GenType _new::handleQualifiers( ast::Type const * type ) {313 void GenType::handleQualifiers( ast::Type const * type ) { 645 314 if ( type->is_const() ) { 646 315 result = "const " + result; … … 657 326 } 658 327 659 std::string GenType _new::genParamList( const ast::vector<ast::Type> & range ) {328 std::string GenType::genParamList( const ast::vector<ast::Type> & range ) { 660 329 auto cur = range.begin(); 661 330 auto end = range.end(); 662 331 if ( cur == end ) return ""; 663 332 std::ostringstream oss; 664 for ( unsigned int i = 0 ; ; ++i ) { 665 oss << genType( *cur++, "__param_" + std::to_string(i), options ); 333 UniqueName param( "__param_" ); 334 while ( true ) { 335 oss << genType( *cur++, options.genC ? param.newName() : "", options ); 666 336 if ( cur == end ) break; 667 337 oss << ", "; … … 675 345 std::ostringstream os; 676 346 if ( !type->attributes.empty() ) { 677 ast::Pass<CodeGenerator _new> cg( os, options );347 ast::Pass<CodeGenerator> cg( os, options ); 678 348 cg.core.genAttributes( type->attributes ); 679 349 } 680 350 681 return os.str() + ast::Pass<GenType _new>::read( type, base, options );351 return os.str() + ast::Pass<GenType>::read( type, base, options ); 682 352 } 683 353 684 354 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) { 685 return ast::Pass<GenType _new>::read( type, base, options );355 return ast::Pass<GenType>::read( type, base, options ); 686 356 } 687 357
Note:
See TracChangeset
for help on using the changeset viewer.