source: src/ResolvExpr/ResolveTypeof.cc @ 9ddcee1

Last change on this file since 9ddcee1 was 2908f08, checked in by Andrew Beach <ajbeach@…>, 7 months ago

Most of ResolvExpr? was written before the new style standard. Some files updated, focus on headers.

  • Property mode set to 100644
File size: 7.0 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/utility.h"       // for copy
27#include "InitTweak/InitTweak.h"  // for isConstExpr
[92355883]28#include "RenameVars.h"
29#include "Resolver.h"  // for resolveInVoidContext
30#include "SymTab/Mangler.h"
[51b7345]31
32namespace ResolvExpr {
[c8e4d2f8]33
[0f6a7752]34namespace {
[2908f08]35
[0bd3faf]36struct ResolveTypeof : public ast::WithShortCircuiting {
[62c6cfa]37    const ResolveContext & context;
[0f6a7752]38
[0bd3faf]39                ResolveTypeof( const ResolveContext & context ) :
[62c6cfa]40                        context( context ) {}
[0f6a7752]41
[62c6cfa]42                void previsit( const ast::TypeofType * ) { visit_children = false; }
[0f6a7752]43
[62c6cfa]44        const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
[92355883]45        // pass on null expression
[62c6cfa]46            if ( ! typeofType->expr ) return typeofType;
[92355883]47
[62c6cfa]48            ast::ptr< ast::Type > newType;
49            if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
[92355883]50            // typeof wrapping type
51            newType = tyExpr->type;
52        } else {
53            // typeof wrapping expression
54            ast::TypeEnvironment dummy;
[62c6cfa]55            ast::ptr< ast::Expr > newExpr =
56                resolveInVoidContext( typeofType->expr, context, dummy );
57            assert( newExpr->result && ! newExpr->result->isVoid() );
[92355883]58            newType = newExpr->result;
59        }
60
61        // clear qualifiers for base, combine with typeoftype quals regardless
[62c6cfa]62        if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
[92355883]63            // replace basetypeof(<enum>) by int
[62c6cfa]64                                if ( newType.as< ast::EnumInstType >() ) {
65                                        newType = new ast::BasicType{
66                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
[92355883]67            }
[62c6cfa]68                                reset_qualifiers(
69                                        newType,
70                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
[92355883]71        } else {
[62c6cfa]72                                add_qualifiers( newType, typeofType->qualifiers );
[92355883]73        }
[0f6a7752]74
[92355883]75        return newType.release();
76    }
77};
[2908f08]78
[62c6cfa]79} // anonymous namespace
[0f6a7752]80
[62c6cfa]81const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
[0bd3faf]82        ast::Pass< ResolveTypeof > mutator( context );
[62c6cfa]83        return type->accept( mutator );
[0f6a7752]84}
85
[0dd9a5e]86struct FixArrayDimension {
[62c6cfa]87        const ResolveContext & context;
88        FixArrayDimension(const ResolveContext & context) : context( context ) {}
89
90        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
91                if (!arrayType->dimension) return arrayType;
92                auto mutType = mutate(arrayType);
93                auto globalSizeType = context.global.sizeType;
94                ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
95                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
96
97                if (InitTweak::isConstExpr(mutType->dimension)) {
98                        mutType->isVarLen = ast::LengthFlag::FixedLen;
99                }
100                else {
101                        mutType->isVarLen = ast::LengthFlag::VariableLen;
102                }
103                return mutType;
104        }
[c1e66d9]105};
106
[62c6cfa]107const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
108        ast::Pass<FixArrayDimension> visitor(context);
109        return type->accept(visitor);
[0dd9a5e]110}
111
[62c6cfa]112const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
[92355883]113    if (decl->isTypeFixed) {
114        return decl;
115    }
116
117    auto mutDecl = mutate(decl);
118    fixObjectInit(decl, context);
119    {
120        auto resolvedType = resolveTypeof(decl->type, context);
121        resolvedType = fixArrayType(resolvedType, context);
122        mutDecl->type = resolvedType;
123    }
124
125    // Do not mangle unnamed variables.
126    if (!mutDecl->name.empty()) {
127        mutDecl->mangleName = Mangle::mangle(mutDecl);
128    }
129
130    mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
131    mutDecl->isTypeFixed = true;
132    return mutDecl;
133}
[94fa946]134
[92355883]135const ast::ObjectDecl *fixObjectInit(const ast::ObjectDecl *decl,
136                                     const ResolveContext &context) {
[62c6cfa]137    if (decl->isTypeFixed) {
[92355883]138        return decl;
139    }
140
[62c6cfa]141    auto mutDecl = mutate(decl);
142
143    if ( auto mutListInit = mutDecl->init.as<ast::ListInit>() ) {
144        // std::list<ast::Designation *> newDesignations;       
145
146        for ( size_t k = 0; k < mutListInit->designations.size(); k++ ) {
147            const ast::Designation *des = mutListInit->designations[k].get();
148            // Desination here
[f033d01]149            ast::Designation * newDesignation = new ast::Designation(des->location);
[c7616dd]150            std::deque<ast::ptr<ast::Expr>> newDesignators;
151
152            for ( ast::ptr<ast::Expr> designator : des->designators ) {
153                // Stupid flag variable for development, to be removed
154                // bool mutated = false;
155                if ( const ast::NameExpr * designatorName = designator.as<ast::NameExpr>() ) {
156                    auto candidates = context.symtab.lookupId(designatorName->name);
157                    // Does not work for the overloading case currently
158                    // assert( candidates.size() == 1 );
159                    if ( candidates.size() != 1 ) return mutDecl;
160                    auto candidate = candidates.at(0);
161                    if ( const ast::EnumInstType * enumInst = dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type())) {
162                        // determine that is an enumInst, swap it with its const value
163                        assert( candidates.size() == 1 );
164                        const ast::EnumDecl * baseEnum = enumInst->base;
165                        // Need to iterate over all enum value to find the initializer to swap
166                        for ( size_t m = 0; m < baseEnum->members.size(); ++m ) {
167                            const ast::ObjectDecl * mem = baseEnum->members.at(m).as<const ast::ObjectDecl>();
168                            if ( baseEnum->members.at(m)->name == designatorName->name ) {
169                                assert(mem);
170                                newDesignators.push_back( ast::ConstantExpr::from_int(designator->location, m) );
171                                // mutated = true;
172                                break;
[62c6cfa]173                            }
174                        }
[c7616dd]175                    } else {
176                        newDesignators.push_back( des->designators.at(0) );
[62c6cfa]177                    }
[92355883]178                } else {
[c7616dd]179                    newDesignators.push_back( des->designators.at(0) );
[62c6cfa]180                }
[c7616dd]181            }           
182           
[f033d01]183            newDesignation->designators = newDesignators;
184            mutListInit = ast::mutate_field_index(mutListInit, &ast::ListInit::designations, k, newDesignation);
[c7616dd]185           
[62c6cfa]186        }
187    }
[92355883]188    return mutDecl;
[16ba4a6]189}
190
[92355883]191}  // namespace ResolvExpr
[a32b204]192
193// Local Variables: //
194// tab-width: 4 //
195// mode: c++ //
196// compile-command: "make install" //
197// End: //
Note: See TracBrowser for help on using the repository browser.