Changeset b067d9b for src/SymTab
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (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. - Location:
- src/SymTab
- Files:
-
- 3 added
- 11 edited
-
Autogen.cc (modified) (8 diffs)
-
Autogen.h (modified) (8 diffs)
-
Demangle.cc (added)
-
FixFunction.cc (modified) (4 diffs)
-
FixFunction.h (modified) (1 diff)
-
Indexer.cc (modified) (10 diffs)
-
Indexer.h (modified) (3 diffs)
-
Mangler.cc (modified) (16 diffs)
-
Mangler.h (modified) (1 diff)
-
ManglerCommon.cc (added)
-
Validate.cc (modified) (48 diffs)
-
Validate.h (modified) (2 diffs)
-
demangler.cc (added)
-
module.mk (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
r7951100 rb067d9b 24 24 #include <vector> // for vector 25 25 26 #include "AST/Decl.hpp" 26 27 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 27 28 #include "Common/PassVisitor.h" // for PassVisitor … … 41 42 42 43 namespace SymTab { 43 Type * SizeType = 0;44 45 44 /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype 46 45 struct FuncData { 47 typedef FunctionType * (*TypeGen)( Type * );46 typedef FunctionType * (*TypeGen)( Type *, bool ); 48 47 FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {} 49 48 std::string fname; … … 211 210 } 212 211 212 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) { 213 return obj && obj->name.empty() && obj->bitfieldWidth; 214 } 215 213 216 /// inserts a forward declaration for functionDecl into declsToAdd 214 217 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 231 234 232 235 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 233 FunctionType * genDefaultType( Type * paramType ) { 234 const auto & typeParams = getGenericParams( paramType ); 236 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { 235 237 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 236 cloneAll( typeParams, ftype->forall ); 238 if ( maybePolymorphic ) { 239 // only copy in 240 const auto & typeParams = getGenericParams( paramType ); 241 cloneAll( typeParams, ftype->forall ); 242 } 237 243 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr ); 238 244 ftype->parameters.push_back( dstParam ); … … 241 247 242 248 /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T) 243 FunctionType * genCopyType( Type * paramType ) {244 FunctionType *ftype = genDefaultType( paramType );249 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) { 250 FunctionType *ftype = genDefaultType( paramType, maybePolymorphic ); 245 251 ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 246 252 ftype->parameters.push_back( srcParam ); … … 249 255 250 256 /// given type T, generate type of assignment, i.e. function type T (*) (T *, T) 251 FunctionType * genAssignType( Type * paramType ) {252 FunctionType *ftype = genCopyType( paramType );257 FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) { 258 FunctionType *ftype = genCopyType( paramType, maybePolymorphic ); 253 259 ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 254 260 ftype->returnVals.push_back( returnVal ); … … 308 314 for ( const FuncData & d : data ) { 309 315 // generate a function (?{}, ?=?, ^?{}) based on the current FuncData. 310 FunctionType * ftype = d.genType( type );316 FunctionType * ftype = d.genType( type, true ); 311 317 312 318 // destructor for concurrent type must be mutex … … 387 393 388 394 void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) { 389 InitTweak::InitExpander srcParam( src );395 InitTweak::InitExpander_old srcParam( src ); 390 396 391 397 // assign to destination -
src/SymTab/Autogen.h
r7951100 rb067d9b 17 17 18 18 #include <cassert> // for assert 19 #include <iterator> // for back_inserter 19 20 #include <string> // for string 20 21 22 #include "AST/Decl.hpp" 23 #include "AST/Expr.hpp" 24 #include "AST/Init.hpp" 25 #include "AST/Node.hpp" 26 #include "AST/Stmt.hpp" 27 #include "AST/Type.hpp" 21 28 #include "CodeGen/OperatorTable.h" 22 29 #include "Common/UniqueName.h" // for UniqueName 30 #include "Common/utility.h" // for splice 23 31 #include "InitTweak/InitTweak.h" // for InitExpander 24 32 #include "SynTree/Constant.h" // for Constant … … 36 44 /// returns true if obj's name is the empty string and it has a bitfield width 37 45 bool isUnnamedBitfield( ObjectDecl * obj ); 38 39 /// size_t type - set when size_t typedef is seen. Useful in a few places, 40 /// such as in determining array dimension type 41 extern Type * SizeType; 42 43 /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations. 44 /// Useful for creating dereference ApplicationExprs without a full resolver pass. 45 extern FunctionDecl * dereferenceOperator; 46 47 // generate the type of an assignment function for paramType 48 FunctionType * genAssignType( Type * paramType ); 49 50 // generate the type of a default constructor or destructor for paramType 51 FunctionType * genDefaultType( Type * paramType ); 52 53 // generate the type of a copy constructor for paramType 54 FunctionType * genCopyType( Type * paramType ); 46 bool isUnnamedBitfield( const ast::ObjectDecl * obj ); 47 48 /// generate the type of an assignment function for paramType. 49 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 50 FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true ); 51 52 /// generate the type of a default constructor or destructor for paramType. 53 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 54 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 55 56 /// generate the type of a copy constructor for paramType. 57 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 58 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true ); 59 60 /// Enum for loop direction 61 enum LoopDirection { LoopBackward, LoopForward }; 55 62 56 63 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 57 64 template< typename OutputIterator > 58 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 65 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 66 67 template< typename OutIter > 68 ast::ptr< ast::Stmt > genCall( 69 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 70 const CodeLocation & loc, const std::string & fname, OutIter && out, 71 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward ); 59 72 60 73 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. 61 74 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one 62 75 template< typename OutputIterator > 63 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {76 Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) { 64 77 bool isReferenceCtorDtor = false; 65 78 if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { … … 84 97 // type->get_qualifiers() = Type::Qualifiers(); 85 98 Type * castType = addCast->clone(); 86 castType->get_qualifiers() -= Type::Qualifiers( Type:: Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );99 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 87 100 // castType->set_lvalue( true ); // xxx - might not need this 88 101 dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) ); … … 111 124 } 112 125 126 /// inserts into out a generated call expression to function fname with arguments dstParam and 127 /// srcParam. Should only be called with non-array types. 128 /// optionally returns a statement which must be inserted prior to the containing loop, if 129 /// there is one 130 template< typename OutIter > 131 ast::ptr< ast::Stmt > genScalarCall( 132 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 133 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type, 134 const ast::Type * addCast = nullptr 135 ) { 136 bool isReferenceCtorDtor = false; 137 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { 138 // reference constructors are essentially application of the rebind operator. 139 // apply & to both arguments, do not need a cast 140 fname = "?=?"; 141 dstParam = new ast::AddressExpr{ dstParam }; 142 addCast = nullptr; 143 isReferenceCtorDtor = true; 144 } 145 146 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of 147 // "?=?", "?{}", or "^?{}" 148 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } }; 149 150 if ( addCast ) { 151 // cast to T& with qualifiers removed, so that qualified objects can be constructed and 152 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue 153 // is considered a qualifier - for AddressExpr to resolve, its argument must have an 154 // lvalue-qualified type, so remove all qualifiers except lvalue. 155 // xxx -- old code actually removed lvalue too... 156 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast 157 ast::ptr< ast::Type > castType = addCast; 158 ast::remove_qualifiers( 159 castType, 160 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic ); 161 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } }; 162 } 163 fExpr->args.emplace_back( dstParam ); 164 165 const ast::Stmt * listInit = srcParam.buildListInit( fExpr ); 166 167 // fetch next set of arguments 168 ++srcParam; 169 170 // return if adding reference fails -- will happen on default ctor and dtor 171 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit; 172 173 std::vector< ast::ptr< ast::Expr > > args = *srcParam; 174 splice( fExpr->args, args ); 175 176 *out++ = new ast::ExprStmt{ loc, fExpr }; 177 178 srcParam.clearArrayIndices(); 179 180 return listInit; 181 } 182 113 183 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments. 114 184 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 115 185 template< typename OutputIterator > 116 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {186 void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) { 117 187 static UniqueName indexName( "_index" ); 118 188 … … 175 245 } 176 246 247 /// Store in out a loop which calls fname on each element of the array with srcParam and 248 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0 249 template< typename OutIter > 250 void genArrayCall( 251 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 252 const CodeLocation & loc, const std::string & fname, OutIter && out, 253 const ast::ArrayType * array, const ast::Type * addCast = nullptr, 254 LoopDirection forward = LoopForward 255 ) { 256 static UniqueName indexName( "_index" ); 257 258 // for a flexible array member nothing is done -- user must define own assignment 259 if ( ! array->dimension ) return; 260 261 if ( addCast ) { 262 // peel off array layer from cast 263 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base; 264 } 265 266 ast::ptr< ast::Expr > begin, end, cmp, update; 267 268 if ( forward ) { 269 // generate: for ( int i = 0; i < N; ++i ) 270 begin = ast::ConstantExpr::from_int( loc, 0 ); 271 end = array->dimension; 272 cmp = new ast::NameExpr{ loc, "?<?" }; 273 update = new ast::NameExpr{ loc, "++?" }; 274 } else { 275 // generate: for ( int i = N-1; i >= 0; --i ) 276 begin = new ast::UntypedExpr{ 277 loc, new ast::NameExpr{ loc, "?-?" }, 278 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } }; 279 end = ast::ConstantExpr::from_int( loc, 0 ); 280 cmp = new ast::NameExpr{ loc, "?>=?" }; 281 update = new ast::NameExpr{ loc, "--?" }; 282 } 283 284 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{ 285 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt }, 286 new ast::SingleInit{ loc, begin } }; 287 288 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{ 289 loc, cmp, { new ast::VariableExpr{ loc, index }, end } }; 290 291 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{ 292 loc, update, { new ast::VariableExpr{ loc, index } } }; 293 294 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{ 295 loc, new ast::NameExpr{ loc, "?[?]" }, 296 { dstParam, new ast::VariableExpr{ loc, index } } }; 297 298 // srcParam must keep track of the array indices to build the source parameter and/or 299 // array list initializer 300 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension ); 301 302 // for stmt's body, eventually containing call 303 ast::CompoundStmt * body = new ast::CompoundStmt{ loc }; 304 ast::ptr< ast::Stmt > listInit = genCall( 305 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast, 306 forward ); 307 308 // block containing the stmt and index variable 309 ast::CompoundStmt * block = new ast::CompoundStmt{ loc }; 310 block->push_back( new ast::DeclStmt{ loc, index } ); 311 if ( listInit ) { block->push_back( listInit ); } 312 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } ); 313 314 *out++ = block; 315 } 316 177 317 template< typename OutputIterator > 178 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {318 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { 179 319 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 180 320 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); … … 185 325 } 186 326 327 template< typename OutIter > 328 ast::ptr< ast::Stmt > genCall( 329 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 330 const CodeLocation & loc, const std::string & fname, OutIter && out, 331 const ast::Type * type, const ast::Type * addCast, LoopDirection forward 332 ) { 333 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 334 genArrayCall( 335 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast, 336 forward ); 337 return {}; 338 } else { 339 return genScalarCall( 340 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast ); 341 } 342 } 343 187 344 /// inserts into out a generated call expression to function fname with arguments dstParam 188 345 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the … … 190 347 /// ImplicitCtorDtorStmt node. 191 348 template< typename OutputIterator > 192 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {349 void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 193 350 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 194 351 assert( obj ); … … 218 375 } 219 376 } 377 378 static inline ast::ptr< ast::Stmt > genImplicitCall( 379 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 380 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj, 381 LoopDirection forward = LoopForward 382 ) { 383 // unnamed bit fields are not copied as they cannot be accessed 384 if ( isUnnamedBitfield( obj ) ) return {}; 385 386 ast::ptr< ast::Type > addCast = nullptr; 387 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) { 388 assert( dstParam->result ); 389 addCast = dstParam->result; 390 } 391 392 std::vector< ast::ptr< ast::Stmt > > stmts; 393 genCall( 394 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward ); 395 396 if ( stmts.empty() ) { 397 return {}; 398 } else if ( stmts.size() == 1 ) { 399 const ast::Stmt * callStmt = stmts.front(); 400 if ( addCast ) { 401 // implicitly generated ctor/dtor calls should be wrapped so that later passes are 402 // aware they were generated. 403 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt }; 404 } 405 return callStmt; 406 } else { 407 assert( false ); 408 return {}; 409 } 410 } 220 411 } // namespace SymTab 221 412 -
src/SymTab/FixFunction.cc
r7951100 rb067d9b 18 18 #include <list> // for list 19 19 20 #include "Common/utility.h" // for maybeClone 20 #include "AST/Decl.hpp" 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 23 #include "Common/utility.h" // for maybeClone, copy 21 24 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarati... 22 25 #include "SynTree/Expression.h" // for Expression … … 24 27 25 28 namespace SymTab { 26 FixFunction::FixFunction() : isVoid( false ) {} 29 class FixFunction_old : public WithShortCircuiting { 30 typedef Mutator Parent; 31 public: 32 FixFunction_old() : isVoid( false ) {} 27 33 34 void premutate(FunctionDecl *functionDecl); 35 DeclarationWithType* postmutate(FunctionDecl *functionDecl); 28 36 29 DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) { 37 Type * postmutate(ArrayType * arrayType); 38 39 void premutate(ArrayType * arrayType); 40 void premutate(VoidType * voidType); 41 void premutate(BasicType * basicType); 42 void premutate(PointerType * pointerType); 43 void premutate(StructInstType * aggregateUseType); 44 void premutate(UnionInstType * aggregateUseType); 45 void premutate(EnumInstType * aggregateUseType); 46 void premutate(TraitInstType * aggregateUseType); 47 void premutate(TypeInstType * aggregateUseType); 48 void premutate(TupleType * tupleType); 49 void premutate(VarArgsType * varArgsType); 50 void premutate(ZeroType * zeroType); 51 void premutate(OneType * oneType); 52 53 bool isVoid; 54 }; 55 56 DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) { 30 57 // can't delete function type because it may contain assertions, so transfer ownership to new object 31 58 ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes ); 59 pointer->location = functionDecl->location; 32 60 functionDecl->attributes.clear(); 33 61 functionDecl->type = nullptr; … … 40 68 // does not cause an error 41 69 42 Type * FixFunction ::postmutate(ArrayType *arrayType) {70 Type * FixFunction_old::postmutate(ArrayType *arrayType) { 43 71 // need to recursively mutate the base type in order for multi-dimensional arrays to work. 44 72 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic ); 73 pointerType->location = arrayType->location; 45 74 arrayType->base = nullptr; 46 75 arrayType->dimension = nullptr; … … 49 78 } 50 79 51 void FixFunction ::premutate(VoidType *) {80 void FixFunction_old::premutate(VoidType *) { 52 81 isVoid = true; 53 82 } 54 83 55 void FixFunction ::premutate(FunctionDecl *) { visit_children = false; }56 void FixFunction ::premutate(ArrayType *) { visit_children = false; }57 void FixFunction ::premutate(BasicType *) { visit_children = false; }58 void FixFunction ::premutate(PointerType *) { visit_children = false; }59 void FixFunction ::premutate(StructInstType *) { visit_children = false; }60 void FixFunction ::premutate(UnionInstType *) { visit_children = false; }61 void FixFunction ::premutate(EnumInstType *) { visit_children = false; }62 void FixFunction ::premutate(TraitInstType *) { visit_children = false; }63 void FixFunction ::premutate(TypeInstType *) { visit_children = false; }64 void FixFunction ::premutate(TupleType *) { visit_children = false; }65 void FixFunction ::premutate(VarArgsType *) { visit_children = false; }66 void FixFunction ::premutate(ZeroType *) { visit_children = false; }67 void FixFunction ::premutate(OneType *) { visit_children = false; }84 void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; } 85 void FixFunction_old::premutate(ArrayType *) { visit_children = false; } 86 void FixFunction_old::premutate(BasicType *) { visit_children = false; } 87 void FixFunction_old::premutate(PointerType *) { visit_children = false; } 88 void FixFunction_old::premutate(StructInstType *) { visit_children = false; } 89 void FixFunction_old::premutate(UnionInstType *) { visit_children = false; } 90 void FixFunction_old::premutate(EnumInstType *) { visit_children = false; } 91 void FixFunction_old::premutate(TraitInstType *) { visit_children = false; } 92 void FixFunction_old::premutate(TypeInstType *) { visit_children = false; } 93 void FixFunction_old::premutate(TupleType *) { visit_children = false; } 94 void FixFunction_old::premutate(VarArgsType *) { visit_children = false; } 95 void FixFunction_old::premutate(ZeroType *) { visit_children = false; } 96 void FixFunction_old::premutate(OneType *) { visit_children = false; } 68 97 69 98 bool fixFunction( DeclarationWithType *& dwt ) { 70 PassVisitor<FixFunction > fixer;99 PassVisitor<FixFunction_old> fixer; 71 100 dwt = dwt->acceptMutator( fixer ); 72 101 return fixer.pass.isVoid; 73 102 } 103 104 namespace { 105 struct FixFunction_new final : public ast::WithShortCircuiting { 106 bool isVoid = false; 107 108 void premutate( const ast::FunctionDecl * ) { visit_children = false; } 109 110 const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) { 111 return new ast::ObjectDecl{ 112 func->location, func->name, new ast::PointerType{ func->type }, nullptr, 113 func->storage, func->linkage, nullptr, copy( func->attributes ) }; 114 } 115 116 void premutate( const ast::ArrayType * ) { visit_children = false; } 117 118 const ast::Type * postmutate( const ast::ArrayType * array ) { 119 return new ast::PointerType{ 120 array->base, array->dimension, array->isVarLen, array->isStatic, 121 array->qualifiers }; 122 } 123 124 void premutate( const ast::VoidType * ) { isVoid = true; } 125 126 void premutate( const ast::BasicType * ) { visit_children = false; } 127 void premutate( const ast::PointerType * ) { visit_children = false; } 128 void premutate( const ast::StructInstType * ) { visit_children = false; } 129 void premutate( const ast::UnionInstType * ) { visit_children = false; } 130 void premutate( const ast::EnumInstType * ) { visit_children = false; } 131 void premutate( const ast::TraitInstType * ) { visit_children = false; } 132 void premutate( const ast::TypeInstType * ) { visit_children = false; } 133 void premutate( const ast::TupleType * ) { visit_children = false; } 134 void premutate( const ast::VarArgsType * ) { visit_children = false; } 135 void premutate( const ast::ZeroType * ) { visit_children = false; } 136 void premutate( const ast::OneType * ) { visit_children = false; } 137 }; 138 } // anonymous namespace 139 140 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) { 141 ast::Pass< FixFunction_new > fixer; 142 dwt = dwt->accept( fixer ); 143 isVoid |= fixer.pass.isVoid; 144 return dwt; 145 } 146 74 147 } // namespace SymTab 75 148 -
src/SymTab/FixFunction.h
r7951100 rb067d9b 19 19 #include "SynTree/SynTree.h" // for Types 20 20 21 namespace ast { 22 class DeclWithType; 23 } 24 21 25 namespace SymTab { 22 /// Replaces function and array types by equivalent pointer types. 23 class FixFunction : public WithShortCircuiting { 24 typedef Mutator Parent; 25 public: 26 FixFunction(); 26 /// Replaces function and array types by equivalent pointer types. Returns true if type is 27 /// void 28 bool fixFunction( DeclarationWithType *& ); 27 29 28 void premutate(FunctionDecl *functionDecl); 29 DeclarationWithType* postmutate(FunctionDecl *functionDecl); 30 31 Type * postmutate(ArrayType * arrayType); 32 33 void premutate(ArrayType * arrayType); 34 void premutate(VoidType * voidType); 35 void premutate(BasicType * basicType); 36 void premutate(PointerType * pointerType); 37 void premutate(StructInstType * aggregateUseType); 38 void premutate(UnionInstType * aggregateUseType); 39 void premutate(EnumInstType * aggregateUseType); 40 void premutate(TraitInstType * aggregateUseType); 41 void premutate(TypeInstType * aggregateUseType); 42 void premutate(TupleType * tupleType); 43 void premutate(VarArgsType * varArgsType); 44 void premutate(ZeroType * zeroType); 45 void premutate(OneType * oneType); 46 47 bool isVoid; 48 }; 49 50 bool fixFunction( DeclarationWithType *& ); 30 /// Returns declaration with function and array types replaced by equivalent pointer types. 31 /// Sets isVoid to true if type is void 32 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ); 51 33 } // namespace SymTab 52 34 -
src/SymTab/Indexer.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:37:33 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Aug 17 16:08:40 201713 // Update Count : 2 011 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Mar 8 13:55:00 2019 13 // Update Count : 21 14 14 // 15 15 … … 17 17 18 18 #include <cassert> // for assert, strict_dynamic_cast 19 #include <iostream> // for operator<<, basic_ostream, ostream20 19 #include <string> // for string, operator<<, operator!= 20 #include <memory> // for shared_ptr, make_shared 21 21 #include <unordered_map> // for operator!=, unordered_map<>::const... 22 22 #include <unordered_set> // for unordered_set 23 23 #include <utility> // for pair, make_pair, move 24 #include <vector> // for vector 24 25 25 26 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 26 27 #include "Common/SemanticError.h" // for SemanticError 27 28 #include "Common/utility.h" // for cloneAll 28 #include "GenPoly/GenPoly.h" 29 #include "Common/Stats/Counter.h" // for counters 30 #include "GenPoly/GenPoly.h" // for getFunctionType 29 31 #include "InitTweak/InitTweak.h" // for isConstructor, isCopyFunction, isC... 30 32 #include "Mangler.h" // for Mangler … … 38 40 #include "SynTree/Type.h" // for Type, StructInstType, UnionInstType 39 41 40 #define debugPrint(x) if ( doDebug ) { std::cerr << x; }41 42 42 namespace SymTab { 43 std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) { 44 return out << "(" << data.id << "," << data.baseExpr << ")"; 45 } 46 47 typedef std::unordered_map< std::string, Indexer::IdData > MangleTable; 48 typedef std::unordered_map< std::string, MangleTable > IdTable; 49 typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable; 50 typedef std::unordered_map< std::string, StructDecl* > StructTable; 51 typedef std::unordered_map< std::string, EnumDecl* > EnumTable; 52 typedef std::unordered_map< std::string, UnionDecl* > UnionTable; 53 typedef std::unordered_map< std::string, TraitDecl* > TraitTable; 54 55 void dump( const IdTable &table, std::ostream &os ) { 56 for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) { 57 for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) { 58 os << mangle->second << std::endl; 59 } 60 } 61 } 62 63 template< typename Decl > 64 void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) { 65 for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) { 66 os << it->second << std::endl; 67 } // for 68 } 69 70 struct Indexer::Impl { 71 Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(), 72 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 73 Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ), 74 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 75 unsigned long refCount; ///< Number of references to these tables 76 unsigned long scope; ///< Scope these tables are associated with 77 unsigned long size; ///< Number of elements stored in this table 78 const Indexer base; ///< Base indexer this extends 79 80 IdTable idTable; ///< Identifier namespace 81 TypeTable typeTable; ///< Type namespace 82 StructTable structTable; ///< Struct namespace 83 EnumTable enumTable; ///< Enum namespace 84 UnionTable unionTable; ///< Union namespace 85 TraitTable traitTable; ///< Trait namespace 86 }; 87 88 Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) { 89 if ( ! toClone ) return 0; 90 91 // shorten the search chain by skipping empty links 92 Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone; 93 if ( ret ) { ++ret->refCount; } 94 95 return ret; 96 } 97 98 void Indexer::deleteRef( Indexer::Impl *toFree ) { 99 if ( ! toFree ) return; 100 101 if ( --toFree->refCount == 0 ) delete toFree; 102 } 103 104 void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const { 105 // only need to perform this step for constructors, destructors, and assignment functions 106 if ( ! CodeGen::isCtorDtorAssign( id ) ) return; 107 108 // helpful data structure to organize properties for a type 109 struct ValueType { 110 struct DeclBall { // properties for this particular decl 111 IdData decl; 112 bool isUserDefinedFunc; 113 bool isCopyFunc; 43 44 // Statistics block 45 namespace { 46 static inline auto stats() { 47 using namespace Stats::Counters; 48 static auto group = build<CounterGroup>("Indexers"); 49 static struct { 50 SimpleCounter * count; 51 AverageCounter<double> * size; 52 SimpleCounter * new_scopes; 53 SimpleCounter * lazy_scopes; 54 AverageCounter<double> * avg_scope_depth; 55 MaxCounter<size_t> * max_scope_depth; 56 SimpleCounter * add_calls; 57 SimpleCounter * lookup_calls; 58 SimpleCounter * map_lookups; 59 SimpleCounter * map_mutations; 60 } ret = { 61 .count = build<SimpleCounter>("Count", group), 62 .size = build<AverageCounter<double>>("Average Size", group), 63 .new_scopes = build<SimpleCounter>("Scopes", group), 64 .lazy_scopes = build<SimpleCounter>("Lazy Scopes", group), 65 .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group), 66 .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group), 67 .add_calls = build<SimpleCounter>("Add Calls", group), 68 .lookup_calls = build<SimpleCounter>("Lookup Calls", group), 69 .map_lookups = build<SimpleCounter>("Map Lookups", group), 70 .map_mutations = build<SimpleCounter>("Map Mutations", group) 114 71 }; 115 // properties for this type 116 bool existsUserDefinedCopyFunc = false; // user-defined copy ctor found 117 BaseSyntaxNode * deleteStmt = nullptr; // non-null if a user-defined function is found 118 std::list< DeclBall > decls; 119 120 // another FunctionDecl for the current type was found - determine 121 // if it has special properties and update data structure accordingly 122 ValueType & operator+=( IdData data ) { 123 DeclarationWithType * function = data.id; 124 bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage ); 125 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name ); 126 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } ); 127 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); 128 if ( isUserDefinedFunc && ! data.deleteStmt ) { 129 // any user-defined function can act as an implicit delete statement for generated constructors. 130 // a delete stmt should not act as an implicit delete statement. 131 deleteStmt = data.id; 132 } 133 return *this; 134 } 135 }; // ValueType 136 137 std::list< IdData > copy; 138 copy.splice( copy.end(), out ); 139 140 // organize discovered declarations by type 141 std::unordered_map< std::string, ValueType > funcMap; 142 for ( auto decl : copy ) { 143 if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) { 144 std::list< DeclarationWithType * > & params = function->type->parameters; 145 assert( ! params.empty() ); 146 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 147 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 148 assert( base ); 149 funcMap[ Mangler::mangle( base ) ] += decl; 150 } else { 151 out.push_back( decl ); 152 } 153 } 154 155 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine 156 // the set of ctor/dtor/assign that can be used by the requester. In particular, if the user defines 157 // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor 158 // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available. 159 // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default 160 // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor, 161 // then the generated copy constructor is unavailable, and likewise for the assignment operator. 162 for ( std::pair< const std::string, ValueType > & pair : funcMap ) { 163 ValueType & val = pair.second; 164 for ( ValueType::DeclBall ball : val.decls ) { 165 bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic; 166 bool isCopyFunc = ball.isCopyFunc; 167 bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc; 168 // only implicitly delete non-user defined functions that are not intrinsic, and are 169 // not copy functions (assignment or copy constructor), unless a user-defined copy function exists. 170 // deleteStmt will be non-null only if a user-defined function is found. 171 if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) { 172 ball.decl.deleteStmt = val.deleteStmt; 173 } 174 out.push_back( ball.decl ); 175 } 176 } 177 } 178 179 void Indexer::makeWritable() { 180 if ( ! tables ) { 181 // create indexer if not yet set 182 tables = new Indexer::Impl( scope ); 183 } else if ( tables->refCount > 1 || tables->scope != scope ) { 184 // make this indexer the base of a fresh indexer at the current scope 185 tables = new Indexer::Impl( scope, std::move( *this ) ); 186 } 187 } 188 189 Indexer::Indexer() : tables( 0 ), scope( 0 ) {} 190 191 Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {} 192 193 Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) { 194 that.tables = 0; 195 } 72 return ret; 73 } 74 } 75 76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; } 196 79 197 80 Indexer::~Indexer() { 198 deleteRef( tables ); 199 } 200 201 Indexer& Indexer::operator= ( const Indexer &that ) { 202 deleteRef( tables ); 203 204 tables = newRef( that.tables ); 205 scope = that.scope; 206 doDebug = that.doDebug; 207 208 return *this; 209 } 210 211 Indexer& Indexer::operator= ( Indexer &&that ) { 212 deleteRef( tables ); 213 214 tables = that.tables; 215 scope = that.scope; 216 doDebug = that.doDebug; 217 218 that.tables = 0; 219 220 return *this; 221 } 222 223 void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const { 224 std::unordered_set< std::string > foundMangleNames; 225 226 Indexer::Impl *searchTables = tables; 227 while ( searchTables ) { 228 229 IdTable::const_iterator decls = searchTables->idTable.find( id ); 230 if ( decls != searchTables->idTable.end() ) { 231 const MangleTable &mangleTable = decls->second; 232 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 233 // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found 234 if ( foundMangleNames.insert( decl->first ).second == false ) continue; 235 236 out.push_back( decl->second ); 237 } 238 } 239 240 // get declarations from base indexers 241 searchTables = searchTables->base.tables; 242 } 243 244 // some special functions, e.g. constructors and destructors 245 // remove autogenerated functions when they are defined so that 246 // they can never be matched 247 removeSpecialOverrides( id, out ); 248 } 249 250 NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { 251 if ( ! tables ) return 0; 252 253 TypeTable::const_iterator ret = tables->typeTable.find( id ); 254 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id ); 255 } 256 257 StructDecl *Indexer::lookupStruct( const std::string &id ) const { 258 if ( ! tables ) return 0; 259 260 StructTable::const_iterator ret = tables->structTable.find( id ); 261 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id ); 262 } 263 264 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 265 if ( ! tables ) return 0; 266 267 EnumTable::const_iterator ret = tables->enumTable.find( id ); 268 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id ); 269 } 270 271 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 272 if ( ! tables ) return 0; 273 274 UnionTable::const_iterator ret = tables->unionTable.find( id ); 275 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id ); 276 } 277 278 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 279 if ( ! tables ) return 0; 280 281 TraitTable::const_iterator ret = tables->traitTable.find( id ); 282 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id ); 283 } 284 285 const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 286 if ( ! tables ) return nullptr; 287 if ( tables->scope < scope ) return nullptr; 288 289 IdTable::const_iterator decls = tables->idTable.find( id ); 290 if ( decls != tables->idTable.end() ) { 291 const MangleTable &mangleTable = decls->second; 292 MangleTable::const_iterator decl = mangleTable.find( mangleName ); 293 if ( decl != mangleTable.end() ) return &decl->second; 294 } 295 296 return tables->base.lookupIdAtScope( id, mangleName, scope ); 297 } 298 299 Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) { 300 return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope )); 301 } 302 303 bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 304 if ( ! tables ) return false; 305 if ( tables->scope < scope ) return false; 306 307 IdTable::const_iterator decls = tables->idTable.find( id ); 308 if ( decls != tables->idTable.end() ) { 309 const MangleTable &mangleTable = decls->second; 310 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 311 // check for C decls with the same name, skipping those with a compatible type (by mangleName) 312 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true; 313 } 314 } 315 316 return tables->base.hasIncompatibleCDecl( id, mangleName, scope ); 317 } 318 319 bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 320 if ( ! tables ) return false; 321 if ( tables->scope < scope ) return false; 322 323 IdTable::const_iterator decls = tables->idTable.find( id ); 324 if ( decls != tables->idTable.end() ) { 325 const MangleTable &mangleTable = decls->second; 326 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 327 // check for C decls with the same name, skipping 328 // those with an incompatible type (by mangleName) 329 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true; 330 } 331 } 332 333 return tables->base.hasCompatibleCDecl( id, mangleName, scope ); 334 } 335 336 NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const { 337 if ( ! tables ) return 0; 338 if ( tables->scope < scope ) return 0; 339 340 TypeTable::const_iterator ret = tables->typeTable.find( id ); 341 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope ); 342 } 343 344 StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const { 345 if ( ! tables ) return 0; 346 if ( tables->scope < scope ) return 0; 347 348 StructTable::const_iterator ret = tables->structTable.find( id ); 349 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope ); 350 } 351 352 EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const { 353 if ( ! tables ) return 0; 354 if ( tables->scope < scope ) return 0; 355 356 EnumTable::const_iterator ret = tables->enumTable.find( id ); 357 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope ); 358 } 359 360 UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const { 361 if ( ! tables ) return 0; 362 if ( tables->scope < scope ) return 0; 363 364 UnionTable::const_iterator ret = tables->unionTable.find( id ); 365 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope ); 366 } 367 368 TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const { 369 if ( ! tables ) return 0; 370 if ( tables->scope < scope ) return 0; 371 372 TraitTable::const_iterator ret = tables->traitTable.find( id ); 373 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope ); 374 } 375 376 bool isFunction( DeclarationWithType * decl ) { 81 stats().size->push( idTable ? idTable->size() : 0 ); 82 } 83 84 void Indexer::lazyInitScope() { 85 if ( repScope < scope ) { 86 ++* stats().lazy_scopes; 87 // create rollback 88 prevScope = std::make_shared<Indexer>( * this ); 89 // update repScope 90 repScope = scope; 91 } 92 } 93 94 void Indexer::enterScope() { 95 ++scope; 96 97 ++* stats().new_scopes; 98 stats().avg_scope_depth->push( scope ); 99 stats().max_scope_depth->push( scope ); 100 } 101 102 void Indexer::leaveScope() { 103 if ( repScope == scope ) { 104 Ptr prev = prevScope; // make sure prevScope stays live 105 * this = std::move(* prevScope); // replace with previous scope 106 } 107 108 --scope; 109 } 110 111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const { 112 ++* stats().lookup_calls; 113 if ( ! idTable ) return; 114 115 ++* stats().map_lookups; 116 auto decls = idTable->find( id ); 117 if ( decls == idTable->end() ) return; 118 119 for ( auto decl : *(decls->second) ) { 120 out.push_back( decl.second ); 121 } 122 } 123 124 const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const { 125 ++* stats().lookup_calls; 126 if ( ! typeTable ) return nullptr; 127 ++* stats().map_lookups; 128 auto it = typeTable->find( id ); 129 return it == typeTable->end() ? nullptr : it->second.decl; 130 } 131 132 const StructDecl * Indexer::lookupStruct( const std::string & id ) const { 133 ++* stats().lookup_calls; 134 if ( ! structTable ) return nullptr; 135 ++* stats().map_lookups; 136 auto it = structTable->find( id ); 137 return it == structTable->end() ? nullptr : it->second.decl; 138 } 139 140 const EnumDecl * Indexer::lookupEnum( const std::string & id ) const { 141 ++* stats().lookup_calls; 142 if ( ! enumTable ) return nullptr; 143 ++* stats().map_lookups; 144 auto it = enumTable->find( id ); 145 return it == enumTable->end() ? nullptr : it->second.decl; 146 } 147 148 const UnionDecl * Indexer::lookupUnion( const std::string & id ) const { 149 ++* stats().lookup_calls; 150 if ( ! unionTable ) return nullptr; 151 ++* stats().map_lookups; 152 auto it = unionTable->find( id ); 153 return it == unionTable->end() ? nullptr : it->second.decl; 154 } 155 156 const TraitDecl * Indexer::lookupTrait( const std::string & id ) const { 157 ++* stats().lookup_calls; 158 if ( ! traitTable ) return nullptr; 159 ++* stats().map_lookups; 160 auto it = traitTable->find( id ); 161 return it == traitTable->end() ? nullptr : it->second.decl; 162 } 163 164 const Indexer * Indexer::atScope( unsigned long target ) const { 165 // by lazy construction, final indexer in list has repScope 0, cannot be > target 166 // otherwise, will find first scope representing the target 167 const Indexer * indexer = this; 168 while ( indexer->repScope > target ) { 169 indexer = indexer->prevScope.get(); 170 } 171 return indexer; 172 } 173 174 const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const { 175 return atScope( 0 )->lookupType( id ); 176 } 177 178 const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const { 179 return atScope( 0 )->lookupStruct( id ); 180 } 181 182 const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const { 183 return atScope( 0 )->lookupUnion( id ); 184 } 185 186 const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const { 187 return atScope( 0 )->lookupEnum( id ); 188 } 189 190 bool isFunction( const DeclarationWithType * decl ) { 377 191 return GenPoly::getFunctionType( decl->get_type() ); 378 192 } 379 193 380 bool isObject( DeclarationWithType * decl ) {194 bool isObject( const DeclarationWithType * decl ) { 381 195 return ! isFunction( decl ); 382 196 } 383 197 384 bool isDefinition( DeclarationWithType * decl ) {385 if ( FunctionDecl * func = dynamic_cast<FunctionDecl * >( decl ) ) {198 bool isDefinition( const DeclarationWithType * decl ) { 199 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) { 386 200 // a function is a definition if it has a body 387 201 return func->statements; … … 393 207 } 394 208 395 bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) { 396 // if we're giving the same name mangling to things of different types then there is something wrong 209 210 bool Indexer::addedIdConflicts( 211 const Indexer::IdData & existing, const DeclarationWithType * added, 212 Indexer::OnConflict handleConflicts, const Declaration * deleteStmt ) { 213 // if we're giving the same name mangling to things of different types then there is 214 // something wrong 397 215 assert( (isObject( added ) && isObject( existing.id ) ) 398 216 || ( isFunction( added ) && isFunction( existing.id ) ) ); 399 217 400 if ( LinkageSpec::isOverridable( existing.id-> get_linkage()) ) {218 if ( LinkageSpec::isOverridable( existing.id->linkage ) ) { 401 219 // new definition shadows the autogenerated one, even at the same scope 402 220 return false; 403 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) { 221 } else if ( LinkageSpec::isMangled( added->linkage ) 222 || ResolvExpr::typesCompatible( 223 added->get_type(), existing.id->get_type(), Indexer() ) ) { 404 224 405 225 // it is a conflict if one declaration is deleted and the other is not 406 226 if ( deleteStmt && ! existing.deleteStmt ) { 407 return handleConflicts( existing, "deletion of defined identifier " ); 227 if ( handleConflicts.mode == OnConflict::Error ) { 228 SemanticError( added, "deletion of defined identifier " ); 229 } 230 return true; 408 231 } else if ( ! deleteStmt && existing.deleteStmt ) { 409 return handleConflicts( existing, "definition of deleted identifier " ); 232 if ( handleConflicts.mode == OnConflict::Error ) { 233 SemanticError( added, "definition of deleted identifier " ); 234 } 235 return true; 410 236 } 411 237 412 238 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 413 if ( isFunction( added ) ) { 414 return handleConflicts( existing, "duplicate function definition for " ); 239 if ( handleConflicts.mode == OnConflict::Error ) { 240 SemanticError( added, 241 isFunction( added ) ? 242 "duplicate function definition for " : 243 "duplicate object definition for " ); 244 } 245 return true; 246 } // if 247 } else { 248 if ( handleConflicts.mode == OnConflict::Error ) { 249 SemanticError( added, "duplicate definition for " ); 250 } 251 return true; 252 } // if 253 254 return true; 255 } 256 257 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const { 258 if ( ! idTable ) return false; 259 260 ++* stats().map_lookups; 261 auto decls = idTable->find( id ); 262 if ( decls == idTable->end() ) return false; 263 264 for ( auto decl : *(decls->second) ) { 265 // skip other scopes (hidden by this decl) 266 if ( decl.second.scope != scope ) continue; 267 // check for C decl with compatible type (by mangleName) 268 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) { 269 return true; 270 } 271 } 272 273 return false; 274 } 275 276 bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const { 277 if ( ! idTable ) return false; 278 279 ++* stats().map_lookups; 280 auto decls = idTable->find( id ); 281 if ( decls == idTable->end() ) return false; 282 283 for ( auto decl : *(decls->second) ) { 284 // skip other scopes (hidden by this decl) 285 if ( decl.second.scope != scope ) continue; 286 // check for C decl with incompatible type (by manglename) 287 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) { 288 return true; 289 } 290 } 291 292 return false; 293 } 294 295 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 296 std::string getOtypeKey( const FunctionDecl * function ) { 297 auto& params = function->type->parameters; 298 assert( ! params.empty() ); 299 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 300 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 301 assert( base ); 302 return Mangler::mangle( base ); 303 } 304 305 /// gets the declaration for the function acting on a type specified by otype key, 306 /// nullptr if none such 307 const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) { 308 const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ); 309 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr; 310 return func; 311 } 312 313 bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 314 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 315 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 316 // if the user defines a default ctor, then the generated default ctor is unavailable, 317 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 318 // field ctors are available. If the user defines any ctor then the generated default ctor 319 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 320 // anything that looks like a copy constructor, then the generated copy constructor is 321 // unavailable, and likewise for the assignment operator. 322 323 // only relevant on function declarations 324 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id ); 325 if ( ! function ) return true; 326 // only need to perform this check for constructors, destructors, and assignment functions 327 if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true; 328 329 // set up information for this type 330 bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage ); 331 bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name ); 332 std::string dataOtypeKey = getOtypeKey( function ); 333 334 if ( dataIsUserDefinedFunc && dataIsCopyFunc ) { 335 // this is a user-defined copy function 336 // if this is the first such, delete/remove non-user-defined overloads as needed 337 std::vector< std::string > removed; 338 std::vector< MangleTable::value_type > deleted; 339 bool alreadyUserDefinedFunc = false; 340 341 for ( const auto& entry : * mangleTable ) { 342 // skip decls that aren't functions or are for the wrong type 343 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 344 if ( ! decl ) continue; 345 346 bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name ); 347 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) { 348 // matching user-defined function 349 if ( isCopyFunc ) { 350 // mutation already performed, return early 351 return true; 352 } else { 353 // note that non-copy deletions already performed 354 alreadyUserDefinedFunc = true; 355 } 415 356 } else { 416 return handleConflicts( existing, "duplicate object definition for " ); 417 } // if 418 } // if 419 } else { 420 return handleConflicts( existing, "duplicate definition for " ); 421 } // if 422 357 // non-user-defined function; mark for deletion/removal as appropriate 358 if ( isCopyFunc ) { 359 removed.push_back( entry.first ); 360 } else if ( ! alreadyUserDefinedFunc ) { 361 deleted.push_back( entry ); 362 } 363 } 364 } 365 366 // perform removals from mangle table, and deletions if necessary 367 for ( const auto& key : removed ) { 368 ++* stats().map_mutations; 369 mangleTable = mangleTable->erase( key ); 370 } 371 if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) { 372 ++* stats().map_mutations; 373 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 374 } 375 } else if ( dataIsUserDefinedFunc ) { 376 // this is a user-defined non-copy function 377 // if this is the first user-defined function, delete non-user-defined overloads 378 std::vector< MangleTable::value_type > deleted; 379 380 for ( const auto& entry : * mangleTable ) { 381 // skip decls that aren't functions or are for the wrong type 382 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 383 if ( ! decl ) continue; 384 385 // exit early if already a matching user-defined function; 386 // earlier function will have mutated table 387 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true; 388 389 // skip mutating intrinsic functions 390 if ( decl->linkage == LinkageSpec::Intrinsic ) continue; 391 392 // user-defined non-copy functions do not override copy functions 393 if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue; 394 395 // this function to be deleted after mangleTable iteration is complete 396 deleted.push_back( entry ); 397 } 398 399 // mark deletions to update mangle table 400 // this needs to be a separate loop because of iterator invalidation 401 for ( const auto& entry : deleted ) { 402 ++* stats().map_mutations; 403 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 404 } 405 } else if ( function->linkage != LinkageSpec::Intrinsic ) { 406 // this is an overridable generated function 407 // if there already exists a matching user-defined function, delete this appropriately 408 for ( const auto& entry : * mangleTable ) { 409 // skip decls that aren't functions or are for the wrong type 410 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 411 if ( ! decl ) continue; 412 413 // skip non-user-defined functions 414 if ( LinkageSpec::isOverridable( decl->linkage ) ) continue; 415 416 if ( dataIsCopyFunc ) { 417 // remove current function if exists a user-defined copy function 418 // since the signatures for copy functions don't need to match exactly, using 419 // a delete statement is the wrong approach 420 if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false; 421 } else { 422 // mark current function deleted by first user-defined function found 423 data.deleteStmt = decl; 424 return true; 425 } 426 } 427 } 428 429 // nothing (more) to fix, return true 423 430 return true; 424 431 } 425 432 426 void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) { 427 if ( decl->name == "" ) return; 428 debugPrint( "Adding Id " << decl->name << std::endl ); 429 makeWritable(); 430 433 void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr, 434 const Declaration * deleteStmt ) { 435 ++* stats().add_calls; 431 436 const std::string &name = decl->name; 437 if ( name == "" ) return; 438 432 439 std::string mangleName; 433 440 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 434 // mangle the name without including the appropriate suffix, so overridable routines are placed into the435 // same "bucket" as their user defined versions.441 // mangle the name without including the appropriate suffix, so overridable routines 442 // are placed into the same "bucket" as their user defined versions. 436 443 mangleName = Mangler::mangle( decl, false ); 437 444 } else { … … 439 446 } // if 440 447 441 // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage 442 if ( ! LinkageSpec::isMangled( decl->linkage ) ) { 443 // NOTE this is broken in Richard's original code in such a way that it never triggers (it 444 // doesn't check decls that have the same manglename, and all C-linkage decls are defined to 445 // have their name as their manglename, hence the error can never trigger). 446 // The code here is closer to correct, but name mangling would have to be completely 447 // isomorphic to C type-compatibility, which it may not be. 448 if ( hasIncompatibleCDecl( name, mangleName, scope ) ) { 448 // this ensures that no two declarations with the same unmangled name at the same scope 449 // both have C linkage 450 if ( LinkageSpec::isMangled( decl->linkage ) ) { 451 // Check that a Cforall declaration doesn't override any C declaration 452 if ( hasCompatibleCDecl( name, mangleName ) ) { 453 SemanticError( decl, "Cforall declaration hides C function " ); 454 } 455 } else { 456 // NOTE: only correct if name mangling is completely isomorphic to C 457 // type-compatibility, which it may not be. 458 if ( hasIncompatibleCDecl( name, mangleName ) ) { 449 459 SemanticError( decl, "conflicting overload of C function " ); 450 460 } 451 } else { 452 // Check that a Cforall declaration doesn't override any C declaration 453 if ( hasCompatibleCDecl( name, mangleName, scope ) ) { 454 SemanticError( decl, "Cforall declaration hides C function " ); 455 } 456 } 457 458 // Skip repeat declarations of the same identifier 459 IdData * existing = lookupIdAtScope( name, mangleName, scope ); 460 if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return; 461 462 // add to indexer 463 tables->idTable[ name ][ mangleName ] = IdData{ decl, baseExpr, deleteStmt }; 464 ++tables->size; 465 } 466 467 void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) { 461 } 462 463 // ensure tables exist and add identifier 464 MangleTable::Ptr mangleTable; 465 if ( ! idTable ) { 466 idTable = IdTable::new_ptr(); 467 mangleTable = MangleTable::new_ptr(); 468 } else { 469 ++* stats().map_lookups; 470 auto decls = idTable->find( name ); 471 if ( decls == idTable->end() ) { 472 mangleTable = MangleTable::new_ptr(); 473 } else { 474 mangleTable = decls->second; 475 // skip in-scope repeat declarations of same identifier 476 ++* stats().map_lookups; 477 auto existing = mangleTable->find( mangleName ); 478 if ( existing != mangleTable->end() 479 && existing->second.scope == scope 480 && existing->second.id ) { 481 if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) { 482 if ( handleConflicts.mode == OnConflict::Delete ) { 483 // set delete expression for conflicting identifier 484 lazyInitScope(); 485 * stats().map_mutations += 2; 486 idTable = idTable->set( 487 name, 488 mangleTable->set( 489 mangleName, 490 IdData{ existing->second, handleConflicts.deleteStmt } ) ); 491 } 492 return; 493 } 494 } 495 } 496 } 497 498 // add/overwrite with new identifier 499 lazyInitScope(); 500 IdData data{ decl, baseExpr, deleteStmt, scope }; 501 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary 502 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 503 * stats().map_mutations += 2; 504 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) ); 505 } 506 507 void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) { 468 508 // default handling of conflicts is to raise an error 469 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );470 } 471 472 void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode* deleteStmt ) {509 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 510 } 511 512 void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) { 473 513 // default handling of conflicts is to raise an error 474 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );475 } 476 477 bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {478 if ( existing-> get_base() == 0) {514 addId( decl, OnConflict::error(), nullptr, deleteStmt ); 515 } 516 517 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) { 518 if ( existing->base == nullptr ) { 479 519 return false; 480 } else if ( added-> get_base() == 0) {520 } else if ( added->base == nullptr ) { 481 521 return true; 482 522 } else { 483 SemanticError( added, "redeclaration of " ); 484 } 485 } 486 487 void Indexer::addType( NamedTypeDecl *decl ) { 488 debugPrint( "Adding type " << decl->name << std::endl ); 489 makeWritable(); 490 491 const std::string &id = decl->get_name(); 492 TypeTable::iterator existing = tables->typeTable.find( id ); 493 if ( existing == tables->typeTable.end() ) { 494 NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope ); 495 if ( ! parent || ! addedTypeConflicts( parent, decl ) ) { 496 tables->typeTable.insert( existing, std::make_pair( id, decl ) ); 497 ++tables->size; 498 } 499 } else { 500 if ( ! addedTypeConflicts( existing->second, decl ) ) { 501 existing->second = decl; 502 } 503 } 504 } 505 506 bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) { 523 assert( existing->base && added->base ); 524 // typedef redeclarations are errors only if types are different 525 if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) { 526 SemanticError( added->location, "redeclaration of " + added->name ); 527 } 528 } 529 // does not need to be added to the table if both existing and added have a base that are 530 // the same 531 return true; 532 } 533 534 void Indexer::addType( const NamedTypeDecl * decl ) { 535 ++* stats().add_calls; 536 const std::string & id = decl->name; 537 538 if ( ! typeTable ) { 539 typeTable = TypeTable::new_ptr(); 540 } else { 541 ++* stats().map_lookups; 542 auto existing = typeTable->find( id ); 543 if ( existing != typeTable->end() 544 && existing->second.scope == scope 545 && addedTypeConflicts( existing->second.decl, decl ) ) return; 546 } 547 548 lazyInitScope(); 549 ++* stats().map_mutations; 550 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } ); 551 } 552 553 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) { 507 554 if ( ! existing->body ) { 508 555 return false; … … 513 560 } 514 561 515 void Indexer::addStruct( const std::string &id ) { 516 debugPrint( "Adding fwd decl for struct " << id << std::endl ); 562 void Indexer::addStruct( const std::string & id ) { 517 563 addStruct( new StructDecl( id ) ); 518 564 } 519 565 520 void Indexer::addStruct( StructDecl *decl ) { 521 debugPrint( "Adding struct " << decl->name << std::endl ); 522 makeWritable(); 523 524 const std::string &id = decl->get_name(); 525 StructTable::iterator existing = tables->structTable.find( id ); 526 if ( existing == tables->structTable.end() ) { 527 StructDecl *parent = tables->base.lookupStructAtScope( id, scope ); 528 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 529 tables->structTable.insert( existing, std::make_pair( id, decl ) ); 530 ++tables->size; 531 } 532 } else { 533 if ( ! addedDeclConflicts( existing->second, decl ) ) { 534 existing->second = decl; 535 } 536 } 537 } 538 539 void Indexer::addEnum( EnumDecl *decl ) { 540 debugPrint( "Adding enum " << decl->name << std::endl ); 541 makeWritable(); 542 543 const std::string &id = decl->get_name(); 544 EnumTable::iterator existing = tables->enumTable.find( id ); 545 if ( existing == tables->enumTable.end() ) { 546 EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope ); 547 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 548 tables->enumTable.insert( existing, std::make_pair( id, decl ) ); 549 ++tables->size; 550 } 551 } else { 552 if ( ! addedDeclConflicts( existing->second, decl ) ) { 553 existing->second = decl; 554 } 555 } 556 } 557 558 void Indexer::addUnion( const std::string &id ) { 559 debugPrint( "Adding fwd decl for union " << id << std::endl ); 566 void Indexer::addStruct( const StructDecl * decl ) { 567 ++* stats().add_calls; 568 const std::string & id = decl->name; 569 570 if ( ! structTable ) { 571 structTable = StructTable::new_ptr(); 572 } else { 573 ++* stats().map_lookups; 574 auto existing = structTable->find( id ); 575 if ( existing != structTable->end() 576 && existing->second.scope == scope 577 && addedDeclConflicts( existing->second.decl, decl ) ) return; 578 } 579 580 lazyInitScope(); 581 ++* stats().map_mutations; 582 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } ); 583 } 584 585 void Indexer::addEnum( const EnumDecl * decl ) { 586 ++* stats().add_calls; 587 const std::string & id = decl->name; 588 589 if ( ! enumTable ) { 590 enumTable = EnumTable::new_ptr(); 591 } else { 592 ++* stats().map_lookups; 593 auto existing = enumTable->find( id ); 594 if ( existing != enumTable->end() 595 && existing->second.scope == scope 596 && addedDeclConflicts( existing->second.decl, decl ) ) return; 597 } 598 599 lazyInitScope(); 600 ++* stats().map_mutations; 601 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } ); 602 } 603 604 void Indexer::addUnion( const std::string & id ) { 560 605 addUnion( new UnionDecl( id ) ); 561 606 } 562 607 563 void Indexer::addUnion( UnionDecl *decl ) {564 debugPrint( "Adding union " << decl->name << std::endl );565 makeWritable();566 567 const std::string &id = decl->get_name();568 UnionTable::iterator existing = tables->unionTable.find( id);569 if ( existing == tables->unionTable.end() ){570 UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );571 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {572 tables->unionTable.insert( existing, std::make_pair( id, decl ) );573 ++tables->size;574 }575 } else {576 if ( ! addedDeclConflicts( existing->second, decl ) ) { 577 existing->second = decl;578 }579 }580 } 581 582 void Indexer::addTrait( TraitDecl *decl ) {583 debugPrint( "Adding trait " << decl->name << std::endl );584 makeWritable();585 586 const std::string &id = decl->get_name();587 TraitTable::iterator existing = tables->traitTable.find( id);588 if ( existing == tables->traitTable.end() ){589 TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );590 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {591 tables->traitTable.insert( existing, std::make_pair( id, decl ) );592 ++tables->size;593 }594 } else {595 if ( ! addedDeclConflicts( existing->second, decl ) ) { 596 existing->second = decl;597 }598 }599 } 600 601 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunctionhandleConflicts ) {608 void Indexer::addUnion( const UnionDecl * decl ) { 609 ++* stats().add_calls; 610 const std::string & id = decl->name; 611 612 if ( ! unionTable ) { 613 unionTable = UnionTable::new_ptr(); 614 } else { 615 ++* stats().map_lookups; 616 auto existing = unionTable->find( id ); 617 if ( existing != unionTable->end() 618 && existing->second.scope == scope 619 && addedDeclConflicts( existing->second.decl, decl ) ) return; 620 } 621 622 lazyInitScope(); 623 ++* stats().map_mutations; 624 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } ); 625 } 626 627 void Indexer::addTrait( const TraitDecl * decl ) { 628 ++* stats().add_calls; 629 const std::string & id = decl->name; 630 631 if ( ! traitTable ) { 632 traitTable = TraitTable::new_ptr(); 633 } else { 634 ++* stats().map_lookups; 635 auto existing = traitTable->find( id ); 636 if ( existing != traitTable->end() 637 && existing->second.scope == scope 638 && addedDeclConflicts( existing->second.decl, decl ) ) return; 639 } 640 641 lazyInitScope(); 642 ++* stats().map_mutations; 643 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } ); 644 } 645 646 void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) { 602 647 for ( Declaration * decl : aggr->members ) { 603 648 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 604 649 addId( dwt, handleConflicts, expr ); 605 650 if ( dwt->name == "" ) { 606 Type * t = dwt->get_type()->stripReferences();607 if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType *>( t ) ) {651 const Type * t = dwt->get_type()->stripReferences(); 652 if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) { 608 653 Expression * base = expr->clone(); 609 654 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost? … … 616 661 } 617 662 618 void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode* withStmt ) {619 for ( Expression * expr : withExprs ) {663 void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) { 664 for ( const Expression * expr : withExprs ) { 620 665 if ( expr->result ) { 621 666 AggregateDecl * aggr = expr->result->stripReferences()->getAggr(); 622 667 assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() ); 623 668 624 addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) { 625 // on conflict, delete the identifier 626 existing.deleteStmt = withStmt; 627 return true; 628 }); 669 addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) ); 629 670 } 630 671 } … … 644 685 } 645 686 646 void Indexer::addFunctionType( FunctionType * ftype ) {687 void Indexer::addFunctionType( const FunctionType * ftype ) { 647 688 addTypes( ftype->forall ); 648 689 addIds( ftype->returnVals ); 649 690 addIds( ftype->parameters ); 650 }651 652 void Indexer::enterScope() {653 ++scope;654 655 if ( doDebug ) {656 std::cerr << "--- Entering scope " << scope << std::endl;657 }658 }659 660 void Indexer::leaveScope() {661 using std::cerr;662 663 assert( scope > 0 && "cannot leave initial scope" );664 if ( doDebug ) {665 cerr << "--- Leaving scope " << scope << " containing" << std::endl;666 }667 --scope;668 669 while ( tables && tables->scope > scope ) {670 if ( doDebug ) {671 dump( tables->idTable, cerr );672 dump( tables->typeTable, cerr );673 dump( tables->structTable, cerr );674 dump( tables->enumTable, cerr );675 dump( tables->unionTable, cerr );676 dump( tables->traitTable, cerr );677 }678 679 // swap tables for base table until we find one at an appropriate scope680 Indexer::Impl *base = newRef( tables->base.tables );681 deleteRef( tables );682 tables = base;683 }684 }685 686 void Indexer::print( std::ostream &os, int indent ) const {687 using std::cerr;688 689 if ( tables ) {690 os << "--- scope " << tables->scope << " ---" << std::endl;691 692 os << "===idTable===" << std::endl;693 dump( tables->idTable, os );694 os << "===typeTable===" << std::endl;695 dump( tables->typeTable, os );696 os << "===structTable===" << std::endl;697 dump( tables->structTable, os );698 os << "===enumTable===" << std::endl;699 dump( tables->enumTable, os );700 os << "===unionTable===" << std::endl;701 dump( tables->unionTable, os );702 os << "===contextTable===" << std::endl;703 dump( tables->traitTable, os );704 705 tables->base.print( os, indent );706 } else {707 os << "--- end ---" << std::endl;708 }709 710 691 } 711 692 … … 715 696 Expression * base = baseExpr->clone(); 716 697 ResolvExpr::referenceToRvalueConversion( base, cost ); 717 ret = new MemberExpr( id, base );698 ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base ); 718 699 // xxx - this introduces hidden environments, for now remove them. 719 700 // std::swap( base->env, ret->env ); … … 721 702 base->env = nullptr; 722 703 } else { 723 ret = new VariableExpr( id);724 } 725 if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt);704 ret = new VariableExpr( const_cast<DeclarationWithType *>(id) ); 705 } 706 if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) ); 726 707 return ret; 727 708 } -
src/SymTab/Indexer.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:38:55 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Aug 17 16:09:12 201713 // Update Count : 811 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Mar 8 13:55:00 2019 13 // Update Count : 9 14 14 // 15 15 16 16 #pragma once 17 17 18 #include < iosfwd> // for ostream19 #include <list> // for list20 #include < string> // for string21 #include < functional> // for function18 #include <functional> // for function 19 #include <list> // for list 20 #include <memory> // for shared_ptr, enable_shared_from_this 21 #include <string> // for string 22 22 23 #include " SynTree/Visitor.h" // for Visitor24 #include "SynTree/SynTree.h" // for AST nodes23 #include "Common/PersistentMap.h" // for PersistentMap 24 #include "SynTree/SynTree.h" // for AST nodes 25 25 26 26 namespace ResolvExpr { 27 class Cost;27 class Cost; 28 28 } 29 29 30 30 namespace SymTab { 31 class Indexer {32 public:31 class Indexer : public std::enable_shared_from_this<SymTab::Indexer> { 32 public: 33 33 explicit Indexer(); 34 virtual ~Indexer(); 34 35 35 Indexer( const Indexer &that ); 36 Indexer( Indexer &&that ); 37 virtual ~Indexer(); 38 Indexer& operator= ( const Indexer &that ); 39 Indexer& operator= ( Indexer &&that ); 40 41 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to tell the indexer 42 // explicitly when scopes begin and end 36 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to 37 // tell the indexer explicitly when scopes begin and end 43 38 void enterScope(); 44 39 void leaveScope(); 45 40 46 41 struct IdData { 47 DeclarationWithType * id = nullptr;48 Expression * baseExpr = nullptr; // WithExpr42 const DeclarationWithType * id = nullptr; 43 const Expression * baseExpr = nullptr; // WithExpr 49 44 50 45 /// non-null if this declaration is deleted 51 BaseSyntaxNode * deleteStmt = nullptr; 46 const Declaration * deleteStmt = nullptr; 47 /// scope of identifier 48 unsigned long scope = 0; 52 49 53 50 // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members. 54 51 IdData() = default; 55 IdData( DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ) {} 52 IdData( 53 const DeclarationWithType * id, const Expression * baseExpr, const Declaration * deleteStmt, 54 unsigned long scope ) 55 : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {} 56 IdData( const IdData& o, const Declaration * deleteStmt ) 57 : id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {} 56 58 57 59 Expression * combine( ResolvExpr::Cost & cost ) const; … … 59 61 60 62 /// Gets all declarations with the given ID 61 void lookupId( const std::string & id, std::list< IdData > &out ) const;63 void lookupId( const std::string & id, std::list< IdData > &out ) const; 62 64 /// Gets the top-most type declaration with the given ID 63 NamedTypeDecl *lookupType( const std::string &id ) const;65 const NamedTypeDecl * lookupType( const std::string & id ) const; 64 66 /// Gets the top-most struct declaration with the given ID 65 StructDecl *lookupStruct( const std::string &id ) const;67 const StructDecl * lookupStruct( const std::string & id ) const; 66 68 /// Gets the top-most enum declaration with the given ID 67 EnumDecl *lookupEnum( const std::string &id ) const;69 const EnumDecl * lookupEnum( const std::string & id ) const; 68 70 /// Gets the top-most union declaration with the given ID 69 UnionDecl *lookupUnion( const std::string &id ) const;71 const UnionDecl * lookupUnion( const std::string & id ) const; 70 72 /// Gets the top-most trait declaration with the given ID 71 TraitDecl *lookupTrait( const std::string &id ) const;73 const TraitDecl * lookupTrait( const std::string & id ) const; 72 74 73 void print( std::ostream &os, int indent = 0 ) const; 75 /// Gets the type declaration with the given ID at global scope 76 const NamedTypeDecl * globalLookupType( const std::string & id ) const; 77 /// Gets the struct declaration with the given ID at global scope 78 const StructDecl * globalLookupStruct( const std::string & id ) const; 79 /// Gets the union declaration with the given ID at global scope 80 const UnionDecl * globalLookupUnion( const std::string & id ) const; 81 /// Gets the enum declaration with the given ID at global scope 82 const EnumDecl * globalLookupEnum( const std::string & id ) const; 74 83 75 /// looks up a specific mangled ID at the given scope 76 IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ); 77 const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const; 78 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name 79 bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const; 80 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name 81 bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const; 82 // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope) 83 NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const; 84 StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const; 85 EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const; 86 UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const; 87 TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const; 84 void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr ); 85 void addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ); 88 86 89 typedef std::function<bool(IdData &, const std::string &)> ConflictFunction; 90 91 void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr ); 92 void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ); 93 94 void addType( NamedTypeDecl *decl ); 95 void addStruct( const std::string &id ); 96 void addStruct( StructDecl *decl ); 97 void addEnum( EnumDecl *decl ); 98 void addUnion( const std::string &id ); 99 void addUnion( UnionDecl *decl ); 100 void addTrait( TraitDecl *decl ); 87 void addType( const NamedTypeDecl * decl ); 88 void addStruct( const std::string & id ); 89 void addStruct( const StructDecl * decl ); 90 void addEnum( const EnumDecl * decl ); 91 void addUnion( const std::string & id ); 92 void addUnion( const UnionDecl * decl ); 93 void addTrait( const TraitDecl * decl ); 101 94 102 95 /// adds all of the IDs from WithStmt exprs 103 void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ); 104 105 /// adds all of the members of the Aggregate (addWith helper) 106 void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction ); 96 void addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ); 107 97 108 98 /// convenience function for adding a list of Ids to the indexer … … 113 103 114 104 /// convenience function for adding all of the declarations in a function type to the indexer 115 void addFunctionType( FunctionType * ftype );105 void addFunctionType( const FunctionType * ftype ); 116 106 117 bool doDebug = false; ///< Display debugging trace?118 107 private: 119 struct Impl; 108 /// Wraps a Decl * with a scope 109 template<typename Decl> 110 struct Scoped { 111 const Decl * decl; ///< declaration 112 unsigned long scope; ///< scope of this declaration 120 113 121 Impl *tables; ///< Copy-on-write instance of table data structure122 unsigned long scope; ///< Scope index of this pointer114 Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {} 115 }; 123 116 124 /// Takes a new ref to a table (returns null if null) 125 static Impl *newRef( Impl *toClone ); 126 /// Clears a ref to a table (does nothing if null) 127 static void deleteRef( Impl *toFree ); 117 using Ptr = std::shared_ptr<const Indexer>; 128 118 129 // Removes matching autogenerated constructors and destructors 130 // so that they will not be selected 131 // void removeSpecialOverrides( FunctionDecl *decl ); 132 void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const; 119 using MangleTable = PersistentMap< std::string, IdData >; 120 using IdTable = PersistentMap< std::string, MangleTable::Ptr >; 121 using TypeTable = PersistentMap< std::string, Scoped<NamedTypeDecl> >; 122 using StructTable = PersistentMap< std::string, Scoped<StructDecl> >; 123 using EnumTable = PersistentMap< std::string, Scoped<EnumDecl> >; 124 using UnionTable = PersistentMap< std::string, Scoped<UnionDecl> >; 125 using TraitTable = PersistentMap< std::string, Scoped<TraitDecl> >; 133 126 134 /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope) 135 void makeWritable(); 127 IdTable::Ptr idTable; ///< identifier namespace 128 TypeTable::Ptr typeTable; ///< type namespace 129 StructTable::Ptr structTable; ///< struct namespace 130 EnumTable::Ptr enumTable; ///< enum namespace 131 UnionTable::Ptr unionTable; ///< union namespace 132 TraitTable::Ptr traitTable; ///< trait namespace 133 134 Ptr prevScope; ///< reference to indexer for parent scope 135 unsigned long scope; ///< Scope index of this indexer 136 unsigned long repScope; ///< Scope index of currently represented scope 137 138 /// Ensures that a proper backtracking scope exists before a mutation 139 void lazyInitScope(); 140 141 /// Gets the indexer at the given scope 142 const Indexer * atScope( unsigned long scope ) const; 143 144 /// Removes matching autogenerated constructors and destructors so that they will not be 145 /// selected. If returns false, passed decl should not be added. 146 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable ); 147 148 /// Options for handling identifier conflicts 149 struct OnConflict { 150 enum { 151 Error, ///< Throw a semantic error 152 Delete ///< Delete the earlier version with the delete statement 153 } mode; 154 const Declaration * deleteStmt; ///< Statement that deletes this expression 155 156 private: 157 OnConflict() : mode(Error), deleteStmt(nullptr) {} 158 OnConflict( const Declaration * d ) : mode(Delete), deleteStmt(d) {} 159 public: 160 OnConflict( const OnConflict& ) = default; 161 162 static OnConflict error() { return {}; } 163 static OnConflict deleteWith( const Declaration * d ) { return { d }; } 164 }; 165 166 /// true if the existing identifier conflicts with the added identifier 167 bool addedIdConflicts( 168 const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts, 169 const Declaration * deleteStmt ); 136 170 137 171 /// common code for addId, addDeletedId, etc. 138 void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr ); 172 void addId(const DeclarationWithType * decl, OnConflict handleConflicts, 173 const Expression * baseExpr = nullptr, const Declaration * deleteStmt = nullptr ); 174 175 /// adds all of the members of the Aggregate (addWith helper) 176 void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ); 177 178 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name 179 bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const; 180 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name 181 bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const; 139 182 }; 140 183 } // namespace SymTab -
src/SymTab/Mangler.cc
r7951100 rb067d9b 10 10 // Created On : Sun May 17 21:40:29 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 25 15:49:26 201713 // Update Count : 2 312 // Last Modified On : Tue Jul 30 13:46:10 2019 13 // Update Count : 26 14 14 // 15 15 #include "Mangler.h" 16 16 17 #include <algorithm> // for copy, transform18 #include <cassert> // for assert, assertf19 #include <functional> // for const_mem_fun_t, mem_fun20 #include <iterator> // for ostream_iterator, back_insert_ite...21 #include <list> // for _List_iterator, list, _List_const...22 #include <string> // for string, char_traits, operator<<23 24 #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup17 #include <algorithm> // for copy, transform 18 #include <cassert> // for assert, assertf 19 #include <functional> // for const_mem_fun_t, mem_fun 20 #include <iterator> // for ostream_iterator, back_insert_ite... 21 #include <list> // for _List_iterator, list, _List_const... 22 #include <string> // for string, char_traits, operator<< 23 24 #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup 25 25 #include "Common/PassVisitor.h" 26 #include "Common/SemanticError.h" // for SemanticError 27 #include "Common/utility.h" // for toString 28 #include "Parser/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... 29 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType 30 #include "SynTree/Expression.h" // for TypeExpr, Expression, operator<< 31 #include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora... 26 #include "Common/SemanticError.h" // for SemanticError 27 #include "Common/utility.h" // for toString 28 #include "Parser/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... 29 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 30 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType 31 #include "SynTree/Expression.h" // for TypeExpr, Expression, operator<< 32 #include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora... 33 34 #include "AST/Pass.hpp" 32 35 33 36 namespace SymTab { … … 35 38 namespace { 36 39 /// Mangles names to a unique C identifier 37 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards { 38 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); 39 Mangler( const Mangler & ) = delete; 40 41 void previsit( BaseSyntaxNode * ) { visit_children = false; } 42 43 void postvisit( ObjectDecl * declaration ); 44 void postvisit( FunctionDecl * declaration ); 45 void postvisit( TypeDecl * declaration ); 46 47 void postvisit( VoidType * voidType ); 48 void postvisit( BasicType * basicType ); 49 void postvisit( PointerType * pointerType ); 50 void postvisit( ArrayType * arrayType ); 51 void postvisit( ReferenceType * refType ); 52 void postvisit( FunctionType * functionType ); 53 void postvisit( StructInstType * aggregateUseType ); 54 void postvisit( UnionInstType * aggregateUseType ); 55 void postvisit( EnumInstType * aggregateUseType ); 56 void postvisit( TypeInstType * aggregateUseType ); 57 void postvisit( TraitInstType * inst ); 58 void postvisit( TupleType * tupleType ); 59 void postvisit( VarArgsType * varArgsType ); 60 void postvisit( ZeroType * zeroType ); 61 void postvisit( OneType * oneType ); 40 struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards { 41 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); 42 Mangler_old( const Mangler_old & ) = delete; 43 44 void previsit( const BaseSyntaxNode * ) { visit_children = false; } 45 46 void postvisit( const ObjectDecl * declaration ); 47 void postvisit( const FunctionDecl * declaration ); 48 void postvisit( const TypeDecl * declaration ); 49 50 void postvisit( const VoidType * voidType ); 51 void postvisit( const BasicType * basicType ); 52 void postvisit( const PointerType * pointerType ); 53 void postvisit( const ArrayType * arrayType ); 54 void postvisit( const ReferenceType * refType ); 55 void postvisit( const FunctionType * functionType ); 56 void postvisit( const StructInstType * aggregateUseType ); 57 void postvisit( const UnionInstType * aggregateUseType ); 58 void postvisit( const EnumInstType * aggregateUseType ); 59 void postvisit( const TypeInstType * aggregateUseType ); 60 void postvisit( const TraitInstType * inst ); 61 void postvisit( const TupleType * tupleType ); 62 void postvisit( const VarArgsType * varArgsType ); 63 void postvisit( const ZeroType * zeroType ); 64 void postvisit( const OneType * oneType ); 65 void postvisit( const QualifiedType * qualType ); 62 66 63 67 std::string get_mangleName() { return mangleName.str(); } … … 72 76 bool mangleGenericParams; ///< Include generic parameters in name mangling if true 73 77 bool inFunctionType = false; ///< Include type qualifiers if false. 74 75 void mangleDecl( DeclarationWithType *declaration ); 76 void mangleRef( ReferenceToType *refType, std::string prefix ); 77 78 void printQualifiers( Type *type ); 79 }; // Mangler 78 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type 79 80 public: 81 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 82 int nextVarNum, const VarMapType& varNums ); 83 84 private: 85 void mangleDecl( const DeclarationWithType * declaration ); 86 void mangleRef( const ReferenceToType * refType, std::string prefix ); 87 88 void printQualifiers( const Type *type ); 89 }; // Mangler_old 80 90 } // namespace 81 91 82 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {83 PassVisitor<Mangler > mangler( mangleOverridable, typeMode, mangleGenericParams );92 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { 93 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams ); 84 94 maybeAccept( decl, mangler ); 85 95 return mangler.pass.get_mangleName(); 86 96 } 87 97 88 std::string mangleType( Type * ty ) {89 PassVisitor<Mangler > mangler( false, true, true );98 std::string mangleType( const Type * ty ) { 99 PassVisitor<Mangler_old> mangler( false, true, true ); 90 100 maybeAccept( ty, mangler ); 91 101 return mangler.pass.get_mangleName(); 92 102 } 93 103 94 std::string mangleConcrete( Type * ty ) {95 PassVisitor<Mangler > mangler( false, false, false );104 std::string mangleConcrete( const Type * ty ) { 105 PassVisitor<Mangler_old> mangler( false, false, false ); 96 106 maybeAccept( ty, mangler ); 97 107 return mangler.pass.get_mangleName(); … … 99 109 100 110 namespace { 101 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 102 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {} 103 104 void Mangler::mangleDecl( DeclarationWithType * declaration ) { 111 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 112 : nextVarNum( 0 ), isTopLevel( true ), 113 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 114 mangleGenericParams( mangleGenericParams ) {} 115 116 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 117 int nextVarNum, const VarMapType& varNums ) 118 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 119 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 120 mangleGenericParams( mangleGenericParams ) {} 121 122 void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) { 105 123 bool wasTopLevel = isTopLevel; 106 124 if ( isTopLevel ) { … … 109 127 isTopLevel = false; 110 128 } // if 111 mangleName << "__";129 mangleName << Encoding::manglePrefix; 112 130 CodeGen::OperatorInfo opInfo; 113 131 if ( operatorLookup( declaration->get_name(), opInfo ) ) { 114 mangleName << opInfo.outputName ;132 mangleName << opInfo.outputName.size() << opInfo.outputName; 115 133 } else { 116 mangleName << declaration->get_name(); 117 } // if 118 mangleName << "__"; 134 mangleName << declaration->name.size() << declaration->name; 135 } // if 119 136 maybeAccept( declaration->get_type(), *visitor ); 120 137 if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) { … … 122 139 // so they need a different name mangling 123 140 if ( declaration->get_linkage() == LinkageSpec::AutoGen ) { 124 mangleName << "autogen__";141 mangleName << Encoding::autogen; 125 142 } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) { 126 mangleName << "intrinsic__";143 mangleName << Encoding::intrinsic; 127 144 } else { 128 145 // if we add another kind of overridable function, this has to change … … 133 150 } 134 151 135 void Mangler ::postvisit(ObjectDecl * declaration ) {152 void Mangler_old::postvisit( const ObjectDecl * declaration ) { 136 153 mangleDecl( declaration ); 137 154 } 138 155 139 void Mangler ::postvisit(FunctionDecl * declaration ) {156 void Mangler_old::postvisit( const FunctionDecl * declaration ) { 140 157 mangleDecl( declaration ); 141 158 } 142 159 143 void Mangler ::postvisit(VoidType * voidType ) {160 void Mangler_old::postvisit( const VoidType * voidType ) { 144 161 printQualifiers( voidType ); 145 mangleName << "v"; 146 } 147 148 void Mangler::postvisit( BasicType * basicType ) { 149 static const char *btLetter[] = { 150 "b", // Bool 151 "c", // Char 152 "Sc", // SignedChar 153 "Uc", // UnsignedChar 154 "s", // ShortSignedInt 155 "Us", // ShortUnsignedInt 156 "i", // SignedInt 157 "Ui", // UnsignedInt 158 "l", // LongSignedInt 159 "Ul", // LongUnsignedInt 160 "q", // LongLongSignedInt 161 "Uq", // LongLongUnsignedInt 162 "f", // Float 163 "d", // Double 164 "r", // LongDouble 165 "Xf", // FloatComplex 166 "Xd", // DoubleComplex 167 "Xr", // LongDoubleComplex 168 "If", // FloatImaginary 169 "Id", // DoubleImaginary 170 "Ir", // LongDoubleImaginary 171 "w", // SignedInt128 172 "Uw", // UnsignedInt128 173 "x", // Float80 174 "y", // Float128 175 }; 176 static_assert( 177 sizeof(btLetter)/sizeof(btLetter[0]) == BasicType::NUMBER_OF_BASIC_TYPES, 178 "Each basic type kind should have a corresponding mangler letter" 179 ); 180 162 mangleName << Encoding::void_t; 163 } 164 165 void Mangler_old::postvisit( const BasicType * basicType ) { 181 166 printQualifiers( basicType ); 182 assert ( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]));183 mangleName << btLetter[ basicType->get_kind()];184 } 185 186 void Mangler ::postvisit(PointerType * pointerType ) {167 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind ); 168 mangleName << Encoding::basicTypes[ basicType->kind ]; 169 } 170 171 void Mangler_old::postvisit( const PointerType * pointerType ) { 187 172 printQualifiers( pointerType ); 188 173 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers 189 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << "P";174 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer; 190 175 maybeAccept( pointerType->base, *visitor ); 191 176 } 192 177 193 void Mangler ::postvisit(ArrayType * arrayType ) {178 void Mangler_old::postvisit( const ArrayType * arrayType ) { 194 179 // TODO: encode dimension 195 180 printQualifiers( arrayType ); 196 mangleName << "A0";181 mangleName << Encoding::array << "0"; 197 182 maybeAccept( arrayType->base, *visitor ); 198 183 } 199 184 200 void Mangler ::postvisit(ReferenceType * refType ) {185 void Mangler_old::postvisit( const ReferenceType * refType ) { 201 186 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 202 187 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), … … 217 202 } 218 203 219 void Mangler ::postvisit(FunctionType * functionType ) {204 void Mangler_old::postvisit( const FunctionType * functionType ) { 220 205 printQualifiers( functionType ); 221 mangleName << "F";206 mangleName << Encoding::function; 222 207 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters, 223 208 // since qualifiers on outermost parameter type do not differentiate function types, e.g., … … 226 211 inFunctionType = true; 227 212 std::list< Type* > returnTypes = getTypes( functionType->returnVals ); 228 acceptAll( returnTypes, *visitor ); 213 if (returnTypes.empty()) mangleName << Encoding::void_t; 214 else acceptAll( returnTypes, *visitor ); 229 215 mangleName << "_"; 230 216 std::list< Type* > paramTypes = getTypes( functionType->parameters ); … … 233 219 } 234 220 235 void Mangler ::mangleRef(ReferenceToType * refType, std::string prefix ) {221 void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) { 236 222 printQualifiers( refType ); 237 223 238 mangleName << ( refType->name.length() + prefix.length() ) << prefix<< refType->name;224 mangleName << prefix << refType->name.length() << refType->name; 239 225 240 226 if ( mangleGenericParams ) { 241 std::list< Expression* >& params = refType->parameters;227 const std::list< Expression* > & params = refType->parameters; 242 228 if ( ! params.empty() ) { 243 229 mangleName << "_"; 244 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param) {245 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );246 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString( *param));230 for ( const Expression * param : params ) { 231 const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param ); 232 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 247 233 maybeAccept( paramType->type, *visitor ); 248 234 } … … 252 238 } 253 239 254 void Mangler ::postvisit(StructInstType * aggregateUseType ) {255 mangleRef( aggregateUseType, "s");256 } 257 258 void Mangler ::postvisit(UnionInstType * aggregateUseType ) {259 mangleRef( aggregateUseType, "u");260 } 261 262 void Mangler ::postvisit(EnumInstType * aggregateUseType ) {263 mangleRef( aggregateUseType, "e");264 } 265 266 void Mangler ::postvisit(TypeInstType * typeInst ) {240 void Mangler_old::postvisit( const StructInstType * aggregateUseType ) { 241 mangleRef( aggregateUseType, Encoding::struct_t ); 242 } 243 244 void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) { 245 mangleRef( aggregateUseType, Encoding::union_t ); 246 } 247 248 void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) { 249 mangleRef( aggregateUseType, Encoding::enum_t ); 250 } 251 252 void Mangler_old::postvisit( const TypeInstType * typeInst ) { 267 253 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 268 254 if ( varNum == varNums.end() ) { 269 mangleRef( typeInst, "t");255 mangleRef( typeInst, Encoding::type ); 270 256 } else { 271 257 printQualifiers( typeInst ); 272 std::ostringstream numStream; 273 numStream << varNum->second.first; 274 switch ( (TypeDecl::Kind )varNum->second.second ) { 275 case TypeDecl::Dtype: 276 mangleName << "d"; 277 break; 278 case TypeDecl::Ftype: 279 mangleName << "f"; 280 break; 281 case TypeDecl::Ttype: 282 mangleName << "tVARGS"; 283 break; 284 default: 285 assert( false ); 286 } // switch 287 mangleName << numStream.str(); 288 } // if 289 } 290 291 void Mangler::postvisit( TraitInstType * inst ) { 258 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g. 259 // forall(dtype T) void f(T); 260 // forall(dtype S) void f(S); 261 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they 262 // are first found and prefixing with the appropriate encoding for the type class. 263 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second ); 264 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first; 265 } // if 266 } 267 268 void Mangler_old::postvisit( const TraitInstType * inst ) { 292 269 printQualifiers( inst ); 293 mangleName << "_Y" << inst->name << "_";294 } 295 296 void Mangler ::postvisit(TupleType * tupleType ) {270 mangleName << inst->name.size() << inst->name; 271 } 272 273 void Mangler_old::postvisit( const TupleType * tupleType ) { 297 274 printQualifiers( tupleType ); 298 mangleName << "T";275 mangleName << Encoding::tuple << tupleType->types.size(); 299 276 acceptAll( tupleType->types, *visitor ); 300 mangleName << "_"; 301 } 302 303 void Mangler::postvisit( VarArgsType * varArgsType ) { 277 } 278 279 void Mangler_old::postvisit( const VarArgsType * varArgsType ) { 304 280 printQualifiers( varArgsType ); 305 mangleName << "VARGS"; 306 } 307 308 void Mangler::postvisit( ZeroType * ) { 309 mangleName << "Z"; 310 } 311 312 void Mangler::postvisit( OneType * ) { 313 mangleName << "O"; 314 } 315 316 void Mangler::postvisit( TypeDecl * decl ) { 317 static const char *typePrefix[] = { "BT", "BD", "BF" }; 318 mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name; 281 static const std::string vargs = "__builtin_va_list"; 282 mangleName << Encoding::type << vargs.size() << vargs; 283 } 284 285 void Mangler_old::postvisit( const ZeroType * ) { 286 mangleName << Encoding::zero; 287 } 288 289 void Mangler_old::postvisit( const OneType * ) { 290 mangleName << Encoding::one; 291 } 292 293 void Mangler_old::postvisit( const QualifiedType * qualType ) { 294 bool inqual = inQualifiedType; 295 if (! inqual ) { 296 // N marks the start of a qualified type 297 inQualifiedType = true; 298 mangleName << Encoding::qualifiedTypeStart; 299 } 300 maybeAccept( qualType->parent, *visitor ); 301 maybeAccept( qualType->child, *visitor ); 302 if ( ! inqual ) { 303 // E marks the end of a qualified type 304 inQualifiedType = false; 305 mangleName << Encoding::qualifiedTypeEnd; 306 } 307 } 308 309 void Mangler_old::postvisit( const TypeDecl * decl ) { 310 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 311 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. 312 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply 313 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 314 // aside from the assert false. 315 assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl)); 316 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 317 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name; 319 318 } 320 319 … … 325 324 } 326 325 327 void Mangler ::printQualifiers(Type * type ) {326 void Mangler_old::printQualifiers( const Type * type ) { 328 327 // skip if not including qualifiers 329 328 if ( typeMode ) return; 330 if ( ! type-> get_forall().empty() ) {329 if ( ! type->forall.empty() ) { 331 330 std::list< std::string > assertionNames; 332 int tcount = 0, dcount = 0, fcount = 0, vcount = 0;333 mangleName << "A";334 for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i) {335 switch ( (*i)->get_kind()) {331 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 332 mangleName << Encoding::forall; 333 for ( const TypeDecl * i : type->forall ) { 334 switch ( i->kind ) { 336 335 case TypeDecl::Dtype: 337 336 dcount++; … … 346 345 assert( false ); 347 346 } // switch 348 varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() ); 349 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 350 PassVisitor<Mangler> sub_mangler( mangleOverridable, typeMode, mangleGenericParams ); 351 sub_mangler.pass.nextVarNum = nextVarNum; 352 sub_mangler.pass.isTopLevel = false; 353 sub_mangler.pass.varNums = varNums; 354 (*assert)->accept( sub_mangler ); 355 assertionNames.push_back( sub_mangler.pass.mangleName.str() ); 347 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind ); 348 for ( const DeclarationWithType * assert : i->assertions ) { 349 PassVisitor<Mangler_old> sub_mangler( 350 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 351 assert->accept( sub_mangler ); 352 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 353 acount++; 356 354 } // for 357 355 } // for 358 mangleName << tcount << "_" << dcount << "_" << fcount << "_" << vcount << "_";356 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_"; 359 357 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); 360 358 mangleName << "_"; … … 363 361 // these qualifiers do not distinguish the outermost type of a function parameter 364 362 if ( type->get_const() ) { 365 mangleName << "C";363 mangleName << Encoding::qualifiers.at(Type::Const); 366 364 } // if 367 365 if ( type->get_volatile() ) { 368 mangleName << "V";366 mangleName << Encoding::qualifiers.at(Type::Volatile); 369 367 } // if 370 368 // Removed due to restrict not affecting function compatibility in GCC … … 373 371 // } // if 374 372 if ( type->get_atomic() ) { 375 mangleName << "A";373 mangleName << Encoding::qualifiers.at(Type::Atomic); 376 374 } // if 377 375 } 378 376 if ( type->get_mutex() ) { 379 mangleName << "M"; 380 } // if 381 if ( type->get_lvalue() ) { 382 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues 383 mangleName << "L"; 384 } 385 377 mangleName << Encoding::qualifiers.at(Type::Mutex); 378 } // if 386 379 if ( inFunctionType ) { 387 380 // turn off inFunctionType so that types can be differentiated for nested qualifiers … … 394 387 } // namespace SymTab 395 388 389 namespace Mangle { 390 namespace { 391 /// Mangles names to a unique C identifier 392 struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards { 393 Mangler_new( Mangle::Mode mode ); 394 Mangler_new( const Mangler_new & ) = delete; 395 396 void previsit( const ast::Node * ) { visit_children = false; } 397 398 void postvisit( const ast::ObjectDecl * declaration ); 399 void postvisit( const ast::FunctionDecl * declaration ); 400 void postvisit( const ast::TypeDecl * declaration ); 401 402 void postvisit( const ast::VoidType * voidType ); 403 void postvisit( const ast::BasicType * basicType ); 404 void postvisit( const ast::PointerType * pointerType ); 405 void postvisit( const ast::ArrayType * arrayType ); 406 void postvisit( const ast::ReferenceType * refType ); 407 void postvisit( const ast::FunctionType * functionType ); 408 void postvisit( const ast::StructInstType * aggregateUseType ); 409 void postvisit( const ast::UnionInstType * aggregateUseType ); 410 void postvisit( const ast::EnumInstType * aggregateUseType ); 411 void postvisit( const ast::TypeInstType * aggregateUseType ); 412 void postvisit( const ast::TraitInstType * inst ); 413 void postvisit( const ast::TupleType * tupleType ); 414 void postvisit( const ast::VarArgsType * varArgsType ); 415 void postvisit( const ast::ZeroType * zeroType ); 416 void postvisit( const ast::OneType * oneType ); 417 void postvisit( const ast::QualifiedType * qualType ); 418 419 std::string get_mangleName() { return mangleName.str(); } 420 private: 421 std::ostringstream mangleName; ///< Mangled name being constructed 422 typedef std::map< std::string, std::pair< int, int > > VarMapType; 423 VarMapType varNums; ///< Map of type variables to indices 424 int nextVarNum; ///< Next type variable index 425 bool isTopLevel; ///< Is the Mangler at the top level 426 bool mangleOverridable; ///< Specially mangle overridable built-in methods 427 bool typeMode; ///< Produce a unique mangled name for a type 428 bool mangleGenericParams; ///< Include generic parameters in name mangling if true 429 bool inFunctionType = false; ///< Include type qualifiers if false. 430 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type 431 432 private: 433 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 434 int nextVarNum, const VarMapType& varNums ); 435 friend class ast::Pass<Mangler_new>; 436 437 private: 438 void mangleDecl( const ast::DeclWithType *declaration ); 439 void mangleRef( const ast::ReferenceToType *refType, std::string prefix ); 440 441 void printQualifiers( const ast::Type *type ); 442 }; // Mangler_new 443 } // namespace 444 445 446 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) { 447 ast::Pass<Mangler_new> mangler( mode ); 448 maybeAccept( decl, mangler ); 449 return mangler.pass.get_mangleName(); 450 } 451 452 namespace { 453 Mangler_new::Mangler_new( Mangle::Mode mode ) 454 : nextVarNum( 0 ), isTopLevel( true ), 455 mangleOverridable ( ! mode.no_overrideable ), 456 typeMode ( mode.type ), 457 mangleGenericParams( ! mode.no_generic_params ) {} 458 459 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 460 int nextVarNum, const VarMapType& varNums ) 461 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 462 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 463 mangleGenericParams( mangleGenericParams ) {} 464 465 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) { 466 bool wasTopLevel = isTopLevel; 467 if ( isTopLevel ) { 468 varNums.clear(); 469 nextVarNum = 0; 470 isTopLevel = false; 471 } // if 472 mangleName << Encoding::manglePrefix; 473 CodeGen::OperatorInfo opInfo; 474 if ( operatorLookup( decl->name, opInfo ) ) { 475 mangleName << opInfo.outputName.size() << opInfo.outputName; 476 } else { 477 mangleName << decl->name.size() << decl->name; 478 } // if 479 maybeAccept( decl->get_type(), *visitor ); 480 if ( mangleOverridable && decl->linkage.is_overrideable ) { 481 // want to be able to override autogenerated and intrinsic routines, 482 // so they need a different name mangling 483 if ( decl->linkage == ast::Linkage::AutoGen ) { 484 mangleName << Encoding::autogen; 485 } else if ( decl->linkage == ast::Linkage::Intrinsic ) { 486 mangleName << Encoding::intrinsic; 487 } else { 488 // if we add another kind of overridable function, this has to change 489 assert( false && "unknown overrideable linkage" ); 490 } // if 491 } 492 isTopLevel = wasTopLevel; 493 } 494 495 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) { 496 mangleDecl( decl ); 497 } 498 499 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) { 500 mangleDecl( decl ); 501 } 502 503 void Mangler_new::postvisit( const ast::VoidType * voidType ) { 504 printQualifiers( voidType ); 505 mangleName << Encoding::void_t; 506 } 507 508 void Mangler_new::postvisit( const ast::BasicType * basicType ) { 509 printQualifiers( basicType ); 510 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind ); 511 mangleName << Encoding::basicTypes[ basicType->kind ]; 512 } 513 514 void Mangler_new::postvisit( const ast::PointerType * pointerType ) { 515 printQualifiers( pointerType ); 516 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers 517 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer; 518 maybe_accept( pointerType->base.get(), *visitor ); 519 } 520 521 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) { 522 // TODO: encode dimension 523 printQualifiers( arrayType ); 524 mangleName << Encoding::array << "0"; 525 maybeAccept( arrayType->base.get(), *visitor ); 526 } 527 528 void Mangler_new::postvisit( const ast::ReferenceType * refType ) { 529 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 530 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), 531 // by pretending every reference type is a function parameter. 532 GuardValue( inFunctionType ); 533 inFunctionType = true; 534 printQualifiers( refType ); 535 maybeAccept( refType->base.get(), *visitor ); 536 } 537 538 inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) { 539 std::vector< ast::ptr< ast::Type > > ret; 540 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ), 541 std::mem_fun( &ast::DeclWithType::get_type ) ); 542 return ret; 543 } 544 545 void Mangler_new::postvisit( const ast::FunctionType * functionType ) { 546 printQualifiers( functionType ); 547 mangleName << Encoding::function; 548 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters, 549 // since qualifiers on outermost parameter type do not differentiate function types, e.g., 550 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different 551 GuardValue( inFunctionType ); 552 inFunctionType = true; 553 std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns ); 554 if (returnTypes.empty()) mangleName << Encoding::void_t; 555 else accept_each( returnTypes, *visitor ); 556 mangleName << "_"; 557 std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params ); 558 accept_each( paramTypes, *visitor ); 559 mangleName << "_"; 560 } 561 562 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) { 563 printQualifiers( refType ); 564 565 mangleName << prefix << refType->name.length() << refType->name; 566 567 if ( mangleGenericParams ) { 568 if ( ! refType->params.empty() ) { 569 mangleName << "_"; 570 for ( const ast::Expr * param : refType->params ) { 571 auto paramType = dynamic_cast< const ast::TypeExpr * >( param ); 572 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 573 maybeAccept( paramType->type.get(), *visitor ); 574 } 575 mangleName << "_"; 576 } 577 } 578 } 579 580 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) { 581 mangleRef( aggregateUseType, Encoding::struct_t ); 582 } 583 584 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) { 585 mangleRef( aggregateUseType, Encoding::union_t ); 586 } 587 588 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) { 589 mangleRef( aggregateUseType, Encoding::enum_t ); 590 } 591 592 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) { 593 VarMapType::iterator varNum = varNums.find( typeInst->name ); 594 if ( varNum == varNums.end() ) { 595 mangleRef( typeInst, Encoding::type ); 596 } else { 597 printQualifiers( typeInst ); 598 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g. 599 // forall(dtype T) void f(T); 600 // forall(dtype S) void f(S); 601 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they 602 // are first found and prefixing with the appropriate encoding for the type class. 603 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second ); 604 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first; 605 } // if 606 } 607 608 void Mangler_new::postvisit( const ast::TraitInstType * inst ) { 609 printQualifiers( inst ); 610 mangleName << inst->name.size() << inst->name; 611 } 612 613 void Mangler_new::postvisit( const ast::TupleType * tupleType ) { 614 printQualifiers( tupleType ); 615 mangleName << Encoding::tuple << tupleType->types.size(); 616 accept_each( tupleType->types, *visitor ); 617 } 618 619 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) { 620 printQualifiers( varArgsType ); 621 static const std::string vargs = "__builtin_va_list"; 622 mangleName << Encoding::type << vargs.size() << vargs; 623 } 624 625 void Mangler_new::postvisit( const ast::ZeroType * ) { 626 mangleName << Encoding::zero; 627 } 628 629 void Mangler_new::postvisit( const ast::OneType * ) { 630 mangleName << Encoding::one; 631 } 632 633 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) { 634 bool inqual = inQualifiedType; 635 if (! inqual ) { 636 // N marks the start of a qualified type 637 inQualifiedType = true; 638 mangleName << Encoding::qualifiedTypeStart; 639 } 640 maybeAccept( qualType->parent.get(), *visitor ); 641 maybeAccept( qualType->child.get(), *visitor ); 642 if ( ! inqual ) { 643 // E marks the end of a qualified type 644 inQualifiedType = false; 645 mangleName << Encoding::qualifiedTypeEnd; 646 } 647 } 648 649 void Mangler_new::postvisit( const ast::TypeDecl * decl ) { 650 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 651 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. 652 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply 653 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 654 // aside from the assert false. 655 assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl)); 656 assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 657 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name; 658 } 659 660 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) { 661 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) { 662 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl; 663 } // for 664 } 665 666 void Mangler_new::printQualifiers( const ast::Type * type ) { 667 // skip if not including qualifiers 668 if ( typeMode ) return; 669 if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) { 670 if ( ! ptype->forall.empty() ) { 671 std::list< std::string > assertionNames; 672 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 673 mangleName << Encoding::forall; 674 for ( const ast::TypeDecl * decl : ptype->forall ) { 675 switch ( decl->kind ) { 676 case ast::TypeVar::Kind::Dtype: 677 dcount++; 678 break; 679 case ast::TypeVar::Kind::Ftype: 680 fcount++; 681 break; 682 case ast::TypeVar::Kind::Ttype: 683 vcount++; 684 break; 685 default: 686 assert( false ); 687 } // switch 688 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 689 for ( const ast::DeclWithType * assert : decl->assertions ) { 690 ast::Pass<Mangler_new> sub_mangler( 691 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 692 assert->accept( sub_mangler ); 693 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 694 acount++; 695 } // for 696 } // for 697 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_"; 698 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); 699 mangleName << "_"; 700 } // if 701 } // if 702 if ( ! inFunctionType ) { 703 // these qualifiers do not distinguish the outermost type of a function parameter 704 if ( type->is_const() ) { 705 mangleName << Encoding::qualifiers.at(Type::Const); 706 } // if 707 if ( type->is_volatile() ) { 708 mangleName << Encoding::qualifiers.at(Type::Volatile); 709 } // if 710 // Removed due to restrict not affecting function compatibility in GCC 711 // if ( type->get_isRestrict() ) { 712 // mangleName << "E"; 713 // } // if 714 if ( type->is_atomic() ) { 715 mangleName << Encoding::qualifiers.at(Type::Atomic); 716 } // if 717 } 718 if ( type->is_mutex() ) { 719 mangleName << Encoding::qualifiers.at(Type::Mutex); 720 } // if 721 if ( inFunctionType ) { 722 // turn off inFunctionType so that types can be differentiated for nested qualifiers 723 GuardValue( inFunctionType ); 724 inFunctionType = false; 725 } 726 } 727 } // namespace 728 } // namespace Mangle 729 396 730 // Local Variables: // 397 731 // tab-width: 4 // -
src/SymTab/Mangler.h
r7951100 rb067d9b 21 21 #include <utility> // for pair 22 22 23 #include "AST/Bitfield.hpp" 24 #include "AST/Fwd.hpp" 23 25 #include "SynTree/SynTree.h" // for Types 24 26 #include "SynTree/Visitor.h" // for Visitor, maybeAccept 27 28 // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling 29 // The CFA name mangling scheme is based closely on the itanium C++ name mangling scheme, with the following key differences: 30 // * Variable names are also mangled to include type information, not just functions 31 // * CFA does not have template expansion, so the rules for function specialization do not apply. 32 // * CFA instead has to handle type parameters and assertion parameters. 33 // * Currently name compression is not implemented. 34 35 namespace ResolvExpr { 36 class TypeEnvironment; 37 } 25 38 26 39 namespace SymTab { 27 40 namespace Mangler { 28 41 /// Mangle syntax tree object; primary interface to clients 29 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );42 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true ); 30 43 31 44 /// Mangle a type name; secondary interface 32 std::string mangleType( Type* ty );45 std::string mangleType( const Type * ty ); 33 46 /// Mangle ignoring generic type parameters 34 std::string mangleConcrete( Type* ty ); 47 std::string mangleConcrete( const Type * ty ); 48 49 namespace Encoding { 50 extern const std::string manglePrefix; 51 extern const std::string basicTypes[]; 52 extern const std::map<int, std::string> qualifiers; 53 54 extern const std::string void_t; 55 extern const std::string zero; 56 extern const std::string one; 57 58 extern const std::string function; 59 extern const std::string tuple; 60 extern const std::string pointer; 61 extern const std::string array; 62 extern const std::string qualifiedTypeStart; 63 extern const std::string qualifiedTypeEnd; 64 65 extern const std::string forall; 66 extern const std::string typeVariables[]; 67 68 extern const std::string struct_t; 69 extern const std::string union_t; 70 extern const std::string enum_t; 71 extern const std::string type; 72 73 extern const std::string autogen; 74 extern const std::string intrinsic; 75 }; 35 76 } // Mangler 36 77 } // SymTab 78 79 namespace Mangle { 80 /// Bitflags for mangle modes 81 enum { 82 NoOverrideable = 1 << 0, 83 Type = 1 << 1, 84 NoGenericParams = 1 << 2 85 }; 86 87 /// Bitflag type for mangler modes 88 struct mangle_flags { 89 union { 90 unsigned int val; 91 struct { 92 bool no_overrideable : 1; 93 bool type : 1; 94 bool no_generic_params : 1; 95 }; 96 }; 97 98 constexpr mangle_flags( unsigned int val ) : val(val) {} 99 }; 100 101 using Mode = bitfield<mangle_flags>; 102 103 static inline Mode typeMode() { return NoOverrideable | Type; } 104 105 /// Mangle declaration name 106 std::string mangle( const ast::Node * decl, Mode mode = {} ); 107 108 namespace Encoding { 109 using namespace SymTab::Mangler::Encoding; 110 }; 111 } 112 113 extern "C" { 114 char * cforall_demangle(const char *, int); 115 } 37 116 38 117 // Local Variables: // -
src/SymTab/Validate.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:50:04 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Aug 28 13:47:23 201713 // Update Count : 3 5911 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Aug 7 6:42:00 2019 13 // Update Count : 360 14 14 // 15 15 … … 44 44 #include <list> // for list 45 45 #include <string> // for string 46 #include <unordered_map> // for unordered_map 46 47 #include <utility> // for pair 47 48 49 #include "AST/Chain.hpp" 50 #include "AST/Decl.hpp" 51 #include "AST/Node.hpp" 52 #include "AST/Pass.hpp" 53 #include "AST/SymbolTable.hpp" 54 #include "AST/Type.hpp" 55 #include "AST/TypeSubstitution.hpp" 48 56 #include "CodeGen/CodeGenerator.h" // for genName 49 57 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 50 58 #include "ControlStruct/Mutate.h" // for ForExprMutator 59 #include "Common/CodeLocation.h" // for CodeLocation 60 #include "Common/Stats.h" // for Stats::Heap 51 61 #include "Common/PassVisitor.h" // for PassVisitor, WithDeclsToAdd 52 62 #include "Common/ScopedMap.h" // for ScopedMap … … 61 71 #include "Parser/LinkageSpec.h" // for C 62 72 #include "ResolvExpr/typeops.h" // for typesCompatible 73 #include "ResolvExpr/Resolver.h" // for findSingleExpression 74 #include "ResolvExpr/ResolveTypeof.h" // for resolveTypeof 63 75 #include "SymTab/Autogen.h" // for SizeType 64 76 #include "SynTree/Attribute.h" // for noAttributes, Attribute … … 72 84 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution 73 85 #include "SynTree/Visitor.h" // for Visitor 86 #include "Validate/HandleAttributes.h" // for handleAttributes 87 #include "Validate/FindSpecialDecls.h" // for FindSpecialDecls 74 88 75 89 class CompoundStmt; … … 77 91 class SwitchStmt; 78 92 79 #define debugPrint( x ) if ( doDebug ) { std::cout << x; }93 #define debugPrint( x ) if ( doDebug ) x 80 94 81 95 namespace SymTab { 96 /// hoists declarations that are difficult to hoist while parsing 97 struct HoistTypeDecls final : public WithDeclsToAdd { 98 void previsit( SizeofExpr * ); 99 void previsit( AlignofExpr * ); 100 void previsit( UntypedOffsetofExpr * ); 101 void previsit( CompoundLiteralExpr * ); 102 void handleType( Type * ); 103 }; 104 105 struct FixQualifiedTypes final : public WithIndexer { 106 Type * postmutate( QualifiedType * ); 107 }; 108 82 109 struct HoistStruct final : public WithDeclsToAdd, public WithGuards { 83 110 /// Flattens nested struct types 84 111 static void hoistStruct( std::list< Declaration * > &translationUnit ); 85 112 86 void previsit( EnumInstType * enumInstType );87 void previsit( StructInstType * structInstType );88 void previsit( UnionInstType * unionInstType );89 113 void previsit( StructDecl * aggregateDecl ); 90 114 void previsit( UnionDecl * aggregateDecl ); 91 115 void previsit( StaticAssertDecl * assertDecl ); 116 void previsit( StructInstType * type ); 117 void previsit( UnionInstType * type ); 118 void previsit( EnumInstType * type ); 92 119 93 120 private: 94 template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );121 template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl ); 95 122 96 123 AggregateDecl * parentAggr = nullptr; … … 106 133 107 134 /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers. 108 struct EnumAndPointerDecay {109 void previsit( EnumDecl * aggregateDecl );110 void previsit( FunctionType * func );135 struct EnumAndPointerDecay_old { 136 void previsit( EnumDecl * aggregateDecl ); 137 void previsit( FunctionType * func ); 111 138 }; 112 139 113 140 /// Associates forward declarations of aggregates with their definitions 114 struct LinkReferenceToTypes final : public WithIndexer, public WithGuards { 115 LinkReferenceToTypes( const Indexer *indexer ); 116 void postvisit( TypeInstType *typeInst ); 117 118 void postvisit( EnumInstType *enumInst ); 119 void postvisit( StructInstType *structInst ); 120 void postvisit( UnionInstType *unionInst ); 121 void postvisit( TraitInstType *traitInst ); 122 123 void postvisit( EnumDecl *enumDecl ); 124 void postvisit( StructDecl *structDecl ); 125 void postvisit( UnionDecl *unionDecl ); 141 struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting { 142 LinkReferenceToTypes_old( const Indexer * indexer ); 143 void postvisit( TypeInstType * typeInst ); 144 145 void postvisit( EnumInstType * enumInst ); 146 void postvisit( StructInstType * structInst ); 147 void postvisit( UnionInstType * unionInst ); 148 void postvisit( TraitInstType * traitInst ); 149 void previsit( QualifiedType * qualType ); 150 void postvisit( QualifiedType * qualType ); 151 152 void postvisit( EnumDecl * enumDecl ); 153 void postvisit( StructDecl * structDecl ); 154 void postvisit( UnionDecl * unionDecl ); 126 155 void postvisit( TraitDecl * traitDecl ); 127 156 128 void previsit( StructDecl * structDecl );129 void previsit( UnionDecl * unionDecl );157 void previsit( StructDecl * structDecl ); 158 void previsit( UnionDecl * unionDecl ); 130 159 131 160 void renameGenericParams( std::list< TypeDecl * > & params ); 132 161 133 162 private: 134 const Indexer * local_indexer;163 const Indexer * local_indexer; 135 164 136 165 typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType; … … 145 174 146 175 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 147 struct ForallPointerDecay final {176 struct ForallPointerDecay_old final { 148 177 void previsit( ObjectDecl * object ); 149 178 void previsit( FunctionDecl * func ); … … 165 194 }; 166 195 167 struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards{168 EliminateTypedef() : scopeLevel( 0 ) {}196 struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd { 197 ReplaceTypedef() : scopeLevel( 0 ) {} 169 198 /// Replaces typedefs by forward declarations 170 static void eliminateTypedef( std::list< Declaration * > &translationUnit ); 171 199 static void replaceTypedef( std::list< Declaration * > &translationUnit ); 200 201 void premutate( QualifiedType * ); 202 Type * postmutate( QualifiedType * qualType ); 172 203 Type * postmutate( TypeInstType * aggregateUseType ); 173 204 Declaration * postmutate( TypedefDecl * typeDecl ); … … 180 211 181 212 void premutate( CompoundStmt * compoundStmt ); 182 CompoundStmt * postmutate( CompoundStmt * compoundStmt );183 213 184 214 void premutate( StructDecl * structDecl ); 185 Declaration * postmutate( StructDecl * structDecl );186 215 void premutate( UnionDecl * unionDecl ); 187 Declaration * postmutate( UnionDecl * unionDecl );188 216 void premutate( EnumDecl * enumDecl ); 189 Declaration * postmutate( EnumDecl * enumDecl ); 190 Declaration * postmutate( TraitDecl * contextDecl ); 217 void premutate( TraitDecl * ); 191 218 192 219 void premutate( FunctionType * ftype ); … … 194 221 private: 195 222 template<typename AggDecl> 196 AggDecl *handleAggregate( AggDecl * aggDecl );197 198 template<typename AggDecl>199 223 void addImplicitTypedef( AggDecl * aggDecl ); 224 template< typename AggDecl > 225 void handleAggregate( AggDecl * aggr ); 200 226 201 227 typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr; 202 228 typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap; 203 typedef std::map< std::string, TypeDecl * > TypeDeclMap;229 typedef ScopedMap< std::string, TypeDecl * > TypeDeclMap; 204 230 TypedefMap typedefNames; 205 231 TypeDeclMap typedeclNames; 206 232 int scopeLevel; 207 233 bool inFunctionType = false; 234 }; 235 236 struct EliminateTypedef { 237 /// removes TypedefDecls from the AST 238 static void eliminateTypedef( std::list< Declaration * > &translationUnit ); 239 240 template<typename AggDecl> 241 void handleAggregate( AggDecl * aggregateDecl ); 242 243 void previsit( StructDecl * aggregateDecl ); 244 void previsit( UnionDecl * aggregateDecl ); 245 void previsit( CompoundStmt * compoundStmt ); 208 246 }; 209 247 … … 214 252 static void verify( std::list< Declaration * > &translationUnit ); 215 253 216 void previsit( FunctionDecl * funcDecl );254 void previsit( FunctionDecl * funcDecl ); 217 255 }; 218 256 … … 223 261 }; 224 262 225 struct ArrayLength { 263 struct FixObjectType : public WithIndexer { 264 /// resolves typeof type in object, function, and type declarations 265 static void fix( std::list< Declaration * > & translationUnit ); 266 267 void previsit( ObjectDecl * ); 268 void previsit( FunctionDecl * ); 269 void previsit( TypeDecl * ); 270 }; 271 272 struct ArrayLength : public WithIndexer { 226 273 /// for array types without an explicit length, compute the length and store it so that it 227 274 /// is known to the rest of the phases. For example, … … 234 281 235 282 void previsit( ObjectDecl * objDecl ); 283 void previsit( ArrayType * arrayType ); 236 284 }; 237 285 … … 239 287 Type::StorageClasses storageClasses; 240 288 241 void premutate( ObjectDecl * objectDecl );242 Expression * postmutate( CompoundLiteralExpr * compLitExpr );289 void premutate( ObjectDecl * objectDecl ); 290 Expression * postmutate( CompoundLiteralExpr * compLitExpr ); 243 291 }; 244 292 … … 250 298 }; 251 299 252 FunctionDecl * dereferenceOperator = nullptr;253 struct FindSpecialDeclarations final {254 void previsit( FunctionDecl * funcDecl );255 };256 257 300 void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) { 258 PassVisitor<EnumAndPointerDecay > epc;259 PassVisitor<LinkReferenceToTypes > lrt( nullptr );260 PassVisitor<ForallPointerDecay > fpd;301 PassVisitor<EnumAndPointerDecay_old> epc; 302 PassVisitor<LinkReferenceToTypes_old> lrt( nullptr ); 303 PassVisitor<ForallPointerDecay_old> fpd; 261 304 PassVisitor<CompoundLiteral> compoundliteral; 262 305 PassVisitor<ValidateGenericParameters> genericParams; 263 PassVisitor<FindSpecialDeclarations> finder;264 306 PassVisitor<LabelAddressFixer> labelAddrFixer; 265 266 EliminateTypedef::eliminateTypedef( translationUnit ); 267 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order 268 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 269 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling 270 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 271 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes 272 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 273 ReturnChecker::checkFunctionReturns( translationUnit ); 274 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen 275 Concurrency::applyKeywords( translationUnit ); 276 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution 277 ControlStruct::hoistControlDecls( translationUnit ); // hoist initialization out of for statements; must happen before autogenerateRoutines 278 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay 279 Concurrency::implementMutexFuncs( translationUnit ); 280 Concurrency::implementThreadStarter( translationUnit ); 281 mutateAll( translationUnit, compoundliteral ); 282 ArrayLength::computeLength( translationUnit ); 283 acceptAll( translationUnit, finder ); // xxx - remove this pass soon 284 mutateAll( translationUnit, labelAddrFixer ); 285 } 286 287 void validateType( Type *type, const Indexer *indexer ) { 288 PassVisitor<EnumAndPointerDecay> epc; 289 PassVisitor<LinkReferenceToTypes> lrt( indexer ); 290 PassVisitor<ForallPointerDecay> fpd; 307 PassVisitor<HoistTypeDecls> hoistDecls; 308 PassVisitor<FixQualifiedTypes> fixQual; 309 310 { 311 Stats::Heap::newPass("validate-A"); 312 Stats::Time::BlockGuard guard("validate-A"); 313 acceptAll( translationUnit, hoistDecls ); 314 ReplaceTypedef::replaceTypedef( translationUnit ); 315 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 316 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling 317 } 318 { 319 Stats::Heap::newPass("validate-B"); 320 Stats::Time::BlockGuard guard("validate-B"); 321 Stats::Time::TimeBlock("Link Reference To Types", [&]() { 322 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 323 }); 324 Stats::Time::TimeBlock("Fix Qualified Types", [&]() { 325 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed 326 }); 327 Stats::Time::TimeBlock("Hoist Structs", [&]() { 328 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order 329 }); 330 Stats::Time::TimeBlock("Eliminate Typedefs", [&]() { 331 EliminateTypedef::eliminateTypedef( translationUnit ); // 332 }); 333 } 334 { 335 Stats::Heap::newPass("validate-C"); 336 Stats::Time::BlockGuard guard("validate-C"); 337 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes_old 338 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 339 ReturnChecker::checkFunctionReturns( translationUnit ); 340 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen 341 } 342 { 343 Stats::Heap::newPass("validate-D"); 344 Stats::Time::BlockGuard guard("validate-D"); 345 Stats::Time::TimeBlock("Apply Concurrent Keywords", [&]() { 346 Concurrency::applyKeywords( translationUnit ); 347 }); 348 Stats::Time::TimeBlock("Forall Pointer Decay", [&]() { 349 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution 350 }); 351 Stats::Time::TimeBlock("Hoist Control Declarations", [&]() { 352 ControlStruct::hoistControlDecls( translationUnit ); // hoist initialization out of for statements; must happen before autogenerateRoutines 353 }); 354 Stats::Time::TimeBlock("Generate Autogen routines", [&]() { 355 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old 356 }); 357 } 358 { 359 Stats::Heap::newPass("validate-E"); 360 Stats::Time::BlockGuard guard("validate-E"); 361 Stats::Time::TimeBlock("Implement Mutex Func", [&]() { 362 Concurrency::implementMutexFuncs( translationUnit ); 363 }); 364 Stats::Time::TimeBlock("Implement Thread Start", [&]() { 365 Concurrency::implementThreadStarter( translationUnit ); 366 }); 367 Stats::Time::TimeBlock("Compound Literal", [&]() { 368 mutateAll( translationUnit, compoundliteral ); 369 }); 370 Stats::Time::TimeBlock("Resolve With Expressions", [&]() { 371 ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables 372 }); 373 } 374 { 375 Stats::Heap::newPass("validate-F"); 376 Stats::Time::BlockGuard guard("validate-F"); 377 Stats::Time::TimeBlock("Fix Object Type", [&]() { 378 FixObjectType::fix( translationUnit ); 379 }); 380 Stats::Time::TimeBlock("Array Length", [&]() { 381 ArrayLength::computeLength( translationUnit ); 382 }); 383 Stats::Time::TimeBlock("Find Special Declarations", [&]() { 384 Validate::findSpecialDecls( translationUnit ); 385 }); 386 Stats::Time::TimeBlock("Fix Label Address", [&]() { 387 mutateAll( translationUnit, labelAddrFixer ); 388 }); 389 Stats::Time::TimeBlock("Handle Attributes", [&]() { 390 Validate::handleAttributes( translationUnit ); 391 }); 392 } 393 } 394 395 void validateType( Type * type, const Indexer * indexer ) { 396 PassVisitor<EnumAndPointerDecay_old> epc; 397 PassVisitor<LinkReferenceToTypes_old> lrt( indexer ); 398 PassVisitor<ForallPointerDecay_old> fpd; 291 399 type->accept( epc ); 292 400 type->accept( lrt ); … … 294 402 } 295 403 404 405 void HoistTypeDecls::handleType( Type * type ) { 406 // some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here 407 AggregateDecl * aggr = nullptr; 408 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) { 409 aggr = inst->baseStruct; 410 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) { 411 aggr = inst->baseUnion; 412 } else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( type ) ) { 413 aggr = inst->baseEnum; 414 } 415 if ( aggr && aggr->body ) { 416 declsToAddBefore.push_front( aggr ); 417 } 418 } 419 420 void HoistTypeDecls::previsit( SizeofExpr * expr ) { 421 handleType( expr->type ); 422 } 423 424 void HoistTypeDecls::previsit( AlignofExpr * expr ) { 425 handleType( expr->type ); 426 } 427 428 void HoistTypeDecls::previsit( UntypedOffsetofExpr * expr ) { 429 handleType( expr->type ); 430 } 431 432 void HoistTypeDecls::previsit( CompoundLiteralExpr * expr ) { 433 handleType( expr->result ); 434 } 435 436 437 Type * FixQualifiedTypes::postmutate( QualifiedType * qualType ) { 438 Type * parent = qualType->parent; 439 Type * child = qualType->child; 440 if ( dynamic_cast< GlobalScopeType * >( qualType->parent ) ) { 441 // .T => lookup T at global scope 442 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) { 443 auto td = indexer.globalLookupType( inst->name ); 444 if ( ! td ) { 445 SemanticError( qualType->location, toString("Use of undefined global type ", inst->name) ); 446 } 447 auto base = td->base; 448 assert( base ); 449 Type * ret = base->clone(); 450 ret->get_qualifiers() = qualType->get_qualifiers(); 451 return ret; 452 } else { 453 // .T => T is not a type name 454 assertf( false, "unhandled global qualified child type: %s", toCString(child) ); 455 } 456 } else { 457 // S.T => S must be an aggregate type, find the declaration for T in S. 458 AggregateDecl * aggr = nullptr; 459 if ( StructInstType * inst = dynamic_cast< StructInstType * >( parent ) ) { 460 aggr = inst->baseStruct; 461 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * > ( parent ) ) { 462 aggr = inst->baseUnion; 463 } else { 464 SemanticError( qualType->location, toString("Qualified type requires an aggregate on the left, but has: ", parent) ); 465 } 466 assert( aggr ); // TODO: need to handle forward declarations 467 for ( Declaration * member : aggr->members ) { 468 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) { 469 // name on the right is a typedef 470 if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) { 471 if ( aggr->name == inst->name ) { 472 assert( aggr->base ); 473 Type * ret = aggr->base->clone(); 474 ret->get_qualifiers() = qualType->get_qualifiers(); 475 TypeSubstitution sub = parent->genericSubstitution(); 476 sub.apply(ret); 477 return ret; 478 } 479 } 480 } else { 481 // S.T - S is not an aggregate => error 482 assertf( false, "unhandled qualified child type: %s", toCString(qualType) ); 483 } 484 } 485 // failed to find a satisfying definition of type 486 SemanticError( qualType->location, toString("Undefined type in qualified type: ", qualType) ); 487 } 488 489 // ... may want to link canonical SUE definition to each forward decl so that it becomes easier to lookup? 490 } 491 492 296 493 void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) { 297 494 PassVisitor<HoistStruct> hoister; … … 299 496 } 300 497 301 bool shouldHoist( Declaration * decl ) {498 bool shouldHoist( Declaration * decl ) { 302 499 return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl ); 303 500 } 304 501 502 namespace { 503 void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) { 504 if ( aggr->parent ) qualifiedName( aggr->parent, ss ); 505 ss << "__" << aggr->name; 506 } 507 508 // mangle nested type names using entire parent chain 509 std::string qualifiedName( AggregateDecl * aggr ) { 510 std::ostringstream ss; 511 qualifiedName( aggr, ss ); 512 return ss.str(); 513 } 514 } 515 305 516 template< typename AggDecl > 306 void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {517 void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) { 307 518 if ( parentAggr ) { 519 aggregateDecl->parent = parentAggr; 520 aggregateDecl->name = qualifiedName( aggregateDecl ); 308 521 // Add elements in stack order corresponding to nesting structure. 309 522 declsToAddBefore.push_front( aggregateDecl ); … … 316 529 } 317 530 318 void HoistStruct::previsit( EnumInstType * inst ) {319 if ( inst->baseEnum && inst->baseEnum->body ) {320 declsToAddBefore.push_front( inst->baseEnum );321 }322 }323 324 void HoistStruct::previsit( StructInstType * inst ) {325 if ( inst->baseStruct && inst->baseStruct->body ) {326 declsToAddBefore.push_front( inst->baseStruct );327 }328 }329 330 void HoistStruct::previsit( UnionInstType * inst ) {331 if ( inst->baseUnion && inst->baseUnion->body ) {332 declsToAddBefore.push_front( inst->baseUnion );333 }334 }335 336 531 void HoistStruct::previsit( StaticAssertDecl * assertDecl ) { 337 532 if ( parentAggr ) { … … 348 543 } 349 544 350 void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) { 545 void HoistStruct::previsit( StructInstType * type ) { 546 // need to reset type name after expanding to qualified name 547 assert( type->baseStruct ); 548 type->name = type->baseStruct->name; 549 } 550 551 void HoistStruct::previsit( UnionInstType * type ) { 552 assert( type->baseUnion ); 553 type->name = type->baseUnion->name; 554 } 555 556 void HoistStruct::previsit( EnumInstType * type ) { 557 assert( type->baseEnum ); 558 type->name = type->baseEnum->name; 559 } 560 561 562 bool isTypedef( Declaration * decl ) { 563 return dynamic_cast< TypedefDecl * >( decl ); 564 } 565 566 void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) { 567 PassVisitor<EliminateTypedef> eliminator; 568 acceptAll( translationUnit, eliminator ); 569 filter( translationUnit, isTypedef, true ); 570 } 571 572 template< typename AggDecl > 573 void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) { 574 filter( aggregateDecl->members, isTypedef, true ); 575 } 576 577 void EliminateTypedef::previsit( StructDecl * aggregateDecl ) { 578 handleAggregate( aggregateDecl ); 579 } 580 581 void EliminateTypedef::previsit( UnionDecl * aggregateDecl ) { 582 handleAggregate( aggregateDecl ); 583 } 584 585 void EliminateTypedef::previsit( CompoundStmt * compoundStmt ) { 586 // remove and delete decl stmts 587 filter( compoundStmt->kids, [](Statement * stmt) { 588 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) { 589 if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) { 590 return true; 591 } // if 592 } // if 593 return false; 594 }, true); 595 } 596 597 void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) { 351 598 // Set the type of each member of the enumeration to be EnumConstant 352 for ( std::list< Declaration * >::iterator i = enumDecl-> get_members().begin(); i != enumDecl->get_members().end(); ++i ) {353 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );599 for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) { 600 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i ); 354 601 assert( obj ); 355 obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl-> get_name()) );602 obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) ); 356 603 } // for 357 604 } … … 380 627 } 381 628 382 void EnumAndPointerDecay ::previsit( FunctionType *func ) {629 void EnumAndPointerDecay_old::previsit( FunctionType * func ) { 383 630 // Fix up parameters and return types 384 631 fixFunctionList( func->parameters, func->isVarArgs, func ); … … 386 633 } 387 634 388 LinkReferenceToTypes ::LinkReferenceToTypes( const Indexer *other_indexer ) {635 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) { 389 636 if ( other_indexer ) { 390 637 local_indexer = other_indexer; … … 394 641 } 395 642 396 void LinkReferenceToTypes ::postvisit( EnumInstType *enumInst ) {397 EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name());643 void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) { 644 const EnumDecl * st = local_indexer->lookupEnum( enumInst->name ); 398 645 // it's not a semantic error if the enum is not found, just an implicit forward declaration 399 646 if ( st ) { 400 //assert( ! enumInst->get_baseEnum() || enumInst->get_baseEnum()->get_members().empty() || ! st->get_members().empty() ); 401 enumInst->set_baseEnum( st ); 402 } // if 403 if ( ! st || st->get_members().empty() ) { 647 enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node 648 } // if 649 if ( ! st || ! st->body ) { 404 650 // use of forward declaration 405 forwardEnums[ enumInst-> get_name()].push_back( enumInst );651 forwardEnums[ enumInst->name ].push_back( enumInst ); 406 652 } // if 407 653 } … … 415 661 } 416 662 417 void LinkReferenceToTypes ::postvisit( StructInstType *structInst ) {418 StructDecl *st = local_indexer->lookupStruct( structInst->get_name());663 void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) { 664 const StructDecl * st = local_indexer->lookupStruct( structInst->name ); 419 665 // it's not a semantic error if the struct is not found, just an implicit forward declaration 420 666 if ( st ) { 421 //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() ); 422 structInst->set_baseStruct( st ); 423 } // if 424 if ( ! st || st->get_members().empty() ) { 667 structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node 668 } // if 669 if ( ! st || ! st->body ) { 425 670 // use of forward declaration 426 forwardStructs[ structInst-> get_name()].push_back( structInst );671 forwardStructs[ structInst->name ].push_back( structInst ); 427 672 } // if 428 673 checkGenericParameters( structInst ); 429 674 } 430 675 431 void LinkReferenceToTypes ::postvisit( UnionInstType *unionInst ) {432 UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name());676 void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) { 677 const UnionDecl * un = local_indexer->lookupUnion( unionInst->name ); 433 678 // it's not a semantic error if the union is not found, just an implicit forward declaration 434 679 if ( un ) { 435 unionInst-> set_baseUnion( un );436 } // if 437 if ( ! un || un->get_members().empty()) {680 unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node 681 } // if 682 if ( ! un || ! un->body ) { 438 683 // use of forward declaration 439 forwardUnions[ unionInst-> get_name()].push_back( unionInst );684 forwardUnions[ unionInst->name ].push_back( unionInst ); 440 685 } // if 441 686 checkGenericParameters( unionInst ); 687 } 688 689 void LinkReferenceToTypes_old::previsit( QualifiedType * ) { 690 visit_children = false; 691 } 692 693 void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) { 694 // linking only makes sense for the 'oldest ancestor' of the qualified type 695 qualType->parent->accept( * visitor ); 442 696 } 443 697 … … 450 704 DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 ); 451 705 if ( dwt1 && dwt2 ) { 452 if ( dwt1-> get_name() == dwt2->get_name()&& ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {706 if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) { 453 707 // std::cerr << "=========== equal:" << std::endl; 454 708 // std::cerr << "d1: " << d1 << std::endl; … … 475 729 template< typename Iterator > 476 730 void expandAssertions( TraitInstType * inst, Iterator out ) { 477 assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", to String( inst ).c_str() );731 assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) ); 478 732 std::list< DeclarationWithType * > asserts; 479 733 for ( Declaration * decl : inst->baseTrait->members ) { … … 484 738 } 485 739 486 void LinkReferenceToTypes ::postvisit( TraitDecl * traitDecl ) {740 void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) { 487 741 if ( traitDecl->name == "sized" ) { 488 742 // "sized" is a special trait - flick the sized status on for the type variable … … 506 760 } 507 761 508 void LinkReferenceToTypes ::postvisit( TraitInstType * traitInst ) {762 void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) { 509 763 // handle other traits 510 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );764 const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name ); 511 765 if ( ! traitDecl ) { 512 766 SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name ); 513 767 } // if 514 if ( traitDecl-> get_parameters().size() != traitInst->get_parameters().size() ) {768 if ( traitDecl->parameters.size() != traitInst->parameters.size() ) { 515 769 SemanticError( traitInst, "incorrect number of trait parameters: " ); 516 770 } // if 517 traitInst->baseTrait = traitDecl;771 traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node 518 772 519 773 // need to carry over the 'sized' status of each decl in the instance 520 for ( auto p : group_iterate( traitDecl-> get_parameters(), traitInst->get_parameters()) ) {774 for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) { 521 775 TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) ); 522 776 if ( ! expr ) { … … 525 779 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) { 526 780 TypeDecl * formalDecl = std::get<0>(p); 527 TypeDecl * instDecl = inst-> get_baseType();781 TypeDecl * instDecl = inst->baseType; 528 782 if ( formalDecl->get_sized() ) instDecl->set_sized( true ); 529 783 } … … 532 786 } 533 787 534 void LinkReferenceToTypes ::postvisit( EnumDecl *enumDecl ) {788 void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) { 535 789 // visit enum members first so that the types of self-referencing members are updated properly 536 if ( ! enumDecl->get_members().empty()) {537 ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl-> get_name());790 if ( enumDecl->body ) { 791 ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name ); 538 792 if ( fwds != forwardEnums.end() ) { 539 793 for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 540 (* inst )->set_baseEnum( enumDecl );794 (* inst)->baseEnum = enumDecl; 541 795 } // for 542 796 forwardEnums.erase( fwds ); 543 797 } // if 544 } // if 545 } 546 547 void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) { 798 799 for ( Declaration * member : enumDecl->members ) { 800 ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member ); 801 if ( field->init ) { 802 // need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information. 803 SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init ); 804 ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer ); 805 } 806 } 807 } // if 808 } 809 810 void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) { 548 811 // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g. 549 812 // forall(otype T) … … 563 826 } 564 827 565 void LinkReferenceToTypes ::previsit( StructDecl * structDecl ) {828 void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) { 566 829 renameGenericParams( structDecl->parameters ); 567 830 } 568 831 569 void LinkReferenceToTypes ::previsit( UnionDecl * unionDecl ) {832 void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) { 570 833 renameGenericParams( unionDecl->parameters ); 571 834 } 572 835 573 void LinkReferenceToTypes ::postvisit( StructDecl *structDecl ) {836 void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) { 574 837 // visit struct members first so that the types of self-referencing members are updated properly 575 838 // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults) 576 if ( ! structDecl->get_members().empty()) {577 ForwardStructsType::iterator fwds = forwardStructs.find( structDecl-> get_name());839 if ( structDecl->body ) { 840 ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name ); 578 841 if ( fwds != forwardStructs.end() ) { 579 842 for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 580 (* inst )->set_baseStruct( structDecl );843 (* inst)->baseStruct = structDecl; 581 844 } // for 582 845 forwardStructs.erase( fwds ); … … 585 848 } 586 849 587 void LinkReferenceToTypes ::postvisit( UnionDecl *unionDecl ) {588 if ( ! unionDecl->get_members().empty()) {589 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl-> get_name());850 void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) { 851 if ( unionDecl->body ) { 852 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name ); 590 853 if ( fwds != forwardUnions.end() ) { 591 854 for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 592 (* inst )->set_baseUnion( unionDecl );855 (* inst)->baseUnion = unionDecl; 593 856 } // for 594 857 forwardUnions.erase( fwds ); … … 597 860 } 598 861 599 void LinkReferenceToTypes ::postvisit( TypeInstType *typeInst ) {862 void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) { 600 863 // ensure generic parameter instances are renamed like the base type 601 864 if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name; 602 if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name()) ) {603 if ( TypeDecl *typeDecl = dynamic_cast<TypeDecl * >( namedTypeDecl ) ) {604 typeInst->set_isFtype( typeDecl-> get_kind()== TypeDecl::Ftype );865 if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) { 866 if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) { 867 typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype ); 605 868 } // if 606 869 } // if … … 614 877 // expand trait instances into their members 615 878 for ( DeclarationWithType * assertion : asserts ) { 616 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {879 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) { 617 880 // expand trait instance into all of its members 618 881 expandAssertions( traitInst, back_inserter( type->assertions ) ); … … 634 897 } 635 898 636 void ForallPointerDecay ::previsit( ObjectDecl *object ) {899 void ForallPointerDecay_old::previsit( ObjectDecl * object ) { 637 900 // ensure that operator names only apply to functions or function pointers 638 901 if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) { … … 642 905 } 643 906 644 void ForallPointerDecay ::previsit( FunctionDecl *func ) {907 void ForallPointerDecay_old::previsit( FunctionDecl * func ) { 645 908 func->fixUniqueId(); 646 909 } 647 910 648 void ForallPointerDecay ::previsit( FunctionType * ftype ) {911 void ForallPointerDecay_old::previsit( FunctionType * ftype ) { 649 912 forallFixer( ftype->forall, ftype ); 650 913 } 651 914 652 void ForallPointerDecay ::previsit( StructDecl * aggrDecl ) {915 void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) { 653 916 forallFixer( aggrDecl->parameters, aggrDecl ); 654 917 } 655 918 656 void ForallPointerDecay ::previsit( UnionDecl * aggrDecl ) {919 void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) { 657 920 forallFixer( aggrDecl->parameters, aggrDecl ); 658 921 } … … 679 942 680 943 681 bool isTypedef( Declaration *decl ) { 682 return dynamic_cast< TypedefDecl * >( decl ); 683 } 684 685 void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) { 686 PassVisitor<EliminateTypedef> eliminator; 944 void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) { 945 PassVisitor<ReplaceTypedef> eliminator; 687 946 mutateAll( translationUnit, eliminator ); 688 947 if ( eliminator.pass.typedefNames.count( "size_t" ) ) { 689 948 // grab and remember declaration of size_t 690 SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();949 Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone(); 691 950 } else { 692 951 // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong 693 952 // eventually should have a warning for this case. 694 SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 695 } 696 filter( translationUnit, isTypedef, true ); 697 } 698 699 Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) { 953 Validate::SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 954 } 955 } 956 957 void ReplaceTypedef::premutate( QualifiedType * ) { 958 visit_children = false; 959 } 960 961 Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) { 962 // replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type 963 qualType->parent = qualType->parent->acceptMutator( * visitor ); 964 return qualType; 965 } 966 967 Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) { 700 968 // instances of typedef types will come here. If it is an instance 701 969 // of a typdef type, link the instance to its actual type. 702 TypedefMap::const_iterator def = typedefNames.find( typeInst-> get_name());970 TypedefMap::const_iterator def = typedefNames.find( typeInst->name ); 703 971 if ( def != typedefNames.end() ) { 704 Type *ret = def->second.first->base->clone(); 972 Type * ret = def->second.first->base->clone(); 973 ret->location = typeInst->location; 705 974 ret->get_qualifiers() |= typeInst->get_qualifiers(); 706 975 // attributes are not carried over from typedef to function parameters/return values … … 713 982 // place instance parameters on the typedef'd type 714 983 if ( ! typeInst->parameters.empty() ) { 715 ReferenceToType * rtt = dynamic_cast<ReferenceToType*>(ret);984 ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret); 716 985 if ( ! rtt ) { 717 986 SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name ); 718 987 } 719 rtt-> get_parameters().clear();988 rtt->parameters.clear(); 720 989 cloneAll( typeInst->parameters, rtt->parameters ); 721 mutateAll( rtt->parameters, * visitor ); // recursively fix typedefs on parameters990 mutateAll( rtt->parameters, * visitor ); // recursively fix typedefs on parameters 722 991 } // if 723 992 delete typeInst; 724 993 return ret; 725 994 } else { 726 TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() ); 727 assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() ); 995 TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name ); 996 if ( base == typedeclNames.end() ) { 997 SemanticError( typeInst->location, toString("Use of undefined type ", typeInst->name) ); 998 } 728 999 typeInst->set_baseType( base->second ); 729 } // if 730 return typeInst; 1000 return typeInst; 1001 } // if 1002 assert( false ); 731 1003 } 732 1004 … … 745 1017 } 746 1018 747 Declaration * EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {748 if ( typedefNames.count( tyDecl-> get_name() ) == 1 && typedefNames[ tyDecl->get_name()].second == scopeLevel ) {1019 Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) { 1020 if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) { 749 1021 // typedef to the same name from the same scope 750 1022 // must be from the same type 751 1023 752 Type * t1 = tyDecl-> get_base();753 Type * t2 = typedefNames[ tyDecl-> get_name() ].first->get_base();1024 Type * t1 = tyDecl->base; 1025 Type * t2 = typedefNames[ tyDecl->name ].first->base; 754 1026 if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) { 755 1027 SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name ); … … 763 1035 } 764 1036 } else { 765 typedefNames[ tyDecl-> get_name()] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );1037 typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel ); 766 1038 } // if 767 1039 … … 771 1043 // struct screen; 772 1044 // because the expansion of the typedef is: 773 // void rtn( SCREEN * p ) => void rtn( struct screen *p )1045 // void rtn( SCREEN * p ) => void rtn( struct screen * p ) 774 1046 // hence the type-name "screen" must be defined. 775 1047 // Note, qualifiers on the typedef are superfluous for the forward declaration. 776 1048 777 Type *designatorType = tyDecl->get_base()->stripDeclarator(); 778 if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) { 779 return new StructDecl( aggDecl->get_name(), DeclarationNode::Struct, noAttributes, tyDecl->get_linkage() ); 780 } else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) { 781 return new UnionDecl( aggDecl->get_name(), noAttributes, tyDecl->get_linkage() ); 782 } else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) { 783 return new EnumDecl( enumDecl->get_name(), noAttributes, tyDecl->get_linkage() ); 784 } else { 785 return tyDecl->clone(); 786 } // if 787 } 788 789 void EliminateTypedef::premutate( TypeDecl * typeDecl ) { 790 TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() ); 1049 Type * designatorType = tyDecl->base->stripDeclarator(); 1050 if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) { 1051 declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) ); 1052 } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) { 1053 declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) ); 1054 } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) { 1055 declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) ); 1056 } // if 1057 return tyDecl->clone(); 1058 } 1059 1060 void ReplaceTypedef::premutate( TypeDecl * typeDecl ) { 1061 TypedefMap::iterator i = typedefNames.find( typeDecl->name ); 791 1062 if ( i != typedefNames.end() ) { 792 1063 typedefNames.erase( i ) ; 793 1064 } // if 794 1065 795 typedeclNames [ typeDecl->get_name() ] = typeDecl;796 } 797 798 void EliminateTypedef::premutate( FunctionDecl * ) {1066 typedeclNames.insert( typeDecl->name, typeDecl ); 1067 } 1068 1069 void ReplaceTypedef::premutate( FunctionDecl * ) { 799 1070 GuardScope( typedefNames ); 800 } 801 802 void EliminateTypedef::premutate( ObjectDecl * ) { 1071 GuardScope( typedeclNames ); 1072 } 1073 1074 void ReplaceTypedef::premutate( ObjectDecl * ) { 803 1075 GuardScope( typedefNames ); 804 } 805 806 DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) { 807 if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type? 1076 GuardScope( typedeclNames ); 1077 } 1078 1079 DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) { 1080 if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type? 808 1081 // replace the current object declaration with a function declaration 809 FunctionDecl * newDecl = new FunctionDecl( objDecl-> get_name(), objDecl->get_storageClasses(), objDecl->get_linkage(), funtype, 0, objDecl->get_attributes(), objDecl->get_funcSpec() );810 objDecl-> get_attributes().clear();1082 FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() ); 1083 objDecl->attributes.clear(); 811 1084 objDecl->set_type( nullptr ); 812 1085 delete objDecl; … … 816 1089 } 817 1090 818 void EliminateTypedef::premutate( CastExpr * ) {1091 void ReplaceTypedef::premutate( CastExpr * ) { 819 1092 GuardScope( typedefNames ); 820 } 821 822 void EliminateTypedef::premutate( CompoundStmt * ) { 1093 GuardScope( typedeclNames ); 1094 } 1095 1096 void ReplaceTypedef::premutate( CompoundStmt * ) { 823 1097 GuardScope( typedefNames ); 1098 GuardScope( typedeclNames ); 824 1099 scopeLevel += 1; 825 1100 GuardAction( [this](){ scopeLevel -= 1; } ); 826 1101 } 827 1102 828 CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {829 // remove and delete decl stmts830 filter( compoundStmt->kids, [](Statement * stmt) {831 if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {832 if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {833 return true;834 } // if835 } // if836 return false;837 }, true);838 return compoundStmt;839 }840 841 // there may be typedefs nested within aggregates. in order for everything to work properly, these should be removed842 // as well843 1103 template<typename AggDecl> 844 AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) { 845 filter( aggDecl->members, isTypedef, true ); 846 return aggDecl; 847 } 848 849 template<typename AggDecl> 850 void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) { 1104 void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) { 851 1105 if ( typedefNames.count( aggDecl->get_name() ) == 0 ) { 852 Type * type = nullptr;1106 Type * type = nullptr; 853 1107 if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) { 854 1108 type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ); … … 860 1114 TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) ); 861 1115 typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel ); 862 } // if 863 } 864 865 void EliminateTypedef::premutate( StructDecl * structDecl ) { 1116 // add the implicit typedef to the AST 1117 declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) ); 1118 } // if 1119 } 1120 1121 template< typename AggDecl > 1122 void ReplaceTypedef::handleAggregate( AggDecl * aggr ) { 1123 SemanticErrorException errors; 1124 1125 ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore ); 1126 ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter ); 1127 declsToAddBefore.clear(); 1128 declsToAddAfter.clear(); 1129 1130 GuardScope( typedefNames ); 1131 GuardScope( typedeclNames ); 1132 mutateAll( aggr->parameters, * visitor ); 1133 1134 // unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body. 1135 for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) { 1136 if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); } 1137 1138 try { 1139 * i = maybeMutate( * i, * visitor ); 1140 } catch ( SemanticErrorException &e ) { 1141 errors.append( e ); 1142 } 1143 1144 if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); } 1145 } 1146 1147 if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); } 1148 if ( !errors.isEmpty() ) { throw errors; } 1149 } 1150 1151 void ReplaceTypedef::premutate( StructDecl * structDecl ) { 1152 visit_children = false; 866 1153 addImplicitTypedef( structDecl ); 867 } 868 869 870 Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) { 871 return handleAggregate( structDecl ); 872 } 873 874 void EliminateTypedef::premutate( UnionDecl * unionDecl ) { 1154 handleAggregate( structDecl ); 1155 } 1156 1157 void ReplaceTypedef::premutate( UnionDecl * unionDecl ) { 1158 visit_children = false; 875 1159 addImplicitTypedef( unionDecl ); 876 } 877 878 Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) { 879 return handleAggregate( unionDecl ); 880 } 881 882 void EliminateTypedef::premutate( EnumDecl * enumDecl ) { 1160 handleAggregate( unionDecl ); 1161 } 1162 1163 void ReplaceTypedef::premutate( EnumDecl * enumDecl ) { 883 1164 addImplicitTypedef( enumDecl ); 884 1165 } 885 1166 886 Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) { 887 return handleAggregate( enumDecl ); 888 } 889 890 Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) { 891 return handleAggregate( traitDecl ); 892 } 893 894 void EliminateTypedef::premutate( FunctionType * ) { 1167 void ReplaceTypedef::premutate( FunctionType * ) { 895 1168 GuardValue( inFunctionType ); 896 1169 inFunctionType = true; 1170 } 1171 1172 void ReplaceTypedef::premutate( TraitDecl * ) { 1173 GuardScope( typedefNames ); 1174 GuardScope( typedeclNames); 897 1175 } 898 1176 … … 939 1217 for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) { 940 1218 if ( i < args.size() ) { 941 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) );942 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );1219 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) ); 1220 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() ); 943 1221 } else if ( i == args.size() ) { 944 Type * defaultType = (* paramIter)->get_init();1222 Type * defaultType = (* paramIter)->get_init(); 945 1223 if ( defaultType ) { 946 1224 args.push_back( new TypeExpr( defaultType->clone() ) ); 947 sub.add( (* paramIter)->get_name(), defaultType->clone() );1225 sub.add( (* paramIter)->get_name(), defaultType->clone() ); 948 1226 } 949 1227 } … … 964 1242 } 965 1243 966 void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {1244 void CompoundLiteral::premutate( ObjectDecl * objectDecl ) { 967 1245 storageClasses = objectDecl->get_storageClasses(); 968 1246 } 969 1247 970 Expression * CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {1248 Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) { 971 1249 // transform [storage_class] ... (struct S){ 3, ... }; 972 1250 // into [storage_class] struct S temp = { 3, ... }; 973 1251 static UniqueName indexName( "_compLit" ); 974 1252 975 ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );1253 ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() ); 976 1254 compLitExpr->set_result( nullptr ); 977 1255 compLitExpr->set_initializer( nullptr ); … … 1011 1289 TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 1012 1290 // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false. 1013 ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );1291 ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) ); 1014 1292 deleteAll( retVals ); 1015 1293 retVals.clear(); … … 1018 1296 } 1019 1297 1298 void FixObjectType::fix( std::list< Declaration * > & translationUnit ) { 1299 PassVisitor<FixObjectType> fixer; 1300 acceptAll( translationUnit, fixer ); 1301 } 1302 1303 void FixObjectType::previsit( ObjectDecl * objDecl ) { 1304 Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer ); 1305 objDecl->set_type( new_type ); 1306 } 1307 1308 void FixObjectType::previsit( FunctionDecl * funcDecl ) { 1309 Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer ); 1310 funcDecl->set_type( new_type ); 1311 } 1312 1313 void FixObjectType::previsit( TypeDecl * typeDecl ) { 1314 if ( typeDecl->get_base() ) { 1315 Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer ); 1316 typeDecl->set_base( new_type ); 1317 } // if 1318 } 1319 1020 1320 void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) { 1021 1321 PassVisitor<ArrayLength> len; … … 1024 1324 1025 1325 void ArrayLength::previsit( ObjectDecl * objDecl ) { 1026 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 1027 if ( at->get_dimension() ) return; 1028 if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->get_init() ) ) { 1029 at->set_dimension( new ConstantExpr( Constant::from_ulong( init->get_initializers().size() ) ) ); 1030 } 1326 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) { 1327 if ( at->dimension ) return; 1328 if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->init ) ) { 1329 at->dimension = new ConstantExpr( Constant::from_ulong( init->initializers.size() ) ); 1330 } 1331 } 1332 } 1333 1334 void ArrayLength::previsit( ArrayType * type ) { 1335 if ( type->dimension ) { 1336 // need to resolve array dimensions early so that constructor code can correctly determine 1337 // if a type is a VLA (and hence whether its elements need to be constructed) 1338 ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); 1339 1340 // must re-evaluate whether a type is a VLA, now that more information is available 1341 // (e.g. the dimension may have been an enumerator, which was unknown prior to this step) 1342 type->isVarLen = ! InitTweak::isConstExpr( type->dimension ); 1031 1343 } 1032 1344 } … … 1062 1374 } 1063 1375 1064 void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) { 1065 if ( ! dereferenceOperator ) { 1066 if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) { 1067 FunctionType * ftype = funcDecl->get_functionType(); 1068 if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) { 1069 dereferenceOperator = funcDecl; 1376 namespace { 1377 /// Replaces enum types by int, and function/array types in function parameter and return 1378 /// lists by appropriate pointers 1379 struct EnumAndPointerDecay_new { 1380 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) { 1381 // set the type of each member of the enumeration to be EnumConstant 1382 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1383 // build new version of object with EnumConstant 1384 ast::ptr< ast::ObjectDecl > obj = 1385 enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1386 obj.get_and_mutate()->type = 1387 new ast::EnumInstType{ enumDecl->name, ast::CV::Const }; 1388 1389 // set into decl 1390 ast::EnumDecl * mut = mutate( enumDecl ); 1391 mut->members[i] = obj.get(); 1392 enumDecl = mut; 1393 } 1394 return enumDecl; 1395 } 1396 1397 static const ast::FunctionType * fixFunctionList( 1398 const ast::FunctionType * func, 1399 std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field, 1400 ast::ArgumentFlag isVarArgs = ast::FixedArgs 1401 ) { 1402 const auto & dwts = func->* field; 1403 unsigned nvals = dwts.size(); 1404 bool hasVoid = false; 1405 for ( unsigned i = 0; i < nvals; ++i ) { 1406 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) ); 1407 } 1408 1409 // the only case in which "void" is valid is where it is the only one in the list 1410 if ( hasVoid && ( nvals > 1 || isVarArgs ) ) { 1411 SemanticError( 1412 dwts.front()->location, func, "invalid type void in function type" ); 1413 } 1414 1415 // one void is the only thing in the list, remove it 1416 if ( hasVoid ) { 1417 func = ast::mutate_field( 1418 func, field, std::vector< ast::ptr< ast::DeclWithType > >{} ); 1419 } 1420 1421 return func; 1422 } 1423 1424 const ast::FunctionType * previsit( const ast::FunctionType * func ) { 1425 func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs ); 1426 return fixFunctionList( func, &ast::FunctionType::returns ); 1427 } 1428 }; 1429 1430 /// expand assertions from a trait instance, performing appropriate type variable substitutions 1431 void expandAssertions( 1432 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out 1433 ) { 1434 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) ); 1435 1436 // build list of trait members, substituting trait decl parameters for instance parameters 1437 ast::TypeSubstitution sub{ 1438 inst->base->params.begin(), inst->base->params.end(), inst->params.begin() }; 1439 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base 1440 for ( ast::ptr< ast::Decl > decl : inst->base->members ) { 1441 auto member = decl.strict_as< ast::DeclWithType >(); 1442 sub.apply( member ); 1443 out.emplace_back( member ); 1444 } 1445 } 1446 1447 /// Associates forward declarations of aggregates with their definitions 1448 class LinkReferenceToTypes_new final 1449 : public ast::WithSymbolTable, public ast::WithGuards, public 1450 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting { 1451 1452 // these maps of uses of forward declarations of types need to have the actual type 1453 // declaration switched in * after * they have been traversed. To enable this in the 1454 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it 1455 // before it is placed in the map, properly updating its parents in the usual traversal, 1456 // then can have the actual mutation applied later 1457 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >; 1458 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >; 1459 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >; 1460 1461 const CodeLocation & location; 1462 const ast::SymbolTable * localSymtab; 1463 1464 ForwardEnumsType forwardEnums; 1465 ForwardStructsType forwardStructs; 1466 ForwardUnionsType forwardUnions; 1467 1468 /// true if currently in a generic type body, so that type parameter instances can be 1469 /// renamed appropriately 1470 bool inGeneric = false; 1471 1472 public: 1473 /// contstruct using running symbol table 1474 LinkReferenceToTypes_new( const CodeLocation & loc ) 1475 : location( loc ), localSymtab( &symtab ) {} 1476 1477 /// construct using provided symbol table 1478 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms ) 1479 : location( loc ), localSymtab( &syms ) {} 1480 1481 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 1482 // ensure generic parameter instances are renamed like the base type 1483 if ( inGeneric && typeInst->base ) { 1484 typeInst = ast::mutate_field( 1485 typeInst, &ast::TypeInstType::name, typeInst->base->name ); 1486 } 1487 1488 if ( 1489 auto typeDecl = dynamic_cast< const ast::TypeDecl * >( 1490 localSymtab->lookupType( typeInst->name ) ) 1491 ) { 1492 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind ); 1493 } 1494 1495 return typeInst; 1496 } 1497 1498 const ast::Type * postvisit( const ast::EnumInstType * inst ) { 1499 const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name ); 1500 // not a semantic error if the enum is not found, just an implicit forward declaration 1501 if ( decl ) { 1502 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl ); 1503 } 1504 if ( ! decl || ! decl->body ) { 1505 // forward declaration 1506 auto mut = mutate( inst ); 1507 forwardEnums.emplace( inst->name, mut ); 1508 inst = mut; 1509 } 1510 return inst; 1511 } 1512 1513 void checkGenericParameters( const ast::ReferenceToType * inst ) { 1514 for ( const ast::Expr * param : inst->params ) { 1515 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { 1516 SemanticError( 1517 location, inst, "Expression parameters for generic types are currently " 1518 "unsupported: " ); 1070 1519 } 1071 1520 } 1072 1521 } 1073 } 1522 1523 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) { 1524 const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name ); 1525 // not a semantic error if the struct is not found, just an implicit forward declaration 1526 if ( decl ) { 1527 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl ); 1528 } 1529 if ( ! decl || ! decl->body ) { 1530 // forward declaration 1531 auto mut = mutate( inst ); 1532 forwardStructs.emplace( inst->name, mut ); 1533 inst = mut; 1534 } 1535 checkGenericParameters( inst ); 1536 return inst; 1537 } 1538 1539 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) { 1540 const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name ); 1541 // not a semantic error if the struct is not found, just an implicit forward declaration 1542 if ( decl ) { 1543 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl ); 1544 } 1545 if ( ! decl || ! decl->body ) { 1546 // forward declaration 1547 auto mut = mutate( inst ); 1548 forwardUnions.emplace( inst->name, mut ); 1549 inst = mut; 1550 } 1551 checkGenericParameters( inst ); 1552 return inst; 1553 } 1554 1555 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) { 1556 // handle other traits 1557 const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name ); 1558 if ( ! traitDecl ) { 1559 SemanticError( location, "use of undeclared trait " + traitInst->name ); 1560 } 1561 if ( traitDecl->params.size() != traitInst->params.size() ) { 1562 SemanticError( location, traitInst, "incorrect number of trait parameters: " ); 1563 } 1564 traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl ); 1565 1566 // need to carry over the "sized" status of each decl in the instance 1567 for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) { 1568 auto expr = traitInst->params[i].as< ast::TypeExpr >(); 1569 if ( ! expr ) { 1570 SemanticError( 1571 traitInst->params[i].get(), "Expression parameters for trait instances " 1572 "are currently unsupported: " ); 1573 } 1574 1575 if ( auto inst = expr->type.as< ast::TypeInstType >() ) { 1576 if ( traitDecl->params[i]->sized && ! inst->base->sized ) { 1577 // traitInst = ast::mutate_field_index( 1578 // traitInst, &ast::TraitInstType::params, i, 1579 // ... 1580 // ); 1581 ast::TraitInstType * mut = ast::mutate( traitInst ); 1582 ast::chain_mutate( mut->params[i] ) 1583 ( &ast::TypeExpr::type ) 1584 ( &ast::TypeInstType::base )->sized = true; 1585 traitInst = mut; 1586 } 1587 } 1588 } 1589 1590 return traitInst; 1591 } 1592 1593 void previsit( const ast::QualifiedType * ) { visit_children = false; } 1594 1595 const ast::Type * postvisit( const ast::QualifiedType * qualType ) { 1596 // linking only makes sense for the "oldest ancestor" of the qualified type 1597 return ast::mutate_field( 1598 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) ); 1599 } 1600 1601 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) { 1602 // visit enum members first so that the types of self-referencing members are updated 1603 // properly 1604 if ( ! enumDecl->body ) return enumDecl; 1605 1606 // update forward declarations to point here 1607 auto fwds = forwardEnums.equal_range( enumDecl->name ); 1608 if ( fwds.first != fwds.second ) { 1609 auto inst = fwds.first; 1610 do { 1611 // forward decl is stored * mutably * in map, can thus be updated 1612 inst->second->base = enumDecl; 1613 } while ( ++inst != fwds.second ); 1614 forwardEnums.erase( fwds.first, fwds.second ); 1615 } 1616 1617 // ensure that enumerator initializers are properly set 1618 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1619 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1620 if ( field->init ) { 1621 // need to resolve enumerator initializers early so that other passes that 1622 // determine if an expression is constexpr have appropriate information 1623 auto init = field->init.strict_as< ast::SingleInit >(); 1624 1625 enumDecl = ast::mutate_field_index( 1626 enumDecl, &ast::EnumDecl::members, i, 1627 ast::mutate_field( field, &ast::ObjectDecl::init, 1628 ast::mutate_field( init, &ast::SingleInit::value, 1629 ResolvExpr::findSingleExpression( 1630 init->value, new ast::BasicType{ ast::BasicType::SignedInt }, 1631 symtab ) ) ) ); 1632 } 1633 } 1634 1635 return enumDecl; 1636 } 1637 1638 /// rename generic type parameters uniquely so that they do not conflict with user defined 1639 /// function forall parameters, e.g. the T in Box and the T in f, below 1640 /// forall(otype T) 1641 /// struct Box { 1642 /// T x; 1643 /// }; 1644 /// forall(otype T) 1645 /// void f(Box(T) b) { 1646 /// ... 1647 /// } 1648 template< typename AggrDecl > 1649 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) { 1650 GuardValue( inGeneric ); 1651 inGeneric = ! aggr->params.empty(); 1652 1653 for ( unsigned i = 0; i < aggr->params.size(); ++i ) { 1654 const ast::TypeDecl * td = aggr->params[i]; 1655 1656 aggr = ast::mutate_field_index( 1657 aggr, &AggrDecl::params, i, 1658 ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) ); 1659 } 1660 return aggr; 1661 } 1662 1663 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) { 1664 return renameGenericParams( structDecl ); 1665 } 1666 1667 void postvisit( const ast::StructDecl * structDecl ) { 1668 // visit struct members first so that the types of self-referencing members are 1669 // updated properly 1670 if ( ! structDecl->body ) return; 1671 1672 // update forward declarations to point here 1673 auto fwds = forwardStructs.equal_range( structDecl->name ); 1674 if ( fwds.first != fwds.second ) { 1675 auto inst = fwds.first; 1676 do { 1677 // forward decl is stored * mutably * in map, can thus be updated 1678 inst->second->base = structDecl; 1679 } while ( ++inst != fwds.second ); 1680 forwardStructs.erase( fwds.first, fwds.second ); 1681 } 1682 } 1683 1684 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) { 1685 return renameGenericParams( unionDecl ); 1686 } 1687 1688 void postvisit( const ast::UnionDecl * unionDecl ) { 1689 // visit union members first so that the types of self-referencing members are updated 1690 // properly 1691 if ( ! unionDecl->body ) return; 1692 1693 // update forward declarations to point here 1694 auto fwds = forwardUnions.equal_range( unionDecl->name ); 1695 if ( fwds.first != fwds.second ) { 1696 auto inst = fwds.first; 1697 do { 1698 // forward decl is stored * mutably * in map, can thus be updated 1699 inst->second->base = unionDecl; 1700 } while ( ++inst != fwds.second ); 1701 forwardUnions.erase( fwds.first, fwds.second ); 1702 } 1703 } 1704 1705 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) { 1706 // set the "sized" status for the special "sized" trait 1707 if ( traitDecl->name == "sized" ) { 1708 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect " 1709 "number of parameters: %zd", traitDecl->params.size() ); 1710 1711 traitDecl = ast::mutate_field_index( 1712 traitDecl, &ast::TraitDecl::params, 0, 1713 ast::mutate_field( 1714 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) ); 1715 } 1716 1717 // move assertions from type parameters into the body of the trait 1718 std::vector< ast::ptr< ast::DeclWithType > > added; 1719 for ( const ast::TypeDecl * td : traitDecl->params ) { 1720 for ( const ast::DeclWithType * assn : td->assertions ) { 1721 auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1722 if ( inst ) { 1723 expandAssertions( inst, added ); 1724 } else { 1725 added.emplace_back( assn ); 1726 } 1727 } 1728 } 1729 if ( ! added.empty() ) { 1730 auto mut = mutate( traitDecl ); 1731 for ( const ast::DeclWithType * decl : added ) { 1732 mut->members.emplace_back( decl ); 1733 } 1734 traitDecl = mut; 1735 } 1736 1737 return traitDecl; 1738 } 1739 }; 1740 1741 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1742 /// each object and function declaration a unique ID 1743 class ForallPointerDecay_new { 1744 const CodeLocation & location; 1745 public: 1746 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {} 1747 1748 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) { 1749 // ensure that operator names only apply to functions or function pointers 1750 if ( 1751 CodeGen::isOperator( obj->name ) 1752 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() ) 1753 ) { 1754 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not " 1755 "a function or function pointer." ) ); 1756 } 1757 1758 // ensure object has unique ID 1759 if ( obj->uniqueId ) return obj; 1760 auto mut = mutate( obj ); 1761 mut->fixUniqueId(); 1762 return mut; 1763 } 1764 1765 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) { 1766 // ensure function has unique ID 1767 if ( func->uniqueId ) return func; 1768 auto mut = mutate( func ); 1769 mut->fixUniqueId(); 1770 return mut; 1771 } 1772 1773 /// Fix up assertions -- flattens assertion lists, removing all trait instances 1774 template< typename node_t, typename parent_t > 1775 static const node_t * forallFixer( 1776 const CodeLocation & loc, const node_t * node, 1777 ast::ParameterizedType::ForallList parent_t::* forallField 1778 ) { 1779 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) { 1780 const ast::TypeDecl * type = (node->* forallField)[i]; 1781 if ( type->assertions.empty() ) continue; 1782 1783 std::vector< ast::ptr< ast::DeclWithType > > asserts; 1784 asserts.reserve( type->assertions.size() ); 1785 1786 // expand trait instances into their members 1787 for ( const ast::DeclWithType * assn : type->assertions ) { 1788 auto traitInst = 1789 dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1790 if ( traitInst ) { 1791 // expand trait instance to all its members 1792 expandAssertions( traitInst, asserts ); 1793 } else { 1794 // pass other assertions through 1795 asserts.emplace_back( assn ); 1796 } 1797 } 1798 1799 // apply FixFunction to every assertion to check for invalid void type 1800 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) { 1801 bool isVoid = false; 1802 assn = fixFunction( assn, isVoid ); 1803 if ( isVoid ) { 1804 SemanticError( loc, node, "invalid type void in assertion of function " ); 1805 } 1806 } 1807 1808 // place mutated assertion list in node 1809 auto mut = mutate( type ); 1810 mut->assertions = move( asserts ); 1811 node = ast::mutate_field_index( node, forallField, i, mut ); 1812 } 1813 return node; 1814 } 1815 1816 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) { 1817 return forallFixer( location, ftype, &ast::FunctionType::forall ); 1818 } 1819 1820 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) { 1821 return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params ); 1822 } 1823 1824 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) { 1825 return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params ); 1826 } 1827 }; 1828 } // anonymous namespace 1829 1830 const ast::Type * validateType( 1831 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1832 ast::Pass< EnumAndPointerDecay_new > epc; 1833 ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab }; 1834 ast::Pass< ForallPointerDecay_new > fpd{ loc }; 1835 1836 return type->accept( epc )->accept( lrt )->accept( fpd ); 1837 } 1838 1074 1839 } // namespace SymTab 1075 1840 -
src/SymTab/Validate.h
r7951100 rb067d9b 19 19 #include <list> // for list 20 20 21 class Declaration; 22 class Type; 21 struct CodeLocation; 22 class Declaration; 23 class Type; 24 25 namespace ast { 26 class Type; 27 class SymbolTable; 28 } 23 29 24 30 namespace SymTab { … … 28 34 void validate( std::list< Declaration * > &translationUnit, bool doDebug = false ); 29 35 void validateType( Type *type, const Indexer *indexer ); 36 37 const ast::Type * validateType( 38 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ); 30 39 } // namespace SymTab 31 40 -
src/SymTab/module.mk
r7951100 rb067d9b 15 15 ############################################################################### 16 16 17 SRC += SymTab/Indexer.cc \ 18 SymTab/Mangler.cc \ 19 SymTab/Validate.cc \ 20 SymTab/FixFunction.cc \ 21 SymTab/Autogen.cc 17 SRC_SYMTAB = \ 18 SymTab/Autogen.cc \ 19 SymTab/FixFunction.cc \ 20 SymTab/Indexer.cc \ 21 SymTab/Mangler.cc \ 22 SymTab/ManglerCommon.cc \ 23 SymTab/Validate.cc 24 25 SRC += $(SRC_SYMTAB) 26 SRCDEMANGLE += $(SRC_SYMTAB) SymTab/Demangle.cc
Note:
See TracChangeset
for help on using the changeset viewer.