source: src/ResolvExpr/ResolveTypeof.cc @ 6bd9f9e

Last change on this file since 6bd9f9e was f033d01, checked in by JiadaL <j82liang@…>, 9 months ago

Fix typo{

  • Property mode set to 100644
File size: 9.5 KB
RevLine 
[a32b204]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[906e24d]7// ResolveTypeof.cc --
[a32b204]8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 12:12:20 2015
[39d8950]11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Mar 16 16:09:00 2022
13// Update Count     : 4
[a32b204]14//
15
[51b7345]16#include "ResolveTypeof.h"
[ea6332d]17
[92355883]18#include <cassert>  // for assert
[ea6332d]19
[0f6a7752]20#include "AST/CVQualifiers.hpp"
21#include "AST/Node.hpp"
22#include "AST/Pass.hpp"
[39d8950]23#include "AST/TranslationUnit.hpp"
[0f6a7752]24#include "AST/Type.hpp"
25#include "AST/TypeEnvironment.hpp"
[62c6cfa]26#include "Common/PassVisitor.h"   // for PassVisitor
27#include "Common/utility.h"       // for copy
28#include "InitTweak/InitTweak.h"  // for isConstExpr
[92355883]29#include "RenameVars.h"
30#include "Resolver.h"  // for resolveInVoidContext
31#include "SymTab/Mangler.h"
[ea6332d]32#include "SynTree/Expression.h"  // for Expression
33#include "SynTree/Mutator.h"     // for Mutator
34#include "SynTree/Type.h"        // for TypeofType, Type
35
36namespace SymTab {
37class Indexer;
38}  // namespace SymTab
[51b7345]39
40namespace ResolvExpr {
[92355883]41namespace {
[51b7345]42#if 0
[a32b204]43                void
44                printAlts( const AltList &list, std::ostream &os, int indent = 0 )
45                {
46                        for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
47                                i->print( os, indent );
48                                os << std::endl;
49                        }
50                }
[51b7345]51#endif
[62c6cfa]52        }
[51b7345]53
[92355883]54class ResolveTypeof_old : public WithShortCircuiting {
55   public:
[62c6cfa]56                ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
57                void premutate( TypeofType *typeofType );
58                Type * postmutate( TypeofType *typeofType );
[51b7345]59
[92355883]60   private:
61    const SymTab::Indexer &indexer;
62};
[51b7345]63
[62c6cfa]64        Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
65                PassVisitor<ResolveTypeof_old> mutator( indexer );
66                return type->acceptMutator( mutator );
67        }
[51b7345]68
[62c6cfa]69        void ResolveTypeof_old::premutate( TypeofType * ) {
70                visit_children = false;
71        }
[9d79f93]72
[62c6cfa]73    Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
[d9a0e76]74#if 0
[9d79f93]75                std::cerr << "resolving typeof: ";
76                typeofType->print( std::cerr );
77                std::cerr << std::endl;
[d9a0e76]78#endif
[92355883]79    // pass on null expression
[62c6cfa]80                if ( ! typeofType->expr ) return typeofType;
[f441c88]81
[92355883]82    bool isBasetypeof = typeofType->is_basetypeof;
83    auto oldQuals = typeofType->get_qualifiers().val;
[f441c88]84
[92355883]85    Type* newType;
[62c6cfa]86                if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
[92355883]87        // typeof wrapping type
88        newType = tyExpr->type;
89        tyExpr->type = nullptr;
90        delete tyExpr;
91    } else {
92        // typeof wrapping expression
[62c6cfa]93                        Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
94                        assert( newExpr->result && ! newExpr->result->isVoid() );
[92355883]95        newType = newExpr->result;
96        newExpr->result = nullptr;
97        delete typeofType;
98        delete newExpr;
99    }
100
101    // clear qualifiers for base, combine with typeoftype quals in any case
[62c6cfa]102    if ( isBasetypeof ) {
103                        // replace basetypeof(<enum>) by int
104                        if ( dynamic_cast<EnumInstType*>(newType) ) {
105                                Type* newerType =
106                                        new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
107                                        newType->attributes };
108                                delete newType;
109                                newType = newerType;
110                        }
111                        newType->get_qualifiers().val
112                                = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
113                } else {
[92355883]114        newType->get_qualifiers().val |= oldQuals;
115    }
[a6f26ca]116
[92355883]117    return newType;
118}
[c8e4d2f8]119
[0f6a7752]120namespace {
[92355883]121struct ResolveTypeof_new : public ast::WithShortCircuiting {
[62c6cfa]122    const ResolveContext & context;
[0f6a7752]123
[62c6cfa]124                ResolveTypeof_new( const ResolveContext & context ) :
125                        context( context ) {}
[0f6a7752]126
[62c6cfa]127                void previsit( const ast::TypeofType * ) { visit_children = false; }
[0f6a7752]128
[62c6cfa]129        const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
[92355883]130        // pass on null expression
[62c6cfa]131            if ( ! typeofType->expr ) return typeofType;
[92355883]132
[62c6cfa]133            ast::ptr< ast::Type > newType;
134            if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
[92355883]135            // typeof wrapping type
136            newType = tyExpr->type;
137        } else {
138            // typeof wrapping expression
139            ast::TypeEnvironment dummy;
[62c6cfa]140            ast::ptr< ast::Expr > newExpr =
141                resolveInVoidContext( typeofType->expr, context, dummy );
142            assert( newExpr->result && ! newExpr->result->isVoid() );
[92355883]143            newType = newExpr->result;
144        }
145
146        // clear qualifiers for base, combine with typeoftype quals regardless
[62c6cfa]147        if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
[92355883]148            // replace basetypeof(<enum>) by int
[62c6cfa]149                                if ( newType.as< ast::EnumInstType >() ) {
150                                        newType = new ast::BasicType{
151                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
[92355883]152            }
[62c6cfa]153                                reset_qualifiers(
154                                        newType,
155                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
[92355883]156        } else {
[62c6cfa]157                                add_qualifiers( newType, typeofType->qualifiers );
[92355883]158        }
[0f6a7752]159
[92355883]160        return newType.release();
161    }
162};
[62c6cfa]163} // anonymous namespace
[0f6a7752]164
[62c6cfa]165const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
166        ast::Pass< ResolveTypeof_new > mutator( context );
167        return type->accept( mutator );
[0f6a7752]168}
169
[0dd9a5e]170struct FixArrayDimension {
[62c6cfa]171        const ResolveContext & context;
172        FixArrayDimension(const ResolveContext & context) : context( context ) {}
173
174        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
175                if (!arrayType->dimension) return arrayType;
176                auto mutType = mutate(arrayType);
177                auto globalSizeType = context.global.sizeType;
178                ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
179                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
180
181                if (InitTweak::isConstExpr(mutType->dimension)) {
182                        mutType->isVarLen = ast::LengthFlag::FixedLen;
183                }
184                else {
185                        mutType->isVarLen = ast::LengthFlag::VariableLen;
186                }
187                return mutType;
188        }
[c1e66d9]189};
190
[62c6cfa]191const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
192        ast::Pass<FixArrayDimension> visitor(context);
193        return type->accept(visitor);
[0dd9a5e]194}
195
[62c6cfa]196const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
[92355883]197    if (decl->isTypeFixed) {
198        return decl;
199    }
200
201    auto mutDecl = mutate(decl);
202    fixObjectInit(decl, context);
203    {
204        auto resolvedType = resolveTypeof(decl->type, context);
205        resolvedType = fixArrayType(resolvedType, context);
206        mutDecl->type = resolvedType;
207    }
208
209    // Do not mangle unnamed variables.
210    if (!mutDecl->name.empty()) {
211        mutDecl->mangleName = Mangle::mangle(mutDecl);
212    }
213
214    mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
215    mutDecl->isTypeFixed = true;
216    return mutDecl;
217}
[94fa946]218
[92355883]219const ast::ObjectDecl *fixObjectInit(const ast::ObjectDecl *decl,
220                                     const ResolveContext &context) {
[62c6cfa]221    if (decl->isTypeFixed) {
[92355883]222        return decl;
223    }
224
[62c6cfa]225    auto mutDecl = mutate(decl);
226
227    if ( auto mutListInit = mutDecl->init.as<ast::ListInit>() ) {
228        // std::list<ast::Designation *> newDesignations;       
229
230        for ( size_t k = 0; k < mutListInit->designations.size(); k++ ) {
231            const ast::Designation *des = mutListInit->designations[k].get();
232            // Desination here
[f033d01]233            ast::Designation * newDesignation = new ast::Designation(des->location);
[c7616dd]234            std::deque<ast::ptr<ast::Expr>> newDesignators;
235
236            for ( ast::ptr<ast::Expr> designator : des->designators ) {
237                // Stupid flag variable for development, to be removed
238                // bool mutated = false;
239                if ( const ast::NameExpr * designatorName = designator.as<ast::NameExpr>() ) {
240                    auto candidates = context.symtab.lookupId(designatorName->name);
241                    // Does not work for the overloading case currently
242                    // assert( candidates.size() == 1 );
243                    if ( candidates.size() != 1 ) return mutDecl;
244                    auto candidate = candidates.at(0);
245                    if ( const ast::EnumInstType * enumInst = dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type())) {
246                        // determine that is an enumInst, swap it with its const value
247                        assert( candidates.size() == 1 );
248                        const ast::EnumDecl * baseEnum = enumInst->base;
249                        // Need to iterate over all enum value to find the initializer to swap
250                        for ( size_t m = 0; m < baseEnum->members.size(); ++m ) {
251                            const ast::ObjectDecl * mem = baseEnum->members.at(m).as<const ast::ObjectDecl>();
252                            if ( baseEnum->members.at(m)->name == designatorName->name ) {
253                                assert(mem);
254                                newDesignators.push_back( ast::ConstantExpr::from_int(designator->location, m) );
255                                // mutated = true;
256                                break;
[62c6cfa]257                            }
258                        }
[c7616dd]259                    } else {
260                        newDesignators.push_back( des->designators.at(0) );
[62c6cfa]261                    }
[92355883]262                } else {
[c7616dd]263                    newDesignators.push_back( des->designators.at(0) );
[62c6cfa]264                }
[c7616dd]265            }           
266           
[f033d01]267            newDesignation->designators = newDesignators;
268            mutListInit = ast::mutate_field_index(mutListInit, &ast::ListInit::designations, k, newDesignation);
[c7616dd]269           
[62c6cfa]270        }
271    }
[92355883]272    return mutDecl;
[16ba4a6]273}
274
[92355883]275}  // namespace ResolvExpr
[a32b204]276
277// Local Variables: //
278// tab-width: 4 //
279// mode: c++ //
280// compile-command: "make install" //
281// End: //
Note: See TracBrowser for help on using the repository browser.