source: src/Validate/ImplementEnumFunc.cpp @ bb336a6

Last change on this file since bb336a6 was bb336a6, checked in by JiadaL <j82liang@…>, 6 weeks ago

Fixed the problem when enum use another enumerator as initializer

  • Property mode set to 100644
File size: 17.5 KB
Line 
1#include "AST/Create.hpp"
2#include "AST/Pass.hpp"
3#include "AST/TranslationUnit.hpp"
4#include "CodeGen/OperatorTable.hpp"  // for isCtorDtor, isCtorDtorAssign
5#include "InitTweak/InitTweak.hpp"    // for isAssignment, isCopyConstructor
6namespace Validate {
7
8namespace {
9class EnumAttrFuncGenerator {
10        const ast::EnumDecl* decl;
11        unsigned int functionNesting;
12        const ast::StructDecl* quasi_void_decl;
13        ast::Linkage::Spec proto_linkage;
14
15public:
16        std::list<ast::ptr<ast::Decl>> forwards;
17        std::list<ast::ptr<ast::Decl>> definitions;
18
19        void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&);
20
21        EnumAttrFuncGenerator(
22                        const ast::EnumDecl* decl,
23                        const ast::EnumInstType*,
24                        unsigned int functionNesting )
25                : decl(decl),
26                  functionNesting{functionNesting},
27                  quasi_void_decl(new ast::StructDecl(decl->location, 
28                        "quasi_void", ast::AggregateDecl::Struct,
29                        {}, ast::Linkage::AutoGen)),
30                  proto_linkage{ast::Linkage::Cforall} {}
31
32private:
33        const CodeLocation& getLocation() const { return decl->location; }
34
35        ast::FunctionDecl* genProto(
36                std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
37                std::vector<ast::ptr<ast::DeclWithType>>&& returns) const;
38
39        void produceDecl(const ast::FunctionDecl* decl);
40        void produceForwardDecl(const ast::FunctionDecl* decl);
41
42        const ast::Decl* getDecl() const { return decl; }
43
44        // Implement Bounded trait
45        void genBoundedFunctions();
46        ast::FunctionDecl* genBoundedProto(const char *) const;
47        void genBoundedBody(ast::FunctionDecl* func) const;
48
49        // Implement Serial trait
50        void genSerialTraitFuncs();
51        ast::FunctionDecl* genFromIntProto() const;
52        ast::FunctionDecl* genFromInstanceProto() const;
53        ast::FunctionDecl* genInstToInstFuncProto(const char* func) const;
54        void genFromIntBody(ast::FunctionDecl *) const;
55        void genFromInstanceBody(ast::FunctionDecl *) const;
56        void genSuccPredBody(ast::FunctionDecl *, const char *) const;
57
58        void genTypeNameFunc();
59
60        // Implement TypedEnum trait
61        void genTypedEnumFuncs();
62        void genTypedEnumFunction(const ast::EnumAttribute attr);
63        ast::FunctionDecl* genPosnProto() const;
64        ast::FunctionDecl* genLabelProto() const;
65        ast::FunctionDecl* genValueProto() const;
66        ast::FunctionDecl* genQuasiValueProto() const;
67        ast::FunctionDecl* genTypeNameProto() const;
68
69        void genValueOrLabelBody(
70                ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
71        void genPosnBody(ast::FunctionDecl* func) const;
72        void genQuasiValueBody(ast::FunctionDecl* func) const;
73        void genTypeNameBody(ast::FunctionDecl* func) const;
74
75        // ----------------------------------------------------
76
77        const ast::Init* getAutoInit(const ast::Init* prev) const;
78
79        std::vector<ast::ptr<ast::Init>> genLabelInit() const;
80
81        std::vector<ast::ptr<ast::Init>> genValueInit() const;
82        ast::ObjectDecl* genAttrArrayProto(
83                const ast::EnumAttribute attr, const CodeLocation& location,
84                std::vector<ast::ptr<ast::Init>>& inits) const;
85};
86
87std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
88        std::vector<ast::ptr<ast::Init>> inits;
89        for (size_t i = 0; i < decl->members.size(); i++) {
90                ast::ptr<ast::Decl> mem = decl->members.at(i);
91                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
92                assert(memAsObjectDecl);
93                inits.emplace_back(new ast::SingleInit(
94                        mem->location,
95                        ast::ConstantExpr::from_string(mem->location, mem->name)));
96        }
97        return inits;
98}
99
100std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
101        std::vector<ast::ptr<ast::Init>> inits;
102        for (size_t i = 0; i < decl->members.size(); i++) {
103                ast::ptr<ast::Decl> mem = decl->members.at(i);
104                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
105                assert(memAsObjectDecl);
106                if (auto& init = memAsObjectDecl->init) {
107                        auto singleInit = init.strict_as<ast::SingleInit>();
108                        auto nameExpr = singleInit->value.as<ast::NameExpr>();
109                        if (nameExpr) {
110                                auto name = nameExpr->name;
111                                if (auto it = std::find_if(decl->members.begin(), decl->members.end(), 
112                                        [name](ast::ptr<ast::Decl> mem_decl) {
113                                                return (mem_decl->name == name);
114                                        }); it != std::end(decl->members)
115                                ) {
116                                        // ast::SingleInit* newInit = new ast::SingleInit(
117                                        //      init->location, new ast::CastExpr( nameExpr->location,
118                                        //      nameExpr, new ast::BasicType( ast::BasicKind::UnsignedInt ), ast::ExplicitCast )
119                                        // );
120                                        // auto targetInit = (*it).strict_as<ast::ObjectDecl>()->init;
121                                        // inits.emplace_back( targetInit );
122                                        auto index = std::distance( decl->members.begin(), it );
123                                        auto targetInit = inits.at(index).strict_as<ast::SingleInit>();
124                                        auto targetExpr = targetInit->value;
125                                        inits.push_back( new ast::SingleInit( targetExpr->location, targetExpr ) );
126                                        continue;
127                                }
128                        }
129
130                        inits.emplace_back(memAsObjectDecl->init);
131                } else {
132                        const CodeLocation& location = mem->location;
133                        if (i == 0) {
134                                inits.emplace_back(new ast::SingleInit(
135                                        location, ast::ConstantExpr::from_int(mem->location, 0)));
136                        } else {
137                                inits.emplace_back(getAutoInit(inits.at(i - 1)));
138                        }
139                }
140        }
141        return inits;
142}
143
144const ast::Init* EnumAttrFuncGenerator::getAutoInit(
145        const ast::Init* prev) const {
146        if (prev == nullptr) {
147                return new ast::SingleInit(
148                        getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
149        }
150        auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
151        assert(prevInit);
152        auto prevInitExpr = prevInit->value;
153        if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
154                // Assume no string literal for now
155                return new ast::SingleInit(
156                        getLocation(), ast::ConstantExpr::from_int(
157                                getLocation(), constInit->intValue() + 1));
158        } else {
159                auto untypedThisInit = new ast::UntypedExpr(
160                        getLocation(), new ast::NameExpr(getLocation(), "?++"),
161                        {prevInitExpr});
162                return new ast::SingleInit(getLocation(), untypedThisInit);
163        }
164}
165
166ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
167        std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
168        std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
169        ast::FunctionDecl* decl = new ast::FunctionDecl(
170                // Auto-generated routines use the type declaration's location.
171                getLocation(), std::move(name), {}, {}, std::move(params),
172                std::move(returns),
173                // Only a prototype, no body.
174                nullptr,
175                // Use static storage if we are at the top level.
176                (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
177                proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
178                // Auto-generated routines are inline to avoid conflicts.
179                ast::Function::Specs(ast::Function::Inline));
180        decl->fixUniqueId();
181        return decl;
182}
183
184void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
185        assert(nullptr != decl->stmts);
186
187        definitions.push_back(decl);
188}
189
190void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
191        if (0 != functionNesting) return;
192        ast::FunctionDecl* fwd =
193                (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
194        fwd->fixUniqueId();
195        forwards.push_back(fwd);
196}
197
198ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const {
199    return genProto(
200        "posn",
201        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
202        {new ast::ObjectDecl(getLocation(), "_ret",
203            new ast::BasicType(ast::BasicKind::UnsignedInt))});
204}
205
206ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
207        return genProto(
208                "label",
209                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
210                {new ast::ObjectDecl(
211                        getLocation(), "_ret",
212                        new ast::PointerType(
213                                new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)))});
214}
215
216ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
217        if (decl->isTyped())
218                return genProto(
219                        "value",
220                        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
221                        {new ast::ObjectDecl(getLocation(), "_ret",
222                                                                ast::deepCopy(decl->base))});
223        else
224                return genQuasiValueProto();
225}
226
227ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const {
228        return genProto(
229                "value",
230                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
231                {new ast::ObjectDecl(getLocation(), "_ret",
232                                                new ast::StructInstType(quasi_void_decl))});
233}
234
235ast::FunctionDecl* EnumAttrFuncGenerator::genFromIntProto() const {
236        return genProto(
237                "fromInt",
238                {new ast::ObjectDecl(getLocation(), "_i", new ast::BasicType(ast::BasicKind::UnsignedInt))},
239                {new ast::ObjectDecl(getLocation(), "_ret", new ast::EnumInstType(decl))}
240        );
241}
242
243ast::FunctionDecl* EnumAttrFuncGenerator::genFromInstanceProto() const {
244        return genProto(
245                "fromInstance",
246                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
247                {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))}
248        );
249}
250
251ast::FunctionDecl* EnumAttrFuncGenerator::genTypeNameProto() const {
252        return genProto(
253                "type_name",
254                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
255                {new ast::ObjectDecl(
256                        getLocation(), "_ret",
257                        new ast::PointerType(
258                                new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)))});
259}
260
261void EnumAttrFuncGenerator::genFromIntBody(ast::FunctionDecl* func) const {
262        auto params = func->params;
263        assert( params.size() == 1 );
264        auto param = params.front();
265        auto castExpr = new ast::CastExpr(
266                func->location,
267                new ast::VariableExpr(func->location, param),
268                new ast::EnumInstType(decl),
269                ast::GeneratedFlag::ExplicitCast
270        );
271        func->stmts = new ast::CompoundStmt(
272                func->location, {new ast::ReturnStmt(func->location, castExpr)}
273        );
274}
275
276void EnumAttrFuncGenerator::genFromInstanceBody(ast::FunctionDecl* func) const {
277        auto params = func->params;
278        assert( params.size() == 1 );
279        auto param = params.front();
280        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
281                func->location, "posn", { new ast::VariableExpr(func->location, param) });
282        func->stmts = new ast::CompoundStmt(
283                func->location, {new ast::ReturnStmt(func->location, untyped)}
284        );
285}
286
287void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {
288        auto params = func->params;
289        assert( params.size() == 1 );
290        auto param = params.front();
291        auto enumToInt = new ast::CastExpr(
292                func->location,
293                new ast::VariableExpr(func->location, param),
294                new ast::BasicType(ast::BasicKind::UnsignedInt),
295                ast::GeneratedFlag::ExplicitCast
296        );
297        ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,
298                opt,
299                {enumToInt,
300                ast::ConstantExpr::from_int(func->location, 1)}
301        );
302        auto intToEnum = new ast::CastExpr(
303                func->location,
304                addOneExpr,
305                new ast::EnumInstType( decl ),
306                ast::GeneratedFlag::ExplicitCast
307        );
308        func->stmts = new ast::CompoundStmt(
309                func->location, {
310                        new ast::ReturnStmt(
311                                func->location,
312                                intToEnum
313                        )
314                }
315        );
316}
317
318void EnumAttrFuncGenerator::genSerialTraitFuncs() {
319        ast::FunctionDecl * protos[4] = {
320                genFromIntProto(),
321                genFromInstanceProto(),
322                genInstToInstFuncProto("succ"),
323                genInstToInstFuncProto("pred")
324        };
325        for (auto& proto: protos) produceForwardDecl(proto);
326        genFromIntBody(protos[0]);
327        genFromInstanceBody(protos[1]);
328        genSuccPredBody(protos[2], "?+?");
329        genSuccPredBody(protos[3], "?-?");
330        for (auto& proto: protos) produceDecl(proto);
331}
332
333ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const {
334        return genProto(
335                func,
336                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
337                {new ast::ObjectDecl(getLocation(), "_ret",
338                                     new ast::EnumInstType(decl))});
339}
340
341ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const {
342    return genProto(func, {}, {
343        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
344    });
345}
346
347void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const {
348        const CodeLocation & loc = func->location;
349        auto mem = func->name=="lowerBound"?  decl->members.front() : decl->members.back();
350        // auto expr = new ast::NameExpr( loc, mem->name );
351        auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name );
352        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
353}
354
355void EnumAttrFuncGenerator::genBoundedFunctions() {
356        ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")};
357        for (auto & protos: boundedProtos) {
358                produceForwardDecl(protos);
359                genBoundedBody(protos);
360                produceDecl(protos);
361        }
362}
363
364ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
365        const ast::EnumAttribute attr, const CodeLocation& location,
366        std::vector<ast::ptr<ast::Init>>& inits) const {
367        ast::ArrayType* arrT = new ast::ArrayType(
368                attr == ast::EnumAttribute::Value
369                        ? decl->base
370                        : new ast::PointerType(
371                                new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)),
372                ast::ConstantExpr::from_int(decl->location, decl->members.size()),
373                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
374
375        ast::ObjectDecl* objDecl =
376                new ast::ObjectDecl(
377                        decl->location, decl->getUnmangeldArrayName( attr ),
378                        arrT, new ast::ListInit( location, std::move( inits ) ),
379                        ast::Storage::Static, ast::Linkage::AutoGen );
380
381        return objDecl;
382}
383
384void EnumAttrFuncGenerator::genValueOrLabelBody(
385        ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
386        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
387                func->location, "?[?]",
388                {new ast::NameExpr(func->location, arrDecl->name),
389                new ast::CastExpr(
390                        func->location,
391                        new ast::VariableExpr( func->location, func->params.front() ),
392                        new ast::BasicType( ast::BasicKind::UnsignedInt ),
393                        ast::GeneratedFlag::ExplicitCast
394                )});
395        func->stmts = new ast::CompoundStmt(
396                func->location, {new ast::ReturnStmt(func->location, untyped)});
397}
398
399void EnumAttrFuncGenerator::genQuasiValueBody(ast::FunctionDecl* func) const {
400        auto location = func->location;
401        const ast::ObjectDecl * objDecl = new ast::ObjectDecl(
402                location, "_out", new ast::StructInstType( quasi_void_decl ));
403        const ast::DeclStmt * declStmt = new ast::DeclStmt(location, objDecl);
404        const ast::VariableExpr * varExpr = new ast::VariableExpr(location, objDecl);
405        const ast::ReturnStmt * retStmt = new ast::ReturnStmt(location, varExpr);
406
407        func->stmts = new ast::CompoundStmt(
408                location, {declStmt, retStmt}
409        );
410}
411
412void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
413        auto castExpr = new ast::CastExpr(
414                func->location,
415                new ast::VariableExpr(func->location, func->params.front()),
416                new ast::BasicType( ast::BasicKind::UnsignedInt ),
417                        ast::GeneratedFlag::ExplicitCast);
418        func->stmts = new ast::CompoundStmt(
419                func->location, {new ast::ReturnStmt(func->location, castExpr)});
420}
421
422void EnumAttrFuncGenerator::genTypeNameBody(ast::FunctionDecl* func) const {
423        const ast::Expr * type_name = ast::ConstantExpr::from_string(func->location, decl->name);
424        func->stmts = new ast::CompoundStmt(
425                func->location, {new ast::ReturnStmt(func->location, type_name)}
426        );
427}
428
429void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
430        if (attr == ast::EnumAttribute::Value) {
431                if (decl->isTyped()) {
432                        // TypedEnum's backing arrays
433                        std::vector<ast::ptr<ast::Init>> inits = genValueInit();
434                        ast::ObjectDecl* arrayProto =
435                                genAttrArrayProto(attr, getLocation(), inits);
436                        forwards.push_back(arrayProto);
437
438                        ast::FunctionDecl* funcProto = genValueProto();
439                        produceForwardDecl(funcProto);
440                        genValueOrLabelBody(funcProto, arrayProto);
441                        produceDecl(funcProto);
442                }  else {
443                        ast::FunctionDecl* funcProto = genQuasiValueProto();
444                        produceForwardDecl(funcProto);
445                        genQuasiValueBody(funcProto);
446                        produceDecl(funcProto);
447                }
448        } else if (attr == ast::EnumAttribute::Label) {
449                std::vector<ast::ptr<ast::Init>> inits = genLabelInit();
450                ast::ObjectDecl* arrayProto =
451                        genAttrArrayProto(attr, getLocation(), inits);
452                forwards.push_back(arrayProto);
453                ast::FunctionDecl* funcProto = genLabelProto();
454                produceForwardDecl(funcProto);
455                genValueOrLabelBody(funcProto, arrayProto);
456                produceDecl(funcProto);
457        } else {
458                ast::FunctionDecl* funcProto = genPosnProto();
459                produceForwardDecl(funcProto);
460                genPosnBody(funcProto);
461                produceDecl(funcProto);
462        }
463}
464
465void EnumAttrFuncGenerator::genTypedEnumFuncs() {
466        // genTypedEnumFunction(ast::EnumAttribute::Value);
467        // genTypedEnumFunction(ast::EnumAttribute::Label);
468        // genTypedEnumFunction(ast::EnumAttribute::Posn);
469}
470
471void EnumAttrFuncGenerator::genTypeNameFunc() {
472        ast::FunctionDecl* funcProto = genTypeNameProto();
473        produceForwardDecl(funcProto);
474        genTypeNameBody(funcProto);
475        produceDecl(funcProto);
476}
477
478void EnumAttrFuncGenerator::generateAndAppendFunctions(
479        std::list<ast::ptr<ast::Decl>>& decls) {
480        // Generate the functions (they go into forwards and definitions).
481        // genTypeNameFunc();
482        genTypedEnumFuncs();
483        // genSerialTraitFuncs();
484        // genBoundedFunctions();
485        // Now export the lists contents.
486        decls.splice(decls.end(), forwards);
487        decls.splice(decls.end(), definitions);
488}
489
490// ---------------------------------------------------------
491
492struct ImplementEnumFunc final :
493                public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting {
494        void previsit(const ast::EnumDecl* enumDecl);
495        void previsit(const ast::FunctionDecl* functionDecl);
496        void postvisit(const ast::FunctionDecl* functionDecl);
497
498private:
499        // Current level of nested functions.
500        unsigned int functionNesting = 0;
501};
502
503void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
504        if (!enumDecl->body || !enumDecl->isCfa) return;
505        ast::EnumInstType enumInst(enumDecl->name);
506        enumInst.base = enumDecl;
507        EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
508        // gen.generateAndAppendFunctions(declsToAddAfter);
509}
510
511void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
512        functionNesting += 1;
513}
514
515void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
516        functionNesting -= 1;
517}
518
519} // namespace
520
521void implementEnumFunc(ast::TranslationUnit& translationUnit) {
522        ast::Pass<ImplementEnumFunc>::run(translationUnit);
523}
524
525} // namespace Validate
Note: See TracBrowser for help on using the repository browser.