source: src/ResolvExpr/ResolveTypeof.cc @ c1e66d9

Last change on this file since c1e66d9 was c1e66d9, checked in by JiadaL <j82liang@…>, 5 months ago

Fix designator value in enumerated array and implemented enumerated array with inlined enume declaration

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