source: src/InitTweak/FixGlobalInit.cc @ d734fa1

Last change on this file since d734fa1 was 37273c8, checked in by Andrew Beach <ajbeach@…>, 11 months ago

Removed the old-ast-compatable FunctionDecl? constructor. However, enough cases pass nothing polymorphic along some of the uses of the constructor now go to a new monomorphic function constructor.

  • Property mode set to 100644
File size: 3.8 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// FixGlobalInit.cc --
8//
9// Author           : Rob Schluntz
10// Created On       : Mon May 04 15:14:56 2016
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Dec 13 23:41:10 2019
13// Update Count     : 19
14//
15
16#include "FixGlobalInit.h"
17
18#include <cassert>                 // for assert
19#include <stddef.h>                // for NULL
20#include <algorithm>               // for replace_if
21
22#include "AST/Expr.hpp"
23#include "AST/Node.hpp"
24#include "AST/Pass.hpp"
25#include "Common/UniqueName.h"     // for UniqueName
26#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
27
28namespace InitTweak {
29
30namespace {
31
32class GlobalFixer : public ast::WithShortCircuiting {
33public:
34        void previsit(const ast::ObjectDecl *);
35        void previsit(const ast::FunctionDecl *) { visit_children = false; }
36        void previsit(const ast::StructDecl *) { visit_children = false; }
37        void previsit(const ast::UnionDecl *) { visit_children = false; }
38        void previsit(const ast::EnumDecl *) { visit_children = false; }
39        void previsit(const ast::TraitDecl *) { visit_children = false; }
40        void previsit(const ast::TypeDecl *) { visit_children = false; }
41
42        std::list< ast::ptr<ast::Stmt> > initStmts;
43        std::list< ast::ptr<ast::Stmt> > destroyStmts;
44};
45
46void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
47        auto mutDecl = mutate(objDecl);
48        assertf(mutDecl == objDecl, "Global object decl must be unique");
49        auto ctorInit = objDecl->init.as<ast::ConstructorInit>();
50        if ( nullptr == ctorInit ) return;
51
52        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
53        assert( !ctorInit->ctor || !ctorInit->init );
54
55        const ast::Stmt * dtor = ctorInit->dtor;
56        if ( dtor && !isIntrinsicSingleArgCallStmt( dtor ) ) {
57                // don't need to call intrinsic dtor, because it does nothing, but
58                // non-intrinsic dtors must be called
59                destroyStmts.push_front( dtor );
60        } // if
61        if ( const ast::Stmt * ctor = ctorInit->ctor ) {
62                addDataSectionAttribute(mutDecl);
63                initStmts.push_back( ctor );
64                mutDecl->init = nullptr;
65        } else if ( const ast::Init * init = ctorInit->init ) {
66                mutDecl->init = init;
67        } else {
68                // no constructor and no initializer, which is okay
69                mutDecl->init = nullptr;
70        }
71}
72
73} // namespace
74
75void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
76        ast::Pass<GlobalFixer> fixer;
77        accept_all(translationUnit, fixer);
78
79        // Say these magic declarations come at the end of the file.
80        CodeLocation const & location = translationUnit.decls.back()->location;
81
82        if ( !fixer.core.initStmts.empty() ) {
83                std::vector<ast::ptr<ast::Expr>> ctorParams;
84                if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
85                auto initFunction = new ast::FunctionDecl(location,
86                        "__global_init__", {}, {}, {}, {},
87                        new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
88                        ast::Storage::Static, ast::Linkage::C,
89                        {new ast::Attribute("constructor", std::move(ctorParams))});
90
91                translationUnit.decls.emplace_back( initFunction );
92        } // if
93
94        if ( !fixer.core.destroyStmts.empty() ) {
95                std::vector<ast::ptr<ast::Expr>> dtorParams;
96                if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
97                auto destroyFunction = new ast::FunctionDecl( location,
98                        "__global_destroy__", {}, {}, {}, {},
99                        new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
100                        ast::Storage::Static, ast::Linkage::C,
101                        {new ast::Attribute("destructor", std::move(dtorParams))});
102
103                translationUnit.decls.emplace_back(destroyFunction);
104        } // if
105}
106
107} // namespace InitTweak
108
109// Local Variables: //
110// tab-width: 4 //
111// mode: c++ //
112// compile-command: "make install" //
113// End: //
Note: See TracBrowser for help on using the repository browser.