Ignore:
Timestamp:
Nov 10, 2020, 12:20:37 AM (21 months ago)
Author:
Fangren Yu <f37yu@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr
Children:
18f0b70
Parents:
3febb2d
Message:

factor out resolver calls in pre-resolution stage

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r3febb2d r16ba4a6  
    2626#include "RenameVars.h"                  // for RenameVars, global_renamer
    2727#include "Resolver.h"
     28#include "ResolveTypeof.h"
    2829#include "ResolvMode.h"                  // for ResolvMode
    2930#include "typeops.h"                     // for extractResultType
    3031#include "Unify.h"                       // for unify
     32#include "CompilationState.h"
    3133#include "AST/Chain.hpp"
    3234#include "AST/Decl.hpp"
     
    4547#include "SymTab/Autogen.h"              // for SizeType
    4648#include "SymTab/Indexer.h"              // for Indexer
     49#include "SymTab/Mangler.h"              // for Mangler
    4750#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
    4851#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
     
    11791182        } // anonymous namespace
    11801183
    1181                 ast::ptr< ast::Expr > findSingleExpression(
    1182                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1183                 ) {
    1184                         assert( untyped && type );
    1185                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1186                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1187                         removeExtraneousCast( newExpr, symtab );
    1188                         return newExpr;
    1189                 }
     1184        ast::ptr< ast::Expr > findSingleExpression(
     1185                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1186        ) {
     1187                assert( untyped && type );
     1188                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
     1189                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
     1190                removeExtraneousCast( newExpr, symtab );
     1191                return newExpr;
     1192        }
    11901193
    11911194        namespace {
     1195                bool structOrUnion( const Candidate & i ) {
     1196                        const ast::Type * t = i.expr->result->stripReferences();
     1197                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
     1198                }
    11921199                /// Predicate for "Candidate has integral type"
    11931200                bool hasIntegralType( const Candidate & i ) {
     
    12371244                ast::ptr< ast::Type > functionReturn = nullptr;
    12381245                ast::CurrentObject currentObject;
     1246                // for work previously in GenInit
     1247                static InitTweak::ManagedTypes_new managedTypes;
     1248
    12391249                bool inEnumDecl = false;
    12401250
     
    12441254                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    12451255
    1246                 void previsit( const ast::FunctionDecl * );
     1256                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
    12471257                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    1248                 void previsit( const ast::ObjectDecl * );
     1258                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
     1259                void previsit( const ast::AggregateDecl * );
     1260                void previsit( const ast::StructDecl * );
    12491261                void previsit( const ast::EnumDecl * );
    12501262                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
     
    12671279                const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
    12681280                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
     1281                const ast::WithStmt *        previsit( const ast::WithStmt * );
    12691282
    12701283                const ast::SingleInit *      previsit( const ast::SingleInit * );
    12711284                const ast::ListInit *        previsit( const ast::ListInit * );
    12721285                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
     1286
     1287                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
     1288
     1289                void beginScope() { managedTypes.beginScope(); }
     1290                void endScope() { managedTypes.endScope(); }
    12731291        };
    12741292        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
     1293
     1294        InitTweak::ManagedTypes_new Resolver_new::managedTypes;
    12751295
    12761296        void resolve( ast::TranslationUnit& translationUnit ) {
     
    12971317        }
    12981318
    1299         void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
     1319        namespace {
     1320                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
     1321                        std::string name = attr->normalizedName();
     1322                        if (name == "constructor" || name == "destructor") {
     1323                                if (attr->params.size() == 1) {
     1324                                        auto arg = attr->params.front();
     1325                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
     1326                                        auto result = eval(arg);
     1327
     1328                                        auto mutAttr = mutate(attr);
     1329                                        mutAttr->params.front() = resolved;
     1330                                        if (! result.second) {
     1331                                                SemanticWarning(loc, Warning::GccAttributes,
     1332                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
     1333                                        }
     1334                                        else {
     1335                                                auto priority = result.first;
     1336                                                if (priority < 101) {
     1337                                                        SemanticWarning(loc, Warning::GccAttributes,
     1338                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
     1339                                                } else if (priority < 201 && ! buildingLibrary()) {
     1340                                                        SemanticWarning(loc, Warning::GccAttributes,
     1341                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
     1342                                                }
     1343                                        }
     1344                                        return mutAttr;
     1345                                } else if (attr->params.size() > 1) {
     1346                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
     1347                                } else {
     1348                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
     1349                                }
     1350                        }
     1351                        return attr;
     1352                }
     1353        }
     1354
     1355        const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
    13001356                GuardValue( functionReturn );
     1357
     1358                assert (functionDecl->unique());
     1359                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
     1360                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
     1361                }
     1362
     1363                if (!functionDecl->isTypeFixed) {
     1364                        auto mutDecl = mutate(functionDecl);
     1365                        auto mutType = mutDecl->type.get_and_mutate();
     1366
     1367                        for (auto & attr: mutDecl->attributes) {
     1368                                attr = handleAttribute(mutDecl->location, attr, symtab);
     1369                        }
     1370
     1371                        // handle assertions. (seems deep)
     1372
     1373                        symtab.enterScope();
     1374                        for (auto & typeParam : mutType->forall) {
     1375                                auto mutParam = typeParam.get_and_mutate();
     1376                                symtab.addType(mutParam);
     1377                                for (auto & asst : mutParam->assertions) {
     1378                                        asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1379                                        symtab.addId(asst);
     1380                                }
     1381                                typeParam = mutParam;
     1382                        }
     1383
     1384                        // temporarily adds params to symbol table.
     1385                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
     1386
     1387                        std::vector<ast::ptr<ast::Type>> paramTypes;
     1388                        std::vector<ast::ptr<ast::Type>> returnTypes;
     1389
     1390                        for (auto & param : mutDecl->params) {
     1391                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
     1392                                symtab.addId(param);
     1393                                paramTypes.emplace_back(param->get_type());
     1394                        }
     1395                        for (auto & ret : mutDecl->returns) {
     1396                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
     1397                                returnTypes.emplace_back(ret->get_type());
     1398                        }
     1399                        // since function type in decl is just a view of param types, need to update that as well
     1400                        mutType->params = std::move(paramTypes);
     1401                        mutType->returns = std::move(returnTypes);
     1402
     1403                        std::list<ast::ptr<ast::Stmt>> newStmts;
     1404                        resolveWithExprs (mutDecl->withExprs, newStmts);
     1405
     1406                        if (mutDecl->stmts) {
     1407                                auto mutStmt = mutDecl->stmts.get_and_mutate();
     1408                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
     1409                                mutDecl->stmts = mutStmt;
     1410                        }
     1411
     1412                        symtab.leaveScope();
     1413
     1414                        mutDecl->mangleName = Mangle::mangle(mutDecl);
     1415                        mutDecl->isTypeFixed = true;
     1416                        functionDecl = mutDecl;
     1417                }
     1418                managedTypes.handleDWT(functionDecl);
     1419
    13011420                functionReturn = extractResultType( functionDecl->type );
     1421                return functionDecl;
    13021422        }
    13031423
     
    13301450        }
    13311451
    1332         void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
     1452        const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    13331453                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    13341454                // class-variable `initContext` is changed multiple times because the LHS is analyzed
     
    13381458                // selecting the RHS.
    13391459                GuardValue( currentObject );
    1340                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1460
    13411461                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    13421462                        // enumerator initializers should not use the enum type to initialize, since the
    13431463                        // enum type is still incomplete at this point. Use `int` instead.
     1464                        objectDecl = fixObjectType(objectDecl, symtab);
    13441465                        currentObject = ast::CurrentObject{
    13451466                                objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    13461467                }
     1468                else {
     1469                        if (!objectDecl->isTypeFixed) {
     1470                                auto newDecl = fixObjectType(objectDecl, symtab);
     1471                                auto mutDecl = mutate(newDecl);
     1472                               
     1473                                // generate CtorInit wrapper when necessary.
     1474                                // in certain cases, fixObjectType is called before reaching
     1475                                // this object in visitor pass, thus disabling CtorInit codegen.
     1476                                // this happens on aggregate members and function parameters.
     1477                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
     1478                                        // constructed objects cannot be designated
     1479                                        if ( InitTweak::isDesignated( mutDecl->init ) ) SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
     1480                                        // constructed objects should not have initializers nested too deeply
     1481                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
     1482
     1483                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
     1484                                }
     1485
     1486                                objectDecl = mutDecl;
     1487                        }
     1488                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1489                }
     1490               
     1491                return objectDecl;
     1492        }
     1493
     1494        void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
     1495                auto aggDecl = mutate(_aggDecl);
     1496                assertf(aggDecl == _aggDecl, "type declarations must be unique");
     1497
     1498                for (auto & member: aggDecl->members) {
     1499                        // nested type decls are hoisted already. no need to do anything
     1500                        if (auto obj = member.as<ast::ObjectDecl>()) {
     1501                                member = fixObjectType(obj, symtab);
     1502                        }
     1503                }
     1504        }
     1505
     1506        void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
     1507                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
     1508                managedTypes.handleStruct(structDecl);
    13471509        }
    13481510
     
    13511513                GuardValue( inEnumDecl );
    13521514                inEnumDecl = true;
    1353         }
     1515                // don't need to fix types for enum fields
     1516        }
     1517
    13541518
    13551519        const ast::StaticAssertDecl * Resolver_new::previsit(
     
    17801944        }
    17811945
     1946        const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
     1947                auto mutStmt = mutate(withStmt);
     1948                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
     1949                return mutStmt;
     1950        }
     1951
     1952        void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
     1953                for (auto & expr : exprs) {
     1954                        // only struct- and union-typed expressions are viable candidates
     1955                        expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
     1956
     1957                        // if with expression might be impure, create a temporary so that it is evaluated once
     1958                        if ( Tuples::maybeImpure( expr ) ) {
     1959                                static UniqueName tmpNamer( "_with_tmp_" );
     1960                                const CodeLocation loc = expr->location;
     1961                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
     1962                                expr = new ast::VariableExpr( loc, tmp );
     1963                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
     1964                                if ( InitTweak::isConstructable( tmp->type ) ) {
     1965                                        // generate ctor/dtor and resolve them
     1966                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
     1967                                }
     1968                                // since tmp is freshly created, this should modify tmp in-place
     1969                                tmp->accept( *visitor );
     1970                        }
     1971                }
     1972        }
    17821973
    17831974
Note: See TracChangeset for help on using the changeset viewer.