Changeset fc12f05 for src/CodeGen/GenType.cc
- Timestamp:
- Nov 13, 2023, 3:43:43 AM (23 months ago)
- Branches:
- master
- Children:
- 25f2798
- Parents:
- 0030b508 (diff), 2174191 (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
r0030b508 rfc12f05 19 19 #include <sstream> // for operator<<, ostringstream, basic_os... 20 20 21 #include "CodeGenerator.h" // for CodeGenerator 22 #include "SynTree/Declaration.h" // for DeclarationWithType 23 #include "SynTree/Expression.h" // for Expression 24 #include "SynTree/Type.h" // for PointerType, Type, FunctionType 25 #include "SynTree/Visitor.h" // for Visitor 21 #include "AST/Print.hpp" // for print 22 #include "AST/Vector.hpp" // for vector 23 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new 24 #include "Common/UniqueName.h" // for UniqueName 26 25 27 26 namespace CodeGen { 28 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting { 29 std::string typeString; 30 GenType( const std::string &typeString, const Options &options ); 31 32 void previsit( BaseSyntaxNode * ); 33 void postvisit( BaseSyntaxNode * ); 34 35 void postvisit( FunctionType * funcType ); 36 void postvisit( VoidType * voidType ); 37 void postvisit( BasicType * basicType ); 38 void postvisit( PointerType * pointerType ); 39 void postvisit( ArrayType * arrayType ); 40 void postvisit( ReferenceType * refType ); 41 void postvisit( StructInstType * structInst ); 42 void postvisit( UnionInstType * unionInst ); 43 void postvisit( EnumInstType * enumInst ); 44 void postvisit( TypeInstType * typeInst ); 45 void postvisit( TupleType * tupleType ); 46 void postvisit( VarArgsType * varArgsType ); 47 void postvisit( ZeroType * zeroType ); 48 void postvisit( OneType * oneType ); 49 void postvisit( GlobalScopeType * globalType ); 50 void postvisit( TraitInstType * inst ); 51 void postvisit( TypeofType * typeof ); 52 void postvisit( VTableType * vtable ); 53 void postvisit( QualifiedType * qualType ); 54 55 private: 56 void handleQualifiers( Type *type ); 57 std::string handleGeneric( ReferenceToType * refType ); 58 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 59 60 Options options; 61 }; 62 63 std::string genType( Type *type, const std::string &baseString, const Options &options ) { 64 PassVisitor<GenType> gt( baseString, options ); 27 28 namespace { 29 30 #warning Remove the _new when old version is removed. 31 struct GenType_new : 32 public ast::WithShortCircuiting, 33 public ast::WithVisitorRef<GenType_new> { 34 std::string result; 35 GenType_new( const std::string &typeString, const Options &options ); 36 37 void previsit( ast::Node const * ); 38 void postvisit( ast::Node const * ); 39 40 void postvisit( ast::FunctionType const * type ); 41 void postvisit( ast::VoidType const * type ); 42 void postvisit( ast::BasicType const * type ); 43 void postvisit( ast::PointerType const * type ); 44 void postvisit( ast::ArrayType const * type ); 45 void postvisit( ast::ReferenceType const * type ); 46 void postvisit( ast::StructInstType const * type ); 47 void postvisit( ast::UnionInstType const * type ); 48 void postvisit( ast::EnumInstType const * type ); 49 void postvisit( ast::TypeInstType const * type ); 50 void postvisit( ast::TupleType const * type ); 51 void postvisit( ast::VarArgsType const * type ); 52 void postvisit( ast::ZeroType const * type ); 53 void postvisit( ast::OneType const * type ); 54 void postvisit( ast::GlobalScopeType const * type ); 55 void postvisit( ast::TraitInstType const * type ); 56 void postvisit( ast::TypeofType const * type ); 57 void postvisit( ast::VTableType const * type ); 58 void postvisit( ast::QualifiedType const * type ); 59 60 private: 61 void handleQualifiers( ast::Type const *type ); 62 std::string handleGeneric( ast::BaseInstType const * type ); 63 void genArray( const ast::CV::Qualifiers &qualifiers, ast::Type const *base, ast::Expr const *dimension, bool isVarLen, bool isStatic ); 64 std::string genParamList( const ast::vector<ast::Type> & ); 65 66 Options options; 67 }; 68 69 GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {} 70 71 void GenType_new::previsit( ast::Node const * ) { 72 // Turn off automatic recursion for all nodes, to allow each visitor to 73 // precisely control the order in which its children are visited. 74 visit_children = false; 75 } 76 77 void GenType_new::postvisit( ast::Node const * node ) { 78 std::stringstream ss; 79 ast::print( ss, node ); 80 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() ); 81 } 82 83 void GenType_new::postvisit( ast::VoidType const * type ) { 84 result = "void " + result; 85 handleQualifiers( type ); 86 } 87 88 void GenType_new::postvisit( ast::BasicType const * type ) { 89 ast::BasicType::Kind kind = type->kind; 90 assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES ); 91 result = std::string( ast::BasicType::typeNames[kind] ) + " " + result; 92 handleQualifiers( type ); 93 } 94 95 void GenType_new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) { 96 std::ostringstream os; 97 if ( result != "" ) { 98 if ( result[ 0 ] == '*' ) { 99 os << "(" << result << ")"; 100 } else { 101 os << result; 102 } 103 } 104 os << "["; 105 if ( isStatic ) { 106 os << "static "; 107 } 108 if ( qualifiers.is_const ) { 109 os << "const "; 110 } 111 if ( qualifiers.is_volatile ) { 112 os << "volatile "; 113 } 114 if ( qualifiers.is_restrict ) { 115 os << "__restrict "; 116 } 117 if ( qualifiers.is_atomic ) { 118 os << "_Atomic "; 119 } 120 if ( dimension != 0 ) { 121 ast::Pass<CodeGenerator_new>::read( dimension, os, options ); 122 } else if ( isVarLen ) { 123 // no dimension expression on a VLA means it came in with the * token 124 os << "*"; 125 } 126 os << "]"; 127 128 result = os.str(); 129 130 base->accept( *visitor ); 131 } 132 133 void GenType_new::postvisit( ast::PointerType const * type ) { 134 if ( type->isStatic || type->isVarLen || type->dimension ) { 135 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 136 } else { 137 handleQualifiers( type ); 138 if ( result[ 0 ] == '?' ) { 139 result = "* " + result; 140 } else { 141 result = "*" + result; 142 } 143 type->base->accept( *visitor ); 144 } 145 } 146 147 void GenType_new::postvisit( ast::ArrayType const * type ) { 148 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 149 } 150 151 void GenType_new::postvisit( ast::ReferenceType const * type ) { 152 assertf( !options.genC, "Reference types should not reach code generation." ); 153 handleQualifiers( type ); 154 result = "&" + result; 155 type->base->accept( *visitor ); 156 } 157 158 void GenType_new::postvisit( ast::FunctionType const * type ) { 159 std::ostringstream os; 160 161 if ( result != "" ) { 162 if ( result[ 0 ] == '*' ) { 163 os << "(" << result << ")"; 164 } else { 165 os << result; 166 } 167 } 168 169 if ( type->params.empty() ) { 170 if ( type->isVarArgs ) { 171 os << "()"; 172 } else { 173 os << "(void)"; 174 } 175 } else { 176 os << "(" ; 177 178 os << genParamList( type->params ); 179 180 if ( type->isVarArgs ) { 181 os << ", ..."; 182 } 183 os << ")"; 184 } 185 186 result = os.str(); 187 188 if ( type->returns.size() == 0 ) { 189 result = "void " + result; 190 } else { 191 type->returns.front()->accept( *visitor ); 192 } 193 194 // Add forall clause. 195 if( !type->forall.empty() && !options.genC ) { 196 //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." ); 65 197 std::ostringstream os; 66 67 if ( ! type->get_attributes().empty() ) { 68 PassVisitor<CodeGenerator> cg( os, options ); 69 cg.pass.genAttributes( type->get_attributes() ); 70 } // if 71 72 type->accept( gt ); 73 return os.str() + gt.pass.typeString; 74 } 75 76 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) { 77 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) ); 78 } 79 80 std::string genPrettyType( Type * type, const std::string & baseString ) { 81 return genType( type, baseString, true, false ); 82 } 83 84 GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {} 85 86 // *** BaseSyntaxNode 87 void GenType::previsit( BaseSyntaxNode * ) { 88 // turn off automatic recursion for all nodes, to allow each visitor to 89 // precisely control the order in which its children are visited. 90 visit_children = false; 91 } 92 93 void GenType::postvisit( BaseSyntaxNode * node ) { 94 std::stringstream ss; 95 node->print( ss ); 96 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() ); 97 } 98 99 void GenType::postvisit( VoidType * voidType ) { 100 typeString = "void " + typeString; 101 handleQualifiers( voidType ); 102 } 103 104 void GenType::postvisit( BasicType * basicType ) { 105 BasicType::Kind kind = basicType->kind; 106 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES ); 107 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString; 108 handleQualifiers( basicType ); 109 } 110 111 void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) { 198 ast::Pass<CodeGenerator_new> cg( os, options ); 199 os << "forall("; 200 cg.core.genCommaList( type->forall ); 201 os << ")" << std::endl; 202 result = os.str() + result; 203 } 204 } 205 206 std::string GenType_new::handleGeneric( ast::BaseInstType const * type ) { 207 if ( !type->params.empty() ) { 112 208 std::ostringstream os; 113 if ( typeString != "" ) { 114 if ( typeString[ 0 ] == '*' ) { 115 os << "(" << typeString << ")"; 116 } else { 117 os << typeString; 118 } // if 119 } // if 120 os << "["; 121 122 if ( isStatic ) { 123 os << "static "; 124 } // if 125 if ( qualifiers.is_const ) { 126 os << "const "; 127 } // if 128 if ( qualifiers.is_volatile ) { 129 os << "volatile "; 130 } // if 131 if ( qualifiers.is_restrict ) { 132 os << "__restrict "; 133 } // if 134 if ( qualifiers.is_atomic ) { 135 os << "_Atomic "; 136 } // if 137 if ( dimension != 0 ) { 138 PassVisitor<CodeGenerator> cg( os, options ); 139 dimension->accept( cg ); 140 } else if ( isVarLen ) { 141 // no dimension expression on a VLA means it came in with the * token 142 os << "*"; 143 } // if 144 os << "]"; 145 146 typeString = os.str(); 147 148 base->accept( *visitor ); 149 } 150 151 void GenType::postvisit( PointerType * pointerType ) { 152 assert( pointerType->base != 0); 153 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) { 154 genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() ); 155 } else { 156 handleQualifiers( pointerType ); 157 if ( typeString[ 0 ] == '?' ) { 158 typeString = "* " + typeString; 159 } else { 160 typeString = "*" + typeString; 161 } // if 162 pointerType->base->accept( *visitor ); 163 } // if 164 } 165 166 void GenType::postvisit( ArrayType * arrayType ) { 167 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() ); 168 } 169 170 void GenType::postvisit( ReferenceType * refType ) { 171 assert( 0 != refType->base ); 172 assertf( ! options.genC, "Reference types should not reach code generation." ); 173 handleQualifiers( refType ); 174 typeString = "&" + typeString; 175 refType->base->accept( *visitor ); 176 } 177 178 void GenType::postvisit( FunctionType * funcType ) { 179 std::ostringstream os; 180 181 if ( typeString != "" ) { 182 if ( typeString[ 0 ] == '*' ) { 183 os << "(" << typeString << ")"; 184 } else { 185 os << typeString; 186 } // if 187 } // if 188 189 /************* parameters ***************/ 190 191 const std::list<DeclarationWithType *> &pars = funcType->parameters; 192 193 if ( pars.empty() ) { 194 if ( funcType->get_isVarArgs() ) { 195 os << "()"; 196 } else { 197 os << "(void)"; 198 } // if 199 } else { 200 PassVisitor<CodeGenerator> cg( os, options ); 201 os << "(" ; 202 203 cg.pass.genCommaList( pars.begin(), pars.end() ); 204 205 if ( funcType->get_isVarArgs() ) { 206 os << ", ..."; 207 } // if 208 os << ")"; 209 } // if 210 211 typeString = os.str(); 212 213 if ( funcType->returnVals.size() == 0 ) { 214 typeString = "void " + typeString; 215 } else { 216 funcType->returnVals.front()->get_type()->accept( *visitor ); 217 } // if 218 219 // add forall 220 if( ! funcType->forall.empty() && ! options.genC ) { 221 // assertf( ! genC, "Aggregate type parameters should not reach code generation." ); 222 std::ostringstream os; 223 PassVisitor<CodeGenerator> cg( os, options ); 224 os << "forall("; 225 cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() ); 226 os << ")" << std::endl; 227 typeString = os.str() + typeString; 228 } 229 } 230 231 std::string GenType::handleGeneric( ReferenceToType * refType ) { 232 if ( ! refType->parameters.empty() ) { 233 std::ostringstream os; 234 PassVisitor<CodeGenerator> cg( os, options ); 235 os << "("; 236 cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() ); 237 os << ") "; 238 return os.str(); 239 } 240 return ""; 241 } 242 243 void GenType::postvisit( StructInstType * structInst ) { 244 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString; 245 if ( options.genC ) typeString = "struct " + typeString; 246 handleQualifiers( structInst ); 247 } 248 249 void GenType::postvisit( UnionInstType * unionInst ) { 250 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString; 251 if ( options.genC ) typeString = "union " + typeString; 252 handleQualifiers( unionInst ); 253 } 254 255 void GenType::postvisit( EnumInstType * enumInst ) { 256 if ( enumInst->baseEnum && enumInst->baseEnum->base ) { 257 typeString = genType(enumInst->baseEnum->base, typeString, options); 258 } else { 259 typeString = enumInst->name + " " + typeString; 260 if ( options.genC ) { 261 typeString = "enum " + typeString; 262 } 263 } 264 handleQualifiers( enumInst ); 265 } 266 267 void GenType::postvisit( TypeInstType * typeInst ) { 268 assertf( ! options.genC, "Type instance types should not reach code generation." ); 269 typeString = typeInst->name + " " + typeString; 270 handleQualifiers( typeInst ); 271 } 272 273 void GenType::postvisit( TupleType * tupleType ) { 274 assertf( ! options.genC, "Tuple types should not reach code generation." ); 275 unsigned int i = 0; 276 std::ostringstream os; 277 os << "["; 278 for ( Type * t : *tupleType ) { 279 i++; 280 os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", "); 281 } 282 os << "] "; 283 typeString = os.str() + typeString; 284 } 285 286 void GenType::postvisit( VarArgsType * varArgsType ) { 287 typeString = "__builtin_va_list " + typeString; 288 handleQualifiers( varArgsType ); 289 } 290 291 void GenType::postvisit( ZeroType * zeroType ) { 292 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 293 typeString = (options.pretty ? "zero_t " : "long int ") + typeString; 294 handleQualifiers( zeroType ); 295 } 296 297 void GenType::postvisit( OneType * oneType ) { 298 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 299 typeString = (options.pretty ? "one_t " : "long int ") + typeString; 300 handleQualifiers( oneType ); 301 } 302 303 void GenType::postvisit( GlobalScopeType * globalType ) { 304 assertf( ! options.genC, "Global scope type should not reach code generation." ); 305 handleQualifiers( globalType ); 306 } 307 308 void GenType::postvisit( TraitInstType * inst ) { 309 assertf( ! options.genC, "Trait types should not reach code generation." ); 310 typeString = inst->name + " " + typeString; 311 handleQualifiers( inst ); 312 } 313 314 void GenType::postvisit( TypeofType * typeof ) { 315 std::ostringstream os; 316 PassVisitor<CodeGenerator> cg( os, options ); 317 os << "typeof("; 318 typeof->expr->accept( cg ); 319 os << ") " << typeString; 320 typeString = os.str(); 321 handleQualifiers( typeof ); 322 } 323 324 void GenType::postvisit( VTableType * vtable ) { 325 assertf( ! options.genC, "Virtual table types should not reach code generation." ); 326 std::ostringstream os; 327 os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString; 328 typeString = os.str(); 329 handleQualifiers( vtable ); 330 } 331 332 void GenType::postvisit( QualifiedType * qualType ) { 333 assertf( ! options.genC, "Qualified types should not reach code generation." ); 334 std::ostringstream os; 335 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString; 336 typeString = os.str(); 337 handleQualifiers( qualType ); 338 } 339 340 void GenType::handleQualifiers( Type * type ) { 341 if ( type->get_const() ) { 342 typeString = "const " + typeString; 343 } // if 344 if ( type->get_volatile() ) { 345 typeString = "volatile " + typeString; 346 } // if 347 if ( type->get_restrict() ) { 348 typeString = "__restrict " + typeString; 349 } // if 350 if ( type->get_atomic() ) { 351 typeString = "_Atomic " + typeString; 352 } // if 353 } 209 ast::Pass<CodeGenerator_new> cg( os, options ); 210 os << "("; 211 cg.core.genCommaList( type->params ); 212 os << ") "; 213 return os.str(); 214 } 215 return ""; 216 } 217 218 void GenType_new::postvisit( ast::StructInstType const * type ) { 219 result = type->name + handleGeneric( type ) + " " + result; 220 if ( options.genC ) result = "struct " + result; 221 handleQualifiers( type ); 222 } 223 224 void GenType_new::postvisit( ast::UnionInstType const * type ) { 225 result = type->name + handleGeneric( type ) + " " + result; 226 if ( options.genC ) result = "union " + result; 227 handleQualifiers( type ); 228 } 229 230 void GenType_new::postvisit( ast::EnumInstType const * type ) { 231 if ( type->base && type->base->base ) { 232 result = genType( type->base->base, result, options ); 233 } else { 234 result = type->name + " " + result; 235 if ( options.genC ) { 236 result = "enum " + result; 237 } 238 } 239 handleQualifiers( type ); 240 } 241 242 void GenType_new::postvisit( ast::TypeInstType const * type ) { 243 assertf( !options.genC, "TypeInstType should not reach code generation." ); 244 result = type->name + " " + result; 245 handleQualifiers( type ); 246 } 247 248 void GenType_new::postvisit( ast::TupleType const * type ) { 249 assertf( !options.genC, "TupleType should not reach code generation." ); 250 unsigned int i = 0; 251 std::ostringstream os; 252 os << "["; 253 for ( ast::ptr<ast::Type> const & t : type->types ) { 254 i++; 255 os << genType( t, "", options ) << (i == type->size() ? "" : ", "); 256 } 257 os << "] "; 258 result = os.str() + result; 259 } 260 261 void GenType_new::postvisit( ast::VarArgsType const * type ) { 262 result = "__builtin_va_list " + result; 263 handleQualifiers( type ); 264 } 265 266 void GenType_new::postvisit( ast::ZeroType const * type ) { 267 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 268 result = (options.pretty ? "zero_t " : "long int ") + result; 269 handleQualifiers( type ); 270 } 271 272 void GenType_new::postvisit( ast::OneType const * type ) { 273 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 274 result = (options.pretty ? "one_t " : "long int ") + result; 275 handleQualifiers( type ); 276 } 277 278 void GenType_new::postvisit( ast::GlobalScopeType const * type ) { 279 assertf( !options.genC, "GlobalScopeType should not reach code generation." ); 280 handleQualifiers( type ); 281 } 282 283 void GenType_new::postvisit( ast::TraitInstType const * type ) { 284 assertf( !options.genC, "TraitInstType should not reach code generation." ); 285 result = type->name + " " + result; 286 handleQualifiers( type ); 287 } 288 289 void GenType_new::postvisit( ast::TypeofType const * type ) { 290 std::ostringstream os; 291 os << "typeof("; 292 ast::Pass<CodeGenerator_new>::read( type, os, options ); 293 os << ") " << result; 294 result = os.str(); 295 handleQualifiers( type ); 296 } 297 298 void GenType_new::postvisit( ast::VTableType const * type ) { 299 assertf( !options.genC, "Virtual table types should not reach code generation." ); 300 std::ostringstream os; 301 os << "vtable(" << genType( type->base, "", options ) << ") " << result; 302 result = os.str(); 303 handleQualifiers( type ); 304 } 305 306 void GenType_new::postvisit( ast::QualifiedType const * type ) { 307 assertf( !options.genC, "QualifiedType should not reach code generation." ); 308 std::ostringstream os; 309 os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result; 310 result = os.str(); 311 handleQualifiers( type ); 312 } 313 314 void GenType_new::handleQualifiers( ast::Type const * type ) { 315 if ( type->is_const() ) { 316 result = "const " + result; 317 } 318 if ( type->is_volatile() ) { 319 result = "volatile " + result; 320 } 321 if ( type->is_restrict() ) { 322 result = "__restrict " + result; 323 } 324 if ( type->is_atomic() ) { 325 result = "_Atomic " + result; 326 } 327 } 328 329 std::string GenType_new::genParamList( const ast::vector<ast::Type> & range ) { 330 auto cur = range.begin(); 331 auto end = range.end(); 332 if ( cur == end ) return ""; 333 std::ostringstream oss; 334 UniqueName param( "__param_" ); 335 while ( true ) { 336 oss << genType( *cur++, options.genC ? param.newName() : "", options ); 337 if ( cur == end ) break; 338 oss << ", "; 339 } 340 return oss.str(); 341 } 342 343 } // namespace 344 345 std::string genType( ast::Type const * type, const std::string & base, const Options & options ) { 346 std::ostringstream os; 347 if ( !type->attributes.empty() ) { 348 ast::Pass<CodeGenerator_new> cg( os, options ); 349 cg.core.genAttributes( type->attributes ); 350 } 351 352 return os.str() + ast::Pass<GenType_new>::read( type, base, options ); 353 } 354 355 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) { 356 return ast::Pass<GenType_new>::read( type, base, options ); 357 } 358 354 359 } // namespace CodeGen 355 360
Note:
See TracChangeset
for help on using the changeset viewer.