Changeset d4b6638
- Timestamp:
- Jun 5, 2019, 11:24:29 AM (4 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
- Children:
- 2a8f0c1, 300fbee
- Parents:
- 4741dfe (diff), 0e42794 (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
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Bitfield.hpp
r4741dfe rd4b6638 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu May 9 10:00:00 2019 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Thu May 910:00:00 201913 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 5 10:00:00 2019 13 // Update Count : 2 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <strings.h> // for ffs 18 #include <strings.h> // for ffs 19 #include <type_traits> // for is_unsigned 19 20 20 21 /// Make a type a bitfield. … … 24 25 template<typename T> 25 26 struct bitfield : public T { 26 static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size");27 27 using T::val; 28 28 using val_t = decltype(val); 29 static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size"); 30 static_assert(std::is_unsigned<val_t>::value, "Bitfield val field is not unsigned."); 29 31 30 32 constexpr bitfield() : T( 0 ) {} -
src/AST/Expr.cpp
r4741dfe rd4b6638 65 65 // base type 66 66 ret->result = base; 67 add_ lvalue( ret->result);67 add_qualifiers( ret->result, CV::Lvalue ); 68 68 } 69 69 } … … 165 165 genericSubsitution( aggregate->result ).apply( result ); 166 166 // ensure lvalue and appropriate restrictions from aggregate type 167 result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;167 add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue ); 168 168 } 169 169 … … 175 175 assert( var->get_type() ); 176 176 result = var->get_type(); 177 add_ lvalue( result);177 add_qualifiers( result, CV::Lvalue ); 178 178 } 179 179 … … 309 309 assert( t && i ); 310 310 result = t; 311 add_ lvalue( result);311 add_qualifiers( result, CV::Lvalue ); 312 312 } 313 313 … … 326 326 // like MemberExpr, TupleIndexExpr is always an lvalue 327 327 result = type->types[ index ]; 328 add_ lvalue( result);328 add_qualifiers( result, CV::Lvalue ); 329 329 } 330 330 -
src/AST/Node.hpp
r4741dfe rd4b6638 18 18 #include <cassert> 19 19 #include <iosfwd> 20 21 #include "Common/ErrorObjects.h" // for SemanticErrorException 20 22 21 23 namespace ast { … … 100 102 } 101 103 104 /// Call a visitor on a collection of nodes, throwing any exceptions when completed 105 template< typename Container > 106 void accept_each( const Container & c, Visitor & v ) { 107 SemanticErrorException errors; 108 for ( const auto & i : c ) { 109 try { 110 if ( i ) { 111 i->accept( v ); 112 } 113 } catch ( SemanticErrorException & e ) { 114 errors.append( e ); 115 } 116 } 117 if ( ! errors.isEmpty() ) { 118 throw errors; 119 } 120 } 121 102 122 /// Base class for the smart pointer types 103 123 /// should never really be used. … … 166 186 const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); } 167 187 188 /// wrapper for convenient access to strict_dynamic_cast 189 template<typename o_node_t> 190 const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); } 191 168 192 /// Returns a mutable version of the pointer in this node. 169 193 node_t * get_and_mutate(); -
src/AST/Pass.hpp
r4741dfe rd4b6638 33 33 #include "AST/Visitor.hpp" 34 34 35 #include " SymTab/Indexer.h"35 #include "AST/SymbolTable.hpp" 36 36 37 37 // Private prelude header, needed for some of the magic tricks this class pulls off … … 61 61 // postvisit/postmutate teminates. 62 62 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 63 // | With Indexer - provides indexer functionality (i.e. up-to-date symbol table)63 // | WithSymbolTable - provides symbol table functionality 64 64 //------------------------------------------------------------------------------------------------- 65 65 template< typename pass_t > … … 206 206 207 207 private: 208 /// Internal RAII guard for indexerfeatures209 struct guard_ indexer{210 guard_ indexer( Pass<pass_t> & pass ): pass( pass ) { __pass::indexer::enter(pass, 0); }211 ~guard_ indexer() { __pass::indexer::leave(pass, 0); }208 /// Internal RAII guard for symbol table features 209 struct guard_symtab { 210 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); } 211 ~guard_symtab() { __pass::symtab::leave(pass, 0); } 212 212 Pass<pass_t> & pass; 213 213 }; … … 294 294 }; 295 295 296 /// Use when the templated visitor should update the indexer297 struct With Indexer{298 Sym Tab::Indexer indexer;296 /// Use when the templated visitor should update the symbol table 297 struct WithSymbolTable { 298 SymbolTable symtab; 299 299 }; 300 300 } -
src/AST/Pass.impl.hpp
r4741dfe rd4b6638 398 398 VISIT( 399 399 { 400 guard_ indexerguard { *this };400 guard_symtab guard { *this }; 401 401 maybe_accept( node, &ObjectDecl::type ); 402 402 } … … 406 406 ) 407 407 408 __pass:: indexer::addId( pass, 0, node );408 __pass::symtab::addId( pass, 0, node ); 409 409 410 410 VISIT_END( DeclWithType, node ); … … 417 417 VISIT_START( node ); 418 418 419 __pass:: indexer::addId( pass, 0, node );419 __pass::symtab::addId( pass, 0, node ); 420 420 421 421 VISIT(maybe_accept( node, &FunctionDecl::withExprs );) 422 422 { 423 423 // with clause introduces a level of scope (for the with expression members). 424 // with clause exprs are added to the indexerbefore parameters so that parameters424 // with clause exprs are added to the symbol table before parameters so that parameters 425 425 // shadow with exprs and not the other way around. 426 guard_ indexerguard { *this };427 __pass:: indexer::addWith( pass, 0, node->withExprs, node );426 guard_symtab guard { *this }; 427 __pass::symtab::addWith( pass, 0, node->withExprs, node ); 428 428 { 429 guard_ indexerguard { *this };429 guard_symtab guard { *this }; 430 430 // implicit add __func__ identifier as specified in the C manual 6.4.2.2 431 431 static ast::ObjectDecl func( … … 436 436 ) 437 437 ); 438 __pass:: indexer::addId( pass, 0, &func );438 __pass::symtab::addId( pass, 0, &func ); 439 439 VISIT( 440 440 maybe_accept( node, &FunctionDecl::type ); … … 460 460 // make up a forward declaration and add it before processing the members 461 461 // needs to be on the heap because addStruct saves the pointer 462 __pass:: indexer::addStructFwd( pass, 0, node );463 464 VISIT({ 465 guard_ indexerguard { * this };462 __pass::symtab::addStructFwd( pass, 0, node ); 463 464 VISIT({ 465 guard_symtab guard { * this }; 466 466 maybe_accept( node, &StructDecl::params ); 467 467 maybe_accept( node, &StructDecl::members ); … … 469 469 470 470 // this addition replaces the forward declaration 471 __pass:: indexer::addStruct( pass, 0, node );471 __pass::symtab::addStruct( pass, 0, node ); 472 472 473 473 VISIT_END( Decl, node ); … … 481 481 482 482 // make up a forward declaration and add it before processing the members 483 __pass:: indexer::addUnionFwd( pass, 0, node );484 485 VISIT({ 486 guard_ indexerguard { * this };483 __pass::symtab::addUnionFwd( pass, 0, node ); 484 485 VISIT({ 486 guard_symtab guard { * this }; 487 487 maybe_accept( node, &UnionDecl::params ); 488 488 maybe_accept( node, &UnionDecl::members ); 489 489 }) 490 490 491 __pass:: indexer::addUnion( pass, 0, node );491 __pass::symtab::addUnion( pass, 0, node ); 492 492 493 493 VISIT_END( Decl, node ); … … 500 500 VISIT_START( node ); 501 501 502 __pass:: indexer::addEnum( pass, 0, node );502 __pass::symtab::addEnum( pass, 0, node ); 503 503 504 504 VISIT( … … 518 518 519 519 VISIT({ 520 guard_ indexerguard { *this };520 guard_symtab guard { *this }; 521 521 maybe_accept( node, &TraitDecl::params ); 522 522 maybe_accept( node, &TraitDecl::members ); 523 523 }) 524 524 525 __pass:: indexer::addTrait( pass, 0, node );525 __pass::symtab::addTrait( pass, 0, node ); 526 526 527 527 VISIT_END( Decl, node ); … … 535 535 536 536 VISIT({ 537 guard_ indexerguard { *this };537 guard_symtab guard { *this }; 538 538 maybe_accept( node, &TypeDecl::params ); 539 539 maybe_accept( node, &TypeDecl::base ); … … 543 543 // note that assertions come after the type is added to the symtab, since they are not part of the type proper 544 544 // and may depend on the type itself 545 __pass:: indexer::addType( pass, 0, node );545 __pass::symtab::addType( pass, 0, node ); 546 546 547 547 VISIT( … … 549 549 550 550 { 551 guard_ indexerguard { *this };551 guard_symtab guard { *this }; 552 552 maybe_accept( node, &TypeDecl::init ); 553 553 } … … 564 564 565 565 VISIT({ 566 guard_ indexerguard { *this };566 guard_symtab guard { *this }; 567 567 maybe_accept( node, &TypedefDecl::params ); 568 568 maybe_accept( node, &TypedefDecl::base ); 569 569 }) 570 570 571 __pass:: indexer::addType( pass, 0, node );571 __pass::symtab::addType( pass, 0, node ); 572 572 573 573 VISIT( maybe_accept( node, &TypedefDecl::assertions ); ) … … 611 611 // do not enter a new scope if inFunction is true - needs to check old state before the assignment 612 612 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() { 613 if ( ! inFunction ) __pass:: indexer::enter(pass, 0);613 if ( ! inFunction ) __pass::symtab::enter(pass, 0); 614 614 }, [this, inFunction = this->inFunction]() { 615 if ( ! inFunction ) __pass:: indexer::leave(pass, 0);615 if ( ! inFunction ) __pass::symtab::leave(pass, 0); 616 616 }); 617 617 ValueGuard< bool > guard2( inFunction ); … … 669 669 VISIT({ 670 670 // if statements introduce a level of scope (for the initialization) 671 guard_ indexerguard { *this };671 guard_symtab guard { *this }; 672 672 maybe_accept( node, &IfStmt::inits ); 673 673 maybe_accept( node, &IfStmt::cond ); … … 687 687 VISIT({ 688 688 // while statements introduce a level of scope (for the initialization) 689 guard_ indexerguard { *this };689 guard_symtab guard { *this }; 690 690 maybe_accept( node, &WhileStmt::inits ); 691 691 maybe_accept( node, &WhileStmt::cond ); … … 704 704 VISIT({ 705 705 // for statements introduce a level of scope (for the initialization) 706 guard_ indexerguard { *this };706 guard_symtab guard { *this }; 707 707 maybe_accept( node, &ForStmt::inits ); 708 708 maybe_accept( node, &ForStmt::cond ); … … 800 800 VISIT({ 801 801 // catch statements introduce a level of scope (for the caught exception) 802 guard_ indexerguard { *this };802 guard_symtab guard { *this }; 803 803 maybe_accept( node, &CatchStmt::decl ); 804 804 maybe_accept( node, &CatchStmt::cond ); … … 901 901 { 902 902 // catch statements introduce a level of scope (for the caught exception) 903 guard_ indexerguard { *this };904 __pass:: indexer::addWith( pass, 0, node->exprs, node );903 guard_symtab guard { *this }; 904 __pass::symtab::addWith( pass, 0, node->exprs, node ); 905 905 maybe_accept( node, &WithStmt::stmt ); 906 906 } … … 953 953 VISIT( 954 954 { 955 guard_ indexerguard { *this };955 guard_symtab guard { *this }; 956 956 maybe_accept( node, &ApplicationExpr::result ); 957 957 } … … 971 971 VISIT( 972 972 { 973 guard_ indexerguard { *this };973 guard_symtab guard { *this }; 974 974 maybe_accept( node, &UntypedExpr::result ); 975 975 } … … 988 988 989 989 VISIT({ 990 guard_ indexerguard { *this };990 guard_symtab guard { *this }; 991 991 maybe_accept( node, &NameExpr::result ); 992 992 }) … … 1002 1002 1003 1003 VISIT({ 1004 guard_ indexerguard { *this };1004 guard_symtab guard { *this }; 1005 1005 maybe_accept( node, &CastExpr::result ); 1006 1006 } … … 1018 1018 1019 1019 VISIT({ 1020 guard_ indexerguard { *this };1020 guard_symtab guard { *this }; 1021 1021 maybe_accept( node, &KeywordCastExpr::result ); 1022 1022 } … … 1034 1034 1035 1035 VISIT({ 1036 guard_ indexerguard { *this };1036 guard_symtab guard { *this }; 1037 1037 maybe_accept( node, &VirtualCastExpr::result ); 1038 1038 } … … 1050 1050 1051 1051 VISIT({ 1052 guard_ indexerguard { *this };1052 guard_symtab guard { *this }; 1053 1053 maybe_accept( node, &AddressExpr::result ); 1054 1054 } … … 1066 1066 1067 1067 VISIT({ 1068 guard_ indexerguard { *this };1068 guard_symtab guard { *this }; 1069 1069 maybe_accept( node, &LabelAddressExpr::result ); 1070 1070 }) … … 1080 1080 1081 1081 VISIT({ 1082 guard_ indexerguard { *this };1082 guard_symtab guard { *this }; 1083 1083 maybe_accept( node, &UntypedMemberExpr::result ); 1084 1084 } … … 1097 1097 1098 1098 VISIT({ 1099 guard_ indexerguard { *this };1099 guard_symtab guard { *this }; 1100 1100 maybe_accept( node, &MemberExpr::result ); 1101 1101 } … … 1113 1113 1114 1114 VISIT({ 1115 guard_ indexerguard { *this };1115 guard_symtab guard { *this }; 1116 1116 maybe_accept( node, &VariableExpr::result ); 1117 1117 }) … … 1127 1127 1128 1128 VISIT({ 1129 guard_ indexerguard { *this };1129 guard_symtab guard { *this }; 1130 1130 maybe_accept( node, &ConstantExpr::result ); 1131 1131 }) … … 1141 1141 1142 1142 VISIT({ 1143 guard_ indexerguard { *this };1143 guard_symtab guard { *this }; 1144 1144 maybe_accept( node, &SizeofExpr::result ); 1145 1145 } … … 1161 1161 1162 1162 VISIT({ 1163 guard_ indexerguard { *this };1163 guard_symtab guard { *this }; 1164 1164 maybe_accept( node, &AlignofExpr::result ); 1165 1165 } … … 1181 1181 1182 1182 VISIT({ 1183 guard_ indexerguard { *this };1183 guard_symtab guard { *this }; 1184 1184 maybe_accept( node, &UntypedOffsetofExpr::result ); 1185 1185 } … … 1197 1197 1198 1198 VISIT({ 1199 guard_ indexerguard { *this };1199 guard_symtab guard { *this }; 1200 1200 maybe_accept( node, &OffsetofExpr::result ); 1201 1201 } … … 1213 1213 1214 1214 VISIT({ 1215 guard_ indexerguard { *this };1215 guard_symtab guard { *this }; 1216 1216 maybe_accept( node, &OffsetPackExpr::result ); 1217 1217 } … … 1229 1229 1230 1230 VISIT({ 1231 guard_ indexerguard { *this };1231 guard_symtab guard { *this }; 1232 1232 maybe_accept( node, &LogicalExpr::result ); 1233 1233 } … … 1246 1246 1247 1247 VISIT({ 1248 guard_ indexerguard { *this };1248 guard_symtab guard { *this }; 1249 1249 maybe_accept( node, &ConditionalExpr::result ); 1250 1250 } … … 1264 1264 1265 1265 VISIT({ 1266 guard_ indexerguard { *this };1266 guard_symtab guard { *this }; 1267 1267 maybe_accept( node, &CommaExpr::result ); 1268 1268 } … … 1281 1281 1282 1282 VISIT({ 1283 guard_ indexerguard { *this };1283 guard_symtab guard { *this }; 1284 1284 maybe_accept( node, &TypeExpr::result ); 1285 1285 } … … 1297 1297 1298 1298 VISIT({ 1299 guard_ indexerguard { *this };1299 guard_symtab guard { *this }; 1300 1300 maybe_accept( node, &AsmExpr::result ); 1301 1301 } … … 1315 1315 1316 1316 VISIT({ 1317 guard_ indexerguard { *this };1317 guard_symtab guard { *this }; 1318 1318 maybe_accept( node, &ImplicitCopyCtorExpr::result ); 1319 1319 } … … 1331 1331 1332 1332 VISIT({ 1333 guard_ indexerguard { *this };1333 guard_symtab guard { *this }; 1334 1334 maybe_accept( node, &ConstructorExpr::result ); 1335 1335 } … … 1347 1347 1348 1348 VISIT({ 1349 guard_ indexerguard { *this };1349 guard_symtab guard { *this }; 1350 1350 maybe_accept( node, &CompoundLiteralExpr::result ); 1351 1351 } … … 1363 1363 1364 1364 VISIT({ 1365 guard_ indexerguard { *this };1365 guard_symtab guard { *this }; 1366 1366 maybe_accept( node, &RangeExpr::result ); 1367 1367 } … … 1380 1380 1381 1381 VISIT({ 1382 guard_ indexerguard { *this };1382 guard_symtab guard { *this }; 1383 1383 maybe_accept( node, &UntypedTupleExpr::result ); 1384 1384 } … … 1396 1396 1397 1397 VISIT({ 1398 guard_ indexerguard { *this };1398 guard_symtab guard { *this }; 1399 1399 maybe_accept( node, &TupleExpr::result ); 1400 1400 } … … 1412 1412 1413 1413 VISIT({ 1414 guard_ indexerguard { *this };1414 guard_symtab guard { *this }; 1415 1415 maybe_accept( node, &TupleIndexExpr::result ); 1416 1416 } … … 1428 1428 1429 1429 VISIT({ 1430 guard_ indexerguard { *this };1430 guard_symtab guard { *this }; 1431 1431 maybe_accept( node, &TupleAssignExpr::result ); 1432 1432 } … … 1454 1454 1455 1455 { 1456 guard_ indexerguard { *this };1456 guard_symtab guard { *this }; 1457 1457 maybe_accept( node, &StmtExpr::result ); 1458 1458 } … … 1472 1472 1473 1473 VISIT({ 1474 guard_ indexerguard { *this };1474 guard_symtab guard { *this }; 1475 1475 maybe_accept( node, &UniqueExpr::result ); 1476 1476 } … … 1488 1488 1489 1489 VISIT({ 1490 guard_ indexerguard { *this };1490 guard_symtab guard { *this }; 1491 1491 maybe_accept( node, &UntypedInitExpr::result ); 1492 1492 } … … 1505 1505 1506 1506 VISIT({ 1507 guard_ indexerguard { *this };1507 guard_symtab guard { *this }; 1508 1508 maybe_accept( node, &InitExpr::result ); 1509 1509 } … … 1522 1522 1523 1523 VISIT({ 1524 guard_ indexerguard { *this };1524 guard_symtab guard { *this }; 1525 1525 maybe_accept( node, &DeletedExpr::result ); 1526 1526 } … … 1539 1539 1540 1540 VISIT({ 1541 guard_ indexerguard { *this };1541 guard_symtab guard { *this }; 1542 1542 maybe_accept( node, &DefaultArgExpr::result ); 1543 1543 } … … 1555 1555 1556 1556 VISIT({ 1557 guard_ indexerguard { *this };1557 guard_symtab guard { *this }; 1558 1558 maybe_accept( node, &GenericExpr::result ); 1559 1559 } … … 1566 1566 const Type * type = nullptr; 1567 1567 if( assoc.type ) { 1568 guard_ indexerguard { *this };1568 guard_symtab guard { *this }; 1569 1569 type = assoc.type->accept( *this ); 1570 1570 if( type != assoc.type ) mutated = true; … … 1682 1682 VISIT_START( node ); 1683 1683 1684 __pass:: indexer::addStruct( pass, 0, node->name );1685 1686 VISIT({ 1687 guard_ indexerguard { *this };1684 __pass::symtab::addStruct( pass, 0, node->name ); 1685 1686 VISIT({ 1687 guard_symtab guard { *this }; 1688 1688 maybe_accept( node, &StructInstType::forall ); 1689 1689 maybe_accept( node, &StructInstType::params ); … … 1699 1699 VISIT_START( node ); 1700 1700 1701 __pass:: indexer::addStruct( pass, 0, node->name );1701 __pass::symtab::addStruct( pass, 0, node->name ); 1702 1702 1703 1703 { 1704 guard_ indexerguard { *this };1704 guard_symtab guard { *this }; 1705 1705 maybe_accept( node, &UnionInstType::forall ); 1706 1706 maybe_accept( node, &UnionInstType::params ); … … 1893 1893 std::unordered_map< std::string, ast::ptr< ast::Type > > new_map; 1894 1894 for ( const auto & p : node->typeEnv ) { 1895 guard_ indexerguard { *this };1895 guard_symtab guard { *this }; 1896 1896 auto new_node = p.second->accept( *this ); 1897 1897 if (new_node != p.second) mutated = false; … … 1909 1909 std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map; 1910 1910 for ( const auto & p : node->varEnv ) { 1911 guard_ indexerguard { *this };1911 guard_symtab guard { *this }; 1912 1912 auto new_node = p.second->accept( *this ); 1913 1913 if (new_node != p.second) mutated = false; -
src/AST/Pass.proto.hpp
r4741dfe rd4b6638 265 265 }; 266 266 267 // Finally certain pass desire an up to date indexerautomatically268 // detect the presence of a member name indexerand call all the members appropriately269 namespace indexer{267 // Finally certain pass desire an up to date symbol table automatically 268 // detect the presence of a member name `symtab` and call all the members appropriately 269 namespace symtab { 270 270 // Some simple scoping rules 271 271 template<typename pass_t> 272 static inline auto enter( pass_t & pass, int ) -> decltype( pass. indexer.enterScope(), void() ) {273 pass. indexer.enterScope();272 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) { 273 pass.symtab.enterScope(); 274 274 } 275 275 … … 278 278 279 279 template<typename pass_t> 280 static inline auto leave( pass_t & pass, int ) -> decltype( pass. indexer.leaveScope(), void() ) {281 pass. indexer.leaveScope();280 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) { 281 pass.symtab.leaveScope(); 282 282 } 283 283 … … 285 285 static inline auto leave( pass_t &, long ) {} 286 286 287 // The indexerhas 2 kind of functions mostly, 1 argument and 2 arguments287 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 288 288 // Create macro to condense these common patterns 289 #define INDEXER_FUNC1( func, type ) \289 #define SYMTAB_FUNC1( func, type ) \ 290 290 template<typename pass_t> \ 291 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass. indexer.func( arg ), void() ) {\292 pass. indexer.func( arg ); \291 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\ 292 pass.symtab.func( arg ); \ 293 293 } \ 294 294 \ … … 296 296 static inline void func( pass_t &, long, type ) {} 297 297 298 #define INDEXER_FUNC2( func, type1, type2 ) \298 #define SYMTAB_FUNC2( func, type1, type2 ) \ 299 299 template<typename pass_t> \ 300 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass. indexer.func( arg1, arg2 ), void () ) {\301 pass. indexer.func( arg1, arg2 ); \300 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\ 301 pass.symtab.func( arg1, arg2 ); \ 302 302 } \ 303 303 \ … … 305 305 static inline void func( pass_t &, long, type1, type2 ) {} 306 306 307 INDEXER_FUNC1( addId , const DeclWithType * );308 INDEXER_FUNC1( addType , const NamedTypeDecl * );309 INDEXER_FUNC1( addStruct , const StructDecl * );310 INDEXER_FUNC1( addEnum , const EnumDecl * );311 INDEXER_FUNC1( addUnion , const UnionDecl * );312 INDEXER_FUNC1( addTrait , const TraitDecl * );313 INDEXER_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node * );307 SYMTAB_FUNC1( addId , const DeclWithType * ); 308 SYMTAB_FUNC1( addType , const NamedTypeDecl * ); 309 SYMTAB_FUNC1( addStruct , const StructDecl * ); 310 SYMTAB_FUNC1( addEnum , const EnumDecl * ); 311 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 312 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 313 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node * ); 314 314 315 315 // A few extra functions have more complicated behaviour, they are hand written 316 316 template<typename pass_t> 317 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass. indexer.addStruct( decl ), void() ) {317 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) { 318 318 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 319 319 fwd->params = decl->params; 320 pass. indexer.addStruct( fwd );320 pass.symtab.addStruct( fwd ); 321 321 } 322 322 … … 325 325 326 326 template<typename pass_t> 327 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass. indexer.addUnion( decl ), void() ) {327 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) { 328 328 UnionDecl * fwd = new UnionDecl( decl->location, decl->name ); 329 329 fwd->params = decl->params; 330 pass. indexer.addUnion( fwd );330 pass.symtab.addUnion( fwd ); 331 331 } 332 332 … … 335 335 336 336 template<typename pass_t> 337 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass. indexer.addStruct( str ), void() ) {338 if ( ! pass. indexer.lookupStruct( str ) ) {339 pass. indexer.addStruct( str );337 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) { 338 if ( ! pass.symtab.lookupStruct( str ) ) { 339 pass.symtab.addStruct( str ); 340 340 } 341 341 } … … 345 345 346 346 template<typename pass_t> 347 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass. indexer.addUnion( str ), void() ) {348 if ( ! pass. indexer.lookupUnion( str ) ) {349 pass. indexer.addUnion( str );347 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) { 348 if ( ! pass.symtab.lookupUnion( str ) ) { 349 pass.symtab.addUnion( str ); 350 350 } 351 351 } … … 354 354 static inline void addUnion( pass_t &, long, const std::string & ) {} 355 355 356 #undef INDEXER_FUNC1357 #undef INDEXER_FUNC2356 #undef SYMTAB_FUNC1 357 #undef SYMTAB_FUNC2 358 358 }; 359 359 }; -
src/AST/SymbolTable.hpp
r4741dfe rd4b6638 123 123 void addType( const NamedTypeDecl * decl ); 124 124 /// Adds a struct declaration to the symbol table by name 125 void addStruct( const std::string & id );125 void addStruct( const std::string & id ); 126 126 /// Adds a struct declaration to the symbol table 127 127 void addStruct( const StructDecl * decl ); 128 128 /// Adds an enum declaration to the symbol table 129 void addEnum( const EnumDecl * decl );129 void addEnum( const EnumDecl * decl ); 130 130 /// Adds a union declaration to the symbol table by name 131 void addUnion( const std::string & id );131 void addUnion( const std::string & id ); 132 132 /// Adds a union declaration to the symbol table 133 133 void addUnion( const UnionDecl * decl ); -
src/AST/Type.hpp
r4741dfe rd4b6638 77 77 }; 78 78 79 /// Set the `is_lvalue` qualifieron this type, cloning only if necessary79 /// Clear/reset the qualifiers on this type, cloning only if necessary 80 80 template< enum Node::ref_type ref_t > 81 void add_lvalue( ptr_base< Type, ref_t > & p) {82 if ( ! p->qualifiers.is_lvalue ) p.get_and_mutate()->qualifiers.is_lvalue = true;81 void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) { 82 if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q; 83 83 } 84 84 85 /// Clear the qualifiers onthis type, cloning only if necessary85 /// Add the specified qualifiers to this type, cloning only if necessary 86 86 template< enum Node::ref_type ref_t > 87 void clear_qualifiers( ptr_base< Type, ref_t > & p ) { 88 if ( p->qualifiers != CV::Qualifiers{} ) p.get_and_mutate()->qualifiers = CV::Qualifiers{}; 87 void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) { 88 if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q; 89 } 90 91 /// Remove the specified qualifiers from this type, cloning only if necessary 92 template< enum Node::ref_type ref_t > 93 void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) { 94 if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q; 89 95 } 90 96 -
src/AST/TypeEnvironment.cpp
r4741dfe rd4b6638 235 235 } 236 236 237 /// true if a type is a function type 238 bool isFtype( const Type * type ) { 239 if ( dynamic_cast< const FunctionType * >( type ) ) { 240 return true; 241 } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) { 242 return typeInst->kind == TypeVar::Ftype; 243 } else return false; 244 } 245 237 246 namespace { 238 /// true if a type is a function type239 bool isFtype( const Type * type ) {240 if ( dynamic_cast< const FunctionType * >( type ) ) {241 return true;242 } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) {243 return typeInst->kind == TypeVar::Ftype;244 } else return false;245 }246 247 247 /// true if the given type can be bound to the given type variable 248 248 bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) { … … 285 285 ptr<Type> common; 286 286 ptr<Type> newType = it->bound; 287 newType.get_and_mutate()->qualifiers = typeInst->qualifiers;287 reset_qualifiers( newType, typeInst->qualifiers ); 288 288 if ( unifyInexact( 289 289 newType, target, *this, need, have, open, … … 291 291 if ( common ) { 292 292 it->bound = std::move(common); 293 clear_qualifiers( it->bound );293 reset_qualifiers( it->bound ); 294 294 } 295 295 } else return false; 296 296 } else { 297 297 it->bound = std::move(target); 298 clear_qualifiers( it->bound );298 reset_qualifiers( it->bound ); 299 299 it->allowWidening = widen.first && widen.second; 300 300 } … … 351 351 if ( common ) { 352 352 c1->bound = std::move(common); 353 clear_qualifiers( c1->bound );353 reset_qualifiers( c1->bound ); 354 354 } 355 355 c1->data.isComplete |= data.isComplete; … … 411 411 if ( common ) { 412 412 to.bound = std::move(common); 413 clear_qualifiers( to.bound );413 reset_qualifiers( to.bound ); 414 414 } 415 415 } else return false; // cannot unify -
src/AST/TypeEnvironment.hpp
r4741dfe rd4b6638 112 112 EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d ) 113 113 : vars{ v }, bound( b ), allowWidening( w ), data( d ) { 114 clear_qualifiers( bound );114 reset_qualifiers( bound ); 115 115 } 116 116 -
src/AST/porting.md
r4741dfe rd4b6638 109 109 * `SymTab::Indexer` => `ast::SymbolTable` 110 110 * `SymTab/Indexer.{h,cc}` => `AST/SymbolTable.{hpp,cpp}` 111 * **TODO**`WithIndexer` => `WithSymbolTable`111 * `WithIndexer` => `WithSymbolTable` 112 112 * `indexer` => `symTab` 113 113 * `IdData::deleteStmt` => `IdData::deleter` 114 114 * `lookupId()` now returns a vector rather than an out-param list 115 116 115 * To avoid name collisions: 116 * `SymTab::Mangler` => `Mangle` 117 117 * `ResolvExpr::TypeEnvironment` => `ast::TypeEnvironment` 118 118 * in `AST/TypeEnvironment.hpp` -
src/ResolvExpr/CommonType.cc
r4741dfe rd4b6638 18 18 #include <utility> // for pair 19 19 20 #include "AST/Decl.hpp" 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" 21 23 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 35 37 36 38 namespace ResolvExpr { 37 struct CommonType : public WithShortCircuiting {38 CommonType ( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );39 struct CommonType_old : public WithShortCircuiting { 40 CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 39 41 Type *get_result() const { return result; } 40 42 … … 94 96 95 97 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 96 PassVisitor<CommonType > visitor( type2, widenFirst, widenSecond, indexer, env, openVars );98 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 97 99 98 100 int depth1 = type1->referenceDepth(); … … 176 178 } 177 179 178 const ast::Type * commonType(179 const ast::Type * type1, const ast::Type * type2, WidenMode widen,180 const ast::SymbolTable & symtab, ast::TypeEnvironment & env,181 const ast::OpenVarSet & open ) {182 #warning unimplemented183 (void)type1; (void)type2; (void)widen; (void)symtab; (void)env; (void)open;184 assert(false);185 return nullptr;186 }187 188 180 // GENERATED START, DO NOT EDIT 189 181 // GENERATED BY BasicTypes-gen.cc … … 493 485 ); 494 486 495 CommonType ::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )487 CommonType_old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) 496 488 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) { 497 489 } 498 490 499 void CommonType ::postvisit( VoidType * ) {}500 501 void CommonType ::postvisit( BasicType *basicType ) {491 void CommonType_old::postvisit( VoidType * ) {} 492 493 void CommonType_old::postvisit( BasicType *basicType ) { 502 494 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 503 495 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 515 507 516 508 template< typename Pointer > 517 void CommonType ::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {509 void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 518 510 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 519 511 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 528 520 } 529 521 530 void CommonType ::postvisit( PointerType *pointerType ) {522 void CommonType_old::postvisit( PointerType *pointerType ) { 531 523 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 532 524 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 563 555 } 564 556 565 void CommonType ::postvisit( ArrayType * ) {}566 567 void CommonType ::postvisit( ReferenceType *refType ) {557 void CommonType_old::postvisit( ArrayType * ) {} 558 559 void CommonType_old::postvisit( ReferenceType *refType ) { 568 560 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 569 561 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 600 592 } 601 593 602 void CommonType ::postvisit( FunctionType * ) {}603 void CommonType ::postvisit( StructInstType * ) {}604 void CommonType ::postvisit( UnionInstType * ) {}605 606 void CommonType ::postvisit( EnumInstType *enumInstType ) {594 void CommonType_old::postvisit( FunctionType * ) {} 595 void CommonType_old::postvisit( StructInstType * ) {} 596 void CommonType_old::postvisit( UnionInstType * ) {} 597 598 void CommonType_old::postvisit( EnumInstType *enumInstType ) { 607 599 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 608 600 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType … … 611 603 } 612 604 613 void CommonType ::postvisit( TraitInstType * ) {614 } 615 616 void CommonType ::postvisit( TypeInstType *inst ) {605 void CommonType_old::postvisit( TraitInstType * ) { 606 } 607 608 void CommonType_old::postvisit( TypeInstType *inst ) { 617 609 if ( widenFirst ) { 618 610 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 636 628 } 637 629 638 void CommonType ::postvisit( TupleType * ) {}639 void CommonType ::postvisit( VarArgsType * ) {}640 641 void CommonType ::postvisit( ZeroType *zeroType ) {630 void CommonType_old::postvisit( TupleType * ) {} 631 void CommonType_old::postvisit( VarArgsType * ) {} 632 633 void CommonType_old::postvisit( ZeroType *zeroType ) { 642 634 if ( widenFirst ) { 643 635 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 653 645 } 654 646 655 void CommonType ::postvisit( OneType *oneType ) {647 void CommonType_old::postvisit( OneType *oneType ) { 656 648 if ( widenFirst ) { 657 649 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 666 658 } 667 659 } 660 661 class CommonType_new final : public ast::WithShortCircuiting { 662 const ast::Type * type2; 663 WidenMode widen; 664 const ast::SymbolTable & symtab; 665 ast::TypeEnvironment & tenv; 666 const ast::OpenVarSet & open; 667 public: 668 ast::ptr< ast::Type > result; 669 670 CommonType_new( 671 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st, 672 ast::TypeEnvironment & env, const ast::OpenVarSet & o ) 673 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {} 674 675 void previsit( const ast::Node * ) { visit_children = false; } 676 677 void postvisit( const ast::VoidType * ) {} 678 679 void postvisit( const ast::BasicType * basic ) { 680 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 681 #warning remove casts when `commonTypes` moved to new AST 682 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 683 if ( 684 ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers ) 685 || widen.first ) 686 && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers ) 687 || widen.second ) 688 ) { 689 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 690 } 691 } else if ( 692 dynamic_cast< const ast::EnumInstType * >( type2 ) 693 || dynamic_cast< const ast::ZeroType * >( type2 ) 694 || dynamic_cast< const ast::OneType * >( type2 ) 695 ) { 696 #warning remove casts when `commonTypes` moved to new AST 697 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ]; 698 if ( 699 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 700 || widen.first ) 701 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 702 || widen.second ) 703 ) { 704 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 705 } 706 } 707 } 708 709 private: 710 template< typename Pointer > 711 void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) { 712 const ast::Type * base = oPtr->base; 713 if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) { 714 auto entry = open.find( var->name ); 715 if ( entry != open.end() ) { 716 ast::AssertionSet need, have; 717 if ( ! tenv.bindVar( 718 var, voidPtr->base, entry->second, need, have, open, widen, symtab ) 719 ) return; 720 } 721 } 722 result = voidPtr; 723 add_qualifiers( result, oPtr->qualifiers ); 724 } 725 726 public: 727 void postvisit( const ast::PointerType * pointer ) { 728 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 729 if ( 730 widen.first 731 && pointer2->base.as< ast::VoidType >() 732 && ! ast::isFtype( pointer->base ) 733 ) { 734 getCommonWithVoidPointer( pointer2, pointer ); 735 } else if ( 736 widen.second 737 && pointer->base.as< ast::VoidType >() 738 && ! ast::isFtype( pointer2->base ) 739 ) { 740 getCommonWithVoidPointer( pointer, pointer2 ); 741 } else if ( 742 ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first ) 743 && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second ) 744 ) { 745 ast::CV::Qualifiers q1 = pointer->base->qualifiers; 746 ast::CV::Qualifiers q2 = pointer2->base->qualifiers; 747 748 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 749 // pointer{,2}->base are unchanged 750 ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base }; 751 reset_qualifiers( t1 ); 752 reset_qualifiers( t2 ); 753 754 ast::AssertionSet have, need; 755 ast::OpenVarSet newOpen{ open }; 756 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 757 result = pointer; 758 if ( q1.val != q2.val ) { 759 // reset result->base->qualifiers to be union of two base qualifiers 760 strict_dynamic_cast< ast::PointerType * >( 761 result.get_and_mutate() 762 )->base.get_and_mutate()->qualifiers = q1 | q2; 763 } 764 } 765 } 766 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 767 result = pointer; 768 add_qualifiers( result, type2->qualifiers ); 769 } 770 } 771 772 void postvisit( const ast::ArrayType * ) {} 773 774 void postvisit( const ast::ReferenceType * ref ) { 775 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 776 if ( 777 widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base ) 778 ) { 779 getCommonWithVoidPointer( ref2, ref ); 780 } else if ( 781 widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base ) 782 ) { 783 getCommonWithVoidPointer( ref, ref2 ); 784 } else if ( 785 ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first ) 786 && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second ) 787 ) { 788 ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers; 789 790 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 791 // ref{,2}->base are unchanged 792 ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base }; 793 reset_qualifiers( t1 ); 794 reset_qualifiers( t2 ); 795 796 ast::AssertionSet have, need; 797 ast::OpenVarSet newOpen{ open }; 798 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 799 result = ref; 800 if ( q1.val != q2.val ) { 801 // reset result->base->qualifiers to be union of two base qualifiers 802 strict_dynamic_cast< ast::ReferenceType * >( 803 result.get_and_mutate() 804 )->base.get_and_mutate()->qualifiers = q1 | q2; 805 } 806 } 807 } 808 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 809 result = ref; 810 add_qualifiers( result, type2->qualifiers ); 811 } 812 } 813 814 void postvisit( const ast::FunctionType * ) {} 815 816 void postvisit( const ast::StructInstType * ) {} 817 818 void postvisit( const ast::UnionInstType * ) {} 819 820 void postvisit( const ast::EnumInstType * enumInst ) { 821 if ( 822 dynamic_cast< const ast::BasicType * >( type2 ) 823 || dynamic_cast< const ast::ZeroType * >( type2 ) 824 || dynamic_cast< const ast::OneType * >( type2 ) 825 ) { 826 // reuse BasicType/EnumInstType common type by swapping 827 result = commonType( type2, enumInst, widen, symtab, tenv, open ); 828 } 829 } 830 831 void postvisit( const ast::TraitInstType * ) {} 832 833 void postvisit( const ast::TypeInstType * inst ) { 834 if ( ! widen.first ) return; 835 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 836 if ( const ast::Type * base = 837 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base 838 ) { 839 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers; 840 841 // force t{1,2} to be cloned if their qualifiers must be mutated 842 ast::ptr< ast::Type > t1{ base }, t2{ type2 }; 843 reset_qualifiers( t1, q1 ); 844 reset_qualifiers( t2 ); 845 846 ast::AssertionSet have, need; 847 ast::OpenVarSet newOpen{ open }; 848 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 849 result = type2; 850 reset_qualifiers( result, q1 | q2 ); 851 } 852 } 853 } 854 } 855 856 void postvisit( const ast::TupleType * ) {} 857 858 void postvisit( const ast::VarArgsType * ) {} 859 860 void postvisit( const ast::ZeroType * zero ) { 861 if ( ! widen.first ) return; 862 if ( 863 dynamic_cast< const ast::BasicType * >( type2 ) 864 || dynamic_cast< const ast::PointerType * >( type2 ) 865 || dynamic_cast< const ast::EnumInstType * >( type2 ) 866 ) { 867 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 868 result = type2; 869 add_qualifiers( result, zero->qualifiers ); 870 } 871 } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) { 872 result = new ast::BasicType{ 873 ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers }; 874 } 875 } 876 877 void postvisit( const ast::OneType * one ) { 878 if ( ! widen.first ) return; 879 if ( 880 dynamic_cast< const ast::BasicType * >( type2 ) 881 || dynamic_cast< const ast::EnumInstType * >( type2 ) 882 ) { 883 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 884 result = type2; 885 add_qualifiers( result, one->qualifiers ); 886 } 887 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 888 result = new ast::BasicType{ 889 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 890 } 891 } 892 893 }; 894 895 namespace { 896 ast::ptr< ast::Type > handleReference( 897 const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen, 898 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 899 const ast::OpenVarSet & open 900 ) { 901 ast::ptr<ast::Type> common; 902 ast::AssertionSet have, need; 903 ast::OpenVarSet newOpen{ open }; 904 905 // need unify to bind type variables 906 if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) { 907 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers; 908 PRINT( 909 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl; 910 ) 911 if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) { 912 PRINT( 913 std::cerr << "widen okay" << std::endl; 914 ) 915 add_qualifiers( common, q1 | q2 ); 916 return common; 917 } 918 } 919 920 PRINT( 921 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 922 ) 923 return { nullptr }; 924 } 925 } 926 927 ast::ptr< ast::Type > commonType( 928 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 929 WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 930 const ast::OpenVarSet & open 931 ) { 932 unsigned depth1 = type1->referenceDepth(); 933 unsigned depth2 = type2->referenceDepth(); 934 935 if ( depth1 != depth2 ) { // implies depth1 > 0 || depth2 > 0 936 PRINT( 937 std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl; 938 ) 939 ast::ptr< ast::Type > result; 940 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 941 const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >(); 942 943 if ( depth1 > depth2 ) { 944 assert( ref1 ); 945 result = handleReference( ref1->base, type2, widen, symtab, env, open ); 946 } else { // implies depth1 < depth2 947 assert( ref2 ); 948 result = handleReference( type1, ref2->base, widen, symtab, env, open ); 949 } 950 951 if ( result && ref1 ) { 952 // formal is reference, so result should be reference 953 PRINT( 954 std::cerr << "formal is reference; result should be reference" << std::endl; 955 ) 956 result = new ast::ReferenceType{ result, ref1->qualifiers }; 957 } 958 959 PRINT( 960 std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is " 961 "[" << result << "]" << std::endl; 962 ) 963 return result; 964 } 965 // otherwise both are reference types of the same depth and this is handled by the visitor 966 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open }; 967 type1->accept( visitor ); 968 ast::ptr< ast::Type > result = visitor.pass.result; 969 970 // handling for opaque type declarations (?) 971 if ( ! result && widen.second ) { 972 if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) { 973 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 974 auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt ); 975 if ( type->base ) { 976 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 977 ast::AssertionSet have, need; 978 ast::OpenVarSet newOpen{ open }; 979 980 // force t{1,2} to be cloned if its qualifiers must be stripped, so that 981 // type1 and type->base are left unchanged; calling convention forces 982 // {type1,type->base}->strong_ref >= 1 983 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base }; 984 reset_qualifiers( t1 ); 985 reset_qualifiers( t2, q1 ); 986 987 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) { 988 result = t1; 989 reset_qualifiers( result, q1 | q2 ); 990 } 991 } 992 } 993 } 994 } 995 996 return result; 997 } 998 668 999 } // namespace ResolvExpr 669 1000 -
src/ResolvExpr/FindOpenVars.cc
r4741dfe rd4b6638 19 19 #include <map> // for map<>::mapped_type 20 20 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 21 23 #include "Common/PassVisitor.h" 22 24 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... … … 24 26 25 27 namespace ResolvExpr { 26 struct FindOpenVars : public WithGuards {27 FindOpenVars ( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );28 struct FindOpenVars_old : public WithGuards { 29 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 28 30 29 31 void previsit( PointerType * pointerType ); … … 40 42 41 43 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) { 42 PassVisitor<FindOpenVars > finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );44 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen ); 43 45 type->accept( finder ); 44 46 } 45 47 46 FindOpenVars ::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )48 FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) 47 49 : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) { 48 50 } 49 51 50 void FindOpenVars ::common_action( Type *type ) {52 void FindOpenVars_old::common_action( Type *type ) { 51 53 if ( nextIsOpen ) { 52 54 for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) { … … 76 78 } 77 79 78 void FindOpenVars ::previsit(PointerType *pointerType) {80 void FindOpenVars_old::previsit(PointerType *pointerType) { 79 81 common_action( pointerType ); 80 82 } 81 83 82 void FindOpenVars ::previsit(ArrayType *arrayType) {84 void FindOpenVars_old::previsit(ArrayType *arrayType) { 83 85 common_action( arrayType ); 84 86 } 85 87 86 void FindOpenVars ::previsit(FunctionType *functionType) {88 void FindOpenVars_old::previsit(FunctionType *functionType) { 87 89 common_action( functionType ); 88 90 nextIsOpen = ! nextIsOpen; … … 90 92 } 91 93 92 void FindOpenVars ::previsit(TupleType *tupleType) {94 void FindOpenVars_old::previsit(TupleType *tupleType) { 93 95 common_action( tupleType ); 96 } 97 98 namespace { 99 struct FindOpenVars_new final : public ast::WithGuards { 100 ast::OpenVarSet & open; 101 ast::OpenVarSet & closed; 102 ast::AssertionSet & need; 103 ast::AssertionSet & have; 104 bool nextIsOpen; 105 106 FindOpenVars_new( 107 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 108 ast::AssertionSet & h, FirstMode firstIsOpen ) 109 : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {} 110 111 void previsit( const ast::FunctionType * type ) { 112 // mark open/closed variables 113 if ( nextIsOpen ) { 114 for ( const ast::TypeDecl * decl : type->forall ) { 115 open[ decl->name ] = ast::TypeDecl::Data{ decl }; 116 for ( const ast::DeclWithType * assert : decl->assertions ) { 117 need[ assert ].isUsed = false; 118 } 119 } 120 } else { 121 for ( const ast::TypeDecl * decl : type->forall ) { 122 closed[ decl->name ] = ast::TypeDecl::Data{ decl }; 123 for ( const ast::DeclWithType * assert : decl->assertions ) { 124 have[ assert ].isUsed = false; 125 } 126 } 127 } 128 129 // flip open variables for contained function types 130 nextIsOpen = ! nextIsOpen; 131 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } ); 132 } 133 134 }; 94 135 } 95 136 … … 97 138 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 98 139 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) { 99 #warning unimplemented 100 (void)type; (void)open; (void)closed; (void)need; (void)have; (void)firstIsOpen; 101 assert(false); 140 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen }; 141 type->accept( finder ); 102 142 } 103 143 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
r4741dfe rd4b6638 938 938 939 939 class Resolver_new final 940 : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>, 941 public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> { 940 : public ast::WithSymbolTable, public ast::WithGuards, 941 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 942 public ast::WithStmtsToAdd<> { 942 943 943 944 public: 944 945 Resolver_new() = default; 945 Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/}946 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 946 947 947 948 void previsit( ast::FunctionDecl * functionDecl ); -
src/ResolvExpr/Unify.cc
r4741dfe rd4b6638 136 136 137 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 139 139 } 140 140 … … 173 173 env.apply( newFirst ); 174 174 env.apply( newSecond ); 175 clear_qualifiers( newFirst );176 clear_qualifiers( newSecond );175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 177 177 178 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 180 180 } 181 181 … … 700 700 } 701 701 702 class Unify_new : public ast::WithShortCircuiting {702 class Unify_new final : public ast::WithShortCircuiting { 703 703 const ast::Type * type2; 704 704 ast::TypeEnvironment & tenv; … … 720 720 void previsit( const ast::Node * ) { visit_children = false; } 721 721 722 void previsit( const ast::VoidType * ) { 723 visit_children = false; 722 void postvisit( const ast::VoidType * ) { 724 723 result = dynamic_cast< const ast::VoidType * >( type2 ); 725 724 } 726 725 727 void previsit( const ast::BasicType * basic ) { 728 visit_children = false; 726 void postvisit( const ast::BasicType * basic ) { 729 727 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 730 728 result = basic->kind == basic2->kind; … … 732 730 } 733 731 734 void previsit( const ast::PointerType * pointer ) { 735 visit_children = false; 732 void postvisit( const ast::PointerType * pointer ) { 736 733 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 737 734 result = unifyExact( 738 735 pointer->base, pointer2->base, tenv, need, have, open, 739 WidenMode{ false, false }, symtab ); 740 } 741 } 742 743 void previsit( const ast::ArrayType * array ) { 744 visit_children = false; 736 noWiden(), symtab ); 737 } 738 } 739 740 void postvisit( const ast::ArrayType * array ) { 745 741 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 ); 746 742 if ( ! array2 ) return; … … 761 757 762 758 result = unifyExact( 763 array->base, array2->base, tenv, need, have, open, WidenMode{ false, false },759 array->base, array2->base, tenv, need, have, open, noWiden(), 764 760 symtab ); 765 761 } 766 762 767 void previsit( const ast::ReferenceType * ref ) { 768 visit_children = false; 763 void postvisit( const ast::ReferenceType * ref ) { 769 764 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 770 765 result = unifyExact( 771 ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false },766 ref->base, ref2->base, tenv, need, have, open, noWiden(), 772 767 symtab ); 773 768 } … … 783 778 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 784 779 785 const ast::Type * post mutate( const ast::TypeInstType * typeInst ) {780 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 786 781 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 787 782 // expand ttype parameter into its actual type … … 811 806 // overloaded on outermost mutex and a mutex function has different 812 807 // requirements than a non-mutex function 813 t.get_and_mutate()->qualifiers 814 -= ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic; 808 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 815 809 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 816 810 } … … 851 845 return unifyExact( 852 846 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 853 WidenMode{ false, false }, symtab );847 noWiden(), symtab ); 854 848 } else if ( ! isTuple1 && isTuple2 ) { 855 849 // combine remainder of list1, then unify 856 850 return unifyExact( 857 851 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 858 WidenMode{ false, false }, symtab );852 noWiden(), symtab ); 859 853 } 860 854 861 855 if ( ! unifyExact( 862 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )856 t1, t2, env, need, have, open, noWiden(), symtab ) 863 857 ) return false; 864 858 … … 874 868 return unifyExact( 875 869 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 876 WidenMode{ false, false }, symtab );870 noWiden(), symtab ); 877 871 } else if ( crnt2 != end2 ) { 878 872 // try unifying empty tuple with ttype … … 881 875 return unifyExact( 882 876 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 883 WidenMode{ false, false }, symtab );877 noWiden(), symtab ); 884 878 } 885 879 … … 919 913 920 914 public: 921 void previsit( const ast::FunctionType * func ) { 922 visit_children = false; 915 void postvisit( const ast::FunctionType * func ) { 923 916 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 ); 924 917 if ( ! func2 ) return; … … 952 945 template< typename RefType > 953 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 954 visit_children = false;955 947 // check that the other type is compatible and named the same 956 948 auto otherInst = dynamic_cast< const RefType * >( other ); … … 1011 1003 1012 1004 if ( ! unifyExact( 1013 pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) {1005 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) { 1014 1006 result = false; 1015 1007 return; … … 1023 1015 1024 1016 public: 1025 void p revisit( const ast::StructInstType * aggrType ) {1017 void postvisit( const ast::StructInstType * aggrType ) { 1026 1018 handleGenericRefType( aggrType, type2 ); 1027 1019 } 1028 1020 1029 void p revisit( const ast::UnionInstType * aggrType ) {1021 void postvisit( const ast::UnionInstType * aggrType ) { 1030 1022 handleGenericRefType( aggrType, type2 ); 1031 1023 } 1032 1024 1033 void p revisit( const ast::EnumInstType * aggrType ) {1025 void postvisit( const ast::EnumInstType * aggrType ) { 1034 1026 handleRefType( aggrType, type2 ); 1035 1027 } 1036 1028 1037 void p revisit( const ast::TraitInstType * aggrType ) {1029 void postvisit( const ast::TraitInstType * aggrType ) { 1038 1030 handleRefType( aggrType, type2 ); 1039 1031 } 1040 1032 1041 void p revisit( const ast::TypeInstType * typeInst ) {1033 void postvisit( const ast::TypeInstType * typeInst ) { 1042 1034 assert( open.find( typeInst->name ) == open.end() ); 1043 1035 handleRefType( typeInst, type2 ); … … 1078 1070 return unifyExact( 1079 1071 t1, tupleFromTypes( list2 ), env, need, have, open, 1080 WidenMode{ false, false }, symtab );1072 noWiden(), symtab ); 1081 1073 } else if ( ! isTuple1 && isTuple2 ) { 1082 1074 // combine entirety of list1, then unify 1083 1075 return unifyExact( 1084 1076 tupleFromTypes( list1 ), t2, env, need, have, open, 1085 WidenMode{ false, false }, symtab );1077 noWiden(), symtab ); 1086 1078 } 1087 1079 1088 1080 if ( ! unifyExact( 1089 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )1081 t1, t2, env, need, have, open, noWiden(), symtab ) 1090 1082 ) return false; 1091 1083 … … 1101 1093 return unifyExact( 1102 1094 t1, tupleFromTypes( list2 ), env, need, have, open, 1103 WidenMode{ false, false }, symtab );1095 noWiden(), symtab ); 1104 1096 } else if ( crnt2 != list2.end() ) { 1105 1097 // try unifying empty tuple with ttype … … 1110 1102 return unifyExact( 1111 1103 tupleFromTypes( list1 ), t2, env, need, have, open, 1112 WidenMode{ false, false }, symtab );1104 noWiden(), symtab ); 1113 1105 } 1114 1106 … … 1117 1109 1118 1110 public: 1119 void previsit( const ast::TupleType * tuple ) { 1120 visit_children = false; 1111 void postvisit( const ast::TupleType * tuple ) { 1121 1112 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 ); 1122 1113 if ( ! tuple2 ) return; … … 1132 1123 } 1133 1124 1134 void previsit( const ast::VarArgsType * ) { 1135 visit_children = false; 1125 void postvisit( const ast::VarArgsType * ) { 1136 1126 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 1137 1127 } 1138 1128 1139 void previsit( const ast::ZeroType * ) { 1140 visit_children = false; 1129 void postvisit( const ast::ZeroType * ) { 1141 1130 result = dynamic_cast< const ast::ZeroType * >( type2 ); 1142 1131 } 1143 1132 1144 void previsit( const ast::OneType * ) { 1145 visit_children = false; 1133 void postvisit( const ast::OneType * ) { 1146 1134 result = dynamic_cast< const ast::OneType * >( type2 ); 1147 1135 } … … 1151 1139 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 1152 1140 }; 1141 1142 bool unify( 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1144 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1146 ) { 1147 ast::OpenVarSet closed; 1148 findOpenVars( type1, open, closed, need, have, FirstClosed ); 1149 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1150 return unifyInexact( 1151 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common ); 1152 } 1153 1153 1154 1154 bool unifyExact( … … 1184 1184 1185 1185 bool unifyInexact( 1186 ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env, 1187 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1188 WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1186 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1187 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1188 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 1189 ast::ptr<ast::Type> & common 1189 1190 ) { 1190 1191 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; … … 1193 1194 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1194 1195 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1195 clear_qualifiers( t1 );1196 clear_qualifiers( t2 );1196 reset_qualifiers( t1 ); 1197 reset_qualifiers( t2 ); 1197 1198 1198 1199 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { … … 1201 1202 // if exact unification on unqualified types, try to merge qualifiers 1202 1203 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1203 common.set_and_mutate( type1 )->qualifiers = q1 | q2; 1204 common = type1; 1205 reset_qualifiers( common, q1 | q2 ); 1204 1206 return true; 1205 1207 } else { … … 1211 1213 1212 1214 // no exact unification, but common type 1213 common.get_and_mutate()->qualifiers = q1 | q2;1215 reset_qualifiers( common, q1 | q2 ); 1214 1216 return true; 1215 1217 } else { -
src/ResolvExpr/Unify.h
r4741dfe rd4b6638 69 69 } 70 70 71 bool unify( 72 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 73 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 74 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 75 71 76 bool unifyExact( 72 77 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 73 ast::AssertionSet & need, ast::AssertionSet & have, ast::OpenVarSet & open,74 const ast::SymbolTable & symtab );78 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 79 WidenMode widen, const ast::SymbolTable & symtab ); 75 80 76 81 bool unifyInexact( 77 ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env, 78 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 79 WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 82 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 83 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 84 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 85 ast::ptr<ast::Type> & common ); 80 86 81 87 } // namespace ResolvExpr -
src/ResolvExpr/WidenMode.h
r4741dfe rd4b6638 40 40 bool first : 1, second : 1; 41 41 }; 42 43 static inline WidenMode noWiden() { return { false, false }; } 42 44 } // namespace ResolvExpr 43 45 -
src/ResolvExpr/typeops.h
r4741dfe rd4b6638 89 89 90 90 // in Unify.cc 91 bool isFtype( Type *type );92 91 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 93 92 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 118 117 // in CommonType.cc 119 118 Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 120 const ast::Type *commonType(121 const ast:: Type * type1, const ast::Type *type2, WidenMode widen,119 ast::ptr< ast::Type > commonType( 120 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen, 122 121 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 123 122 … … 177 176 return out; 178 177 } 178 179 // in TypeEnvironment.cc 180 bool isFtype( Type *type ); 179 181 } // namespace ResolvExpr 182 183 namespace ast { 184 // in TypeEnvironment.cpp 185 bool isFtype( const ast::Type * type ); 186 } // namespace ast 180 187 181 188 // Local Variables: // -
src/SymTab/Mangler.cc
r4741dfe rd4b6638 32 32 #include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora... 33 33 34 #include "AST/Pass.hpp" 35 34 36 namespace SymTab { 35 37 namespace Mangler { 36 38 namespace { 37 39 /// Mangles names to a unique C identifier 38 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {39 Mangler ( bool mangleOverridable, bool typeMode, bool mangleGenericParams );40 Mangler ( const Mangler& ) = delete;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; 41 43 42 44 void previsit( BaseSyntaxNode * ) { visit_children = false; } … … 77 79 78 80 public: 79 Mangler ( bool mangleOverridable, bool typeMode, bool mangleGenericParams,81 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 80 82 int nextVarNum, const VarMapType& varNums ); 81 83 … … 85 87 86 88 void printQualifiers( Type *type ); 87 }; // Mangler 89 }; // Mangler_old 88 90 } // namespace 89 91 90 92 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { 91 PassVisitor<Mangler > mangler( mangleOverridable, typeMode, mangleGenericParams );93 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams ); 92 94 maybeAccept( decl, mangler ); 93 95 return mangler.pass.get_mangleName(); … … 95 97 96 98 std::string mangleType( Type * ty ) { 97 PassVisitor<Mangler > mangler( false, true, true );99 PassVisitor<Mangler_old> mangler( false, true, true ); 98 100 maybeAccept( ty, mangler ); 99 101 return mangler.pass.get_mangleName(); … … 101 103 102 104 std::string mangleConcrete( Type * ty ) { 103 PassVisitor<Mangler > mangler( false, false, false );105 PassVisitor<Mangler_old> mangler( false, false, false ); 104 106 maybeAccept( ty, mangler ); 105 107 return mangler.pass.get_mangleName(); … … 107 109 108 110 namespace { 109 Mangler ::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )111 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 110 112 : nextVarNum( 0 ), isTopLevel( true ), 111 113 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 112 114 mangleGenericParams( mangleGenericParams ) {} 113 115 114 Mangler ::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,116 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 115 117 int nextVarNum, const VarMapType& varNums ) 116 118 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), … … 118 120 mangleGenericParams( mangleGenericParams ) {} 119 121 120 void Mangler ::mangleDecl( DeclarationWithType * declaration ) {122 void Mangler_old::mangleDecl( DeclarationWithType * declaration ) { 121 123 bool wasTopLevel = isTopLevel; 122 124 if ( isTopLevel ) { … … 148 150 } 149 151 150 void Mangler ::postvisit( ObjectDecl * declaration ) {152 void Mangler_old::postvisit( ObjectDecl * declaration ) { 151 153 mangleDecl( declaration ); 152 154 } 153 155 154 void Mangler ::postvisit( FunctionDecl * declaration ) {156 void Mangler_old::postvisit( FunctionDecl * declaration ) { 155 157 mangleDecl( declaration ); 156 158 } 157 159 158 void Mangler ::postvisit( VoidType * voidType ) {160 void Mangler_old::postvisit( VoidType * voidType ) { 159 161 printQualifiers( voidType ); 160 162 mangleName << Encoding::void_t; 161 163 } 162 164 163 void Mangler ::postvisit( BasicType * basicType ) {165 void Mangler_old::postvisit( BasicType * basicType ) { 164 166 printQualifiers( basicType ); 165 167 assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() ); … … 167 169 } 168 170 169 void Mangler ::postvisit( PointerType * pointerType ) {171 void Mangler_old::postvisit( PointerType * pointerType ) { 170 172 printQualifiers( pointerType ); 171 173 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers … … 174 176 } 175 177 176 void Mangler ::postvisit( ArrayType * arrayType ) {178 void Mangler_old::postvisit( ArrayType * arrayType ) { 177 179 // TODO: encode dimension 178 180 printQualifiers( arrayType ); … … 181 183 } 182 184 183 void Mangler ::postvisit( ReferenceType * refType ) {185 void Mangler_old::postvisit( ReferenceType * refType ) { 184 186 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 185 187 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), … … 200 202 } 201 203 202 void Mangler ::postvisit( FunctionType * functionType ) {204 void Mangler_old::postvisit( FunctionType * functionType ) { 203 205 printQualifiers( functionType ); 204 206 mangleName << Encoding::function; … … 217 219 } 218 220 219 void Mangler ::mangleRef( ReferenceToType * refType, std::string prefix ) {221 void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) { 220 222 printQualifiers( refType ); 221 223 … … 236 238 } 237 239 238 void Mangler ::postvisit( StructInstType * aggregateUseType ) {240 void Mangler_old::postvisit( StructInstType * aggregateUseType ) { 239 241 mangleRef( aggregateUseType, Encoding::struct_t ); 240 242 } 241 243 242 void Mangler ::postvisit( UnionInstType * aggregateUseType ) {244 void Mangler_old::postvisit( UnionInstType * aggregateUseType ) { 243 245 mangleRef( aggregateUseType, Encoding::union_t ); 244 246 } 245 247 246 void Mangler ::postvisit( EnumInstType * aggregateUseType ) {248 void Mangler_old::postvisit( EnumInstType * aggregateUseType ) { 247 249 mangleRef( aggregateUseType, Encoding::enum_t ); 248 250 } 249 251 250 void Mangler ::postvisit( TypeInstType * typeInst ) {252 void Mangler_old::postvisit( TypeInstType * typeInst ) { 251 253 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 252 254 if ( varNum == varNums.end() ) { … … 264 266 } 265 267 266 void Mangler ::postvisit( TraitInstType * inst ) {268 void Mangler_old::postvisit( TraitInstType * inst ) { 267 269 printQualifiers( inst ); 268 270 mangleName << inst->name.size() << inst->name; 269 271 } 270 272 271 void Mangler ::postvisit( TupleType * tupleType ) {273 void Mangler_old::postvisit( TupleType * tupleType ) { 272 274 printQualifiers( tupleType ); 273 275 mangleName << Encoding::tuple << tupleType->types.size(); … … 275 277 } 276 278 277 void Mangler ::postvisit( VarArgsType * varArgsType ) {279 void Mangler_old::postvisit( VarArgsType * varArgsType ) { 278 280 printQualifiers( varArgsType ); 279 281 static const std::string vargs = "__builtin_va_list"; … … 281 283 } 282 284 283 void Mangler ::postvisit( ZeroType * ) {285 void Mangler_old::postvisit( ZeroType * ) { 284 286 mangleName << Encoding::zero; 285 287 } 286 288 287 void Mangler ::postvisit( OneType * ) {289 void Mangler_old::postvisit( OneType * ) { 288 290 mangleName << Encoding::one; 289 291 } 290 292 291 void Mangler ::postvisit( QualifiedType * qualType ) {293 void Mangler_old::postvisit( QualifiedType * qualType ) { 292 294 bool inqual = inQualifiedType; 293 295 if (! inqual ) { … … 305 307 } 306 308 307 void Mangler ::postvisit( TypeDecl * decl ) {309 void Mangler_old::postvisit( TypeDecl * decl ) { 308 310 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 309 311 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. … … 311 313 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 312 314 // aside from the assert false. 313 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));315 assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl)); 314 316 assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() ); 315 317 mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name; … … 322 324 } 323 325 324 void Mangler ::printQualifiers( Type * type ) {326 void Mangler_old::printQualifiers( Type * type ) { 325 327 // skip if not including qualifiers 326 328 if ( typeMode ) return; … … 345 347 varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() ); 346 348 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 347 PassVisitor<Mangler > sub_mangler(349 PassVisitor<Mangler_old> sub_mangler( 348 350 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 349 351 (*assert)->accept( sub_mangler ); … … 391 393 392 394 namespace Mangle { 395 namespace { 396 /// Mangles names to a unique C identifier 397 struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards { 398 Mangler_new( Mangle::Mode mode ); 399 Mangler_new( const Mangler_new & ) = delete; 400 401 void previsit( const ast::Node * ) { visit_children = false; } 402 403 void postvisit( const ast::ObjectDecl * declaration ); 404 void postvisit( const ast::FunctionDecl * declaration ); 405 void postvisit( const ast::TypeDecl * declaration ); 406 407 void postvisit( const ast::VoidType * voidType ); 408 void postvisit( const ast::BasicType * basicType ); 409 void postvisit( const ast::PointerType * pointerType ); 410 void postvisit( const ast::ArrayType * arrayType ); 411 void postvisit( const ast::ReferenceType * refType ); 412 void postvisit( const ast::FunctionType * functionType ); 413 void postvisit( const ast::StructInstType * aggregateUseType ); 414 void postvisit( const ast::UnionInstType * aggregateUseType ); 415 void postvisit( const ast::EnumInstType * aggregateUseType ); 416 void postvisit( const ast::TypeInstType * aggregateUseType ); 417 void postvisit( const ast::TraitInstType * inst ); 418 void postvisit( const ast::TupleType * tupleType ); 419 void postvisit( const ast::VarArgsType * varArgsType ); 420 void postvisit( const ast::ZeroType * zeroType ); 421 void postvisit( const ast::OneType * oneType ); 422 void postvisit( const ast::QualifiedType * qualType ); 423 424 std::string get_mangleName() { return mangleName.str(); } 425 private: 426 std::ostringstream mangleName; ///< Mangled name being constructed 427 typedef std::map< std::string, std::pair< int, int > > VarMapType; 428 VarMapType varNums; ///< Map of type variables to indices 429 int nextVarNum; ///< Next type variable index 430 bool isTopLevel; ///< Is the Mangler at the top level 431 bool mangleOverridable; ///< Specially mangle overridable built-in methods 432 bool typeMode; ///< Produce a unique mangled name for a type 433 bool mangleGenericParams; ///< Include generic parameters in name mangling if true 434 bool inFunctionType = false; ///< Include type qualifiers if false. 435 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type 436 437 private: 438 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 439 int nextVarNum, const VarMapType& varNums ); 440 friend class ast::Pass<Mangler_new>; 441 442 private: 443 void mangleDecl( const ast::DeclWithType *declaration ); 444 void mangleRef( const ast::ReferenceToType *refType, std::string prefix ); 445 446 void printQualifiers( const ast::Type *type ); 447 }; // Mangler_new 448 } // namespace 449 450 393 451 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) { 394 #warning unimplemented395 assert( decl && mode.val && false);396 return "";452 ast::Pass<Mangler_new> mangler( mode ); 453 maybeAccept( decl, mangler ); 454 return mangler.pass.get_mangleName(); 397 455 } 456 457 namespace { 458 Mangler_new::Mangler_new( Mangle::Mode mode ) 459 : nextVarNum( 0 ), isTopLevel( true ), 460 mangleOverridable ( ! mode.no_overrideable ), 461 typeMode ( mode.type ), 462 mangleGenericParams( ! mode.no_generic_params ) {} 463 464 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 465 int nextVarNum, const VarMapType& varNums ) 466 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 467 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 468 mangleGenericParams( mangleGenericParams ) {} 469 470 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) { 471 bool wasTopLevel = isTopLevel; 472 if ( isTopLevel ) { 473 varNums.clear(); 474 nextVarNum = 0; 475 isTopLevel = false; 476 } // if 477 mangleName << Encoding::manglePrefix; 478 CodeGen::OperatorInfo opInfo; 479 if ( operatorLookup( decl->name, opInfo ) ) { 480 mangleName << opInfo.outputName.size() << opInfo.outputName; 481 } else { 482 mangleName << decl->name.size() << decl->name; 483 } // if 484 maybeAccept( decl->get_type(), *visitor ); 485 if ( mangleOverridable && decl->linkage.is_overrideable ) { 486 // want to be able to override autogenerated and intrinsic routines, 487 // so they need a different name mangling 488 if ( decl->linkage == ast::Linkage::AutoGen ) { 489 mangleName << Encoding::autogen; 490 } else if ( decl->linkage == ast::Linkage::Intrinsic ) { 491 mangleName << Encoding::intrinsic; 492 } else { 493 // if we add another kind of overridable function, this has to change 494 assert( false && "unknown overrideable linkage" ); 495 } // if 496 } 497 isTopLevel = wasTopLevel; 498 } 499 500 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) { 501 mangleDecl( decl ); 502 } 503 504 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) { 505 mangleDecl( decl ); 506 } 507 508 void Mangler_new::postvisit( const ast::VoidType * voidType ) { 509 printQualifiers( voidType ); 510 mangleName << Encoding::void_t; 511 } 512 513 void Mangler_new::postvisit( const ast::BasicType * basicType ) { 514 printQualifiers( basicType ); 515 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind ); 516 mangleName << Encoding::basicTypes[ basicType->kind ]; 517 } 518 519 void Mangler_new::postvisit( const ast::PointerType * pointerType ) { 520 printQualifiers( pointerType ); 521 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers 522 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer; 523 maybe_accept( pointerType->base.get(), *visitor ); 524 } 525 526 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) { 527 // TODO: encode dimension 528 printQualifiers( arrayType ); 529 mangleName << Encoding::array << "0"; 530 maybeAccept( arrayType->base.get(), *visitor ); 531 } 532 533 void Mangler_new::postvisit( const ast::ReferenceType * refType ) { 534 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 535 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), 536 // by pretending every reference type is a function parameter. 537 GuardValue( inFunctionType ); 538 inFunctionType = true; 539 printQualifiers( refType ); 540 maybeAccept( refType->base.get(), *visitor ); 541 } 542 543 inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) { 544 std::vector< ast::ptr< ast::Type > > ret; 545 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ), 546 std::mem_fun( &ast::DeclWithType::get_type ) ); 547 return ret; 548 } 549 550 void Mangler_new::postvisit( const ast::FunctionType * functionType ) { 551 printQualifiers( functionType ); 552 mangleName << Encoding::function; 553 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters, 554 // since qualifiers on outermost parameter type do not differentiate function types, e.g., 555 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different 556 GuardValue( inFunctionType ); 557 inFunctionType = true; 558 std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns ); 559 if (returnTypes.empty()) mangleName << Encoding::void_t; 560 else accept_each( returnTypes, *visitor ); 561 mangleName << "_"; 562 std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params ); 563 accept_each( paramTypes, *visitor ); 564 mangleName << "_"; 565 } 566 567 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) { 568 printQualifiers( refType ); 569 570 mangleName << prefix << refType->name.length() << refType->name; 571 572 if ( mangleGenericParams ) { 573 if ( ! refType->params.empty() ) { 574 mangleName << "_"; 575 for ( const ast::Expr * param : refType->params ) { 576 auto paramType = dynamic_cast< const ast::TypeExpr * >( param ); 577 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 578 maybeAccept( paramType->type.get(), *visitor ); 579 } 580 mangleName << "_"; 581 } 582 } 583 } 584 585 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) { 586 mangleRef( aggregateUseType, Encoding::struct_t ); 587 } 588 589 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) { 590 mangleRef( aggregateUseType, Encoding::union_t ); 591 } 592 593 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) { 594 mangleRef( aggregateUseType, Encoding::enum_t ); 595 } 596 597 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) { 598 VarMapType::iterator varNum = varNums.find( typeInst->name ); 599 if ( varNum == varNums.end() ) { 600 mangleRef( typeInst, Encoding::type ); 601 } else { 602 printQualifiers( typeInst ); 603 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g. 604 // forall(dtype T) void f(T); 605 // forall(dtype S) void f(S); 606 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they 607 // are first found and prefixing with the appropriate encoding for the type class. 608 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second ); 609 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first; 610 } // if 611 } 612 613 void Mangler_new::postvisit( const ast::TraitInstType * inst ) { 614 printQualifiers( inst ); 615 mangleName << inst->name.size() << inst->name; 616 } 617 618 void Mangler_new::postvisit( const ast::TupleType * tupleType ) { 619 printQualifiers( tupleType ); 620 mangleName << Encoding::tuple << tupleType->types.size(); 621 accept_each( tupleType->types, *visitor ); 622 } 623 624 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) { 625 printQualifiers( varArgsType ); 626 static const std::string vargs = "__builtin_va_list"; 627 mangleName << Encoding::type << vargs.size() << vargs; 628 } 629 630 void Mangler_new::postvisit( const ast::ZeroType * ) { 631 mangleName << Encoding::zero; 632 } 633 634 void Mangler_new::postvisit( const ast::OneType * ) { 635 mangleName << Encoding::one; 636 } 637 638 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) { 639 bool inqual = inQualifiedType; 640 if (! inqual ) { 641 // N marks the start of a qualified type 642 inQualifiedType = true; 643 mangleName << Encoding::qualifiedTypeStart; 644 } 645 maybeAccept( qualType->parent.get(), *visitor ); 646 maybeAccept( qualType->child.get(), *visitor ); 647 if ( ! inqual ) { 648 // E marks the end of a qualified type 649 inQualifiedType = false; 650 mangleName << Encoding::qualifiedTypeEnd; 651 } 652 } 653 654 void Mangler_new::postvisit( const ast::TypeDecl * decl ) { 655 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 656 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. 657 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply 658 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 659 // aside from the assert false. 660 assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl)); 661 assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 662 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name; 663 } 664 665 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) { 666 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) { 667 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl; 668 } // for 669 } 670 671 void Mangler_new::printQualifiers( const ast::Type * type ) { 672 // skip if not including qualifiers 673 if ( typeMode ) return; 674 if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) { 675 if ( ! ptype->forall.empty() ) { 676 std::list< std::string > assertionNames; 677 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 678 mangleName << Encoding::forall; 679 for ( const ast::TypeDecl * decl : ptype->forall ) { 680 switch ( decl->kind ) { 681 case ast::TypeVar::Kind::Dtype: 682 dcount++; 683 break; 684 case ast::TypeVar::Kind::Ftype: 685 fcount++; 686 break; 687 case ast::TypeVar::Kind::Ttype: 688 vcount++; 689 break; 690 default: 691 assert( false ); 692 } // switch 693 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 694 for ( const ast::DeclWithType * assert : decl->assertions ) { 695 ast::Pass<Mangler_new> sub_mangler( 696 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 697 assert->accept( sub_mangler ); 698 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 699 acount++; 700 } // for 701 } // for 702 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_"; 703 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); 704 mangleName << "_"; 705 } // if 706 } // if 707 if ( ! inFunctionType ) { 708 // these qualifiers do not distinguish the outermost type of a function parameter 709 if ( type->is_const() ) { 710 mangleName << Encoding::qualifiers.at(Type::Const); 711 } // if 712 if ( type->is_volatile() ) { 713 mangleName << Encoding::qualifiers.at(Type::Volatile); 714 } // if 715 // Removed due to restrict not affecting function compatibility in GCC 716 // if ( type->get_isRestrict() ) { 717 // mangleName << "E"; 718 // } // if 719 if ( type->is_atomic() ) { 720 mangleName << Encoding::qualifiers.at(Type::Atomic); 721 } // if 722 } 723 if ( type->is_mutex() ) { 724 mangleName << Encoding::qualifiers.at(Type::Mutex); 725 } // if 726 if ( type->is_lvalue() ) { 727 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues 728 mangleName << Encoding::qualifiers.at(Type::Lvalue); 729 } 730 731 if ( inFunctionType ) { 732 // turn off inFunctionType so that types can be differentiated for nested qualifiers 733 GuardValue( inFunctionType ); 734 inFunctionType = false; 735 } 736 } 737 } // namespace 398 738 } // namespace Mangle 399 739
Note: See TracChangeset
for help on using the changeset viewer.