source: src/InitTweak/FixGlobalInit.cpp@ 13481af0

Last change on this file since 13481af0 was 13481af0, checked in by Peter A. Buhr <pabuhr@…>, 4 days ago

remove addDataSectionAttribute hack and handle dynamic initialization of const definitions by removing the const after resolution

  • Property mode set to 100644
File size: 4.7 KB
RevLine 
[711eee5]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//
[c92bdcc]7// FixGlobalInit.cpp --
[711eee5]8//
9// Author : Rob Schluntz
10// Created On : Mon May 04 15:14:56 2016
[ca35c51]11// Last Modified By : Peter A. Buhr
[13481af0]12// Last Modified On : Thu Jul 2 16:39:52 2026
13// Update Count : 35
[711eee5]14//
15
[c92bdcc]16#include "FixGlobalInit.hpp"
[d180746]17
[13481af0]18#include <set>
[ea6332d]19#include <cassert> // for assert
[d180746]20#include <stddef.h> // for NULL
21#include <algorithm> // for replace_if
22
[490fb92e]23#include "AST/Expr.hpp"
24#include "AST/Node.hpp"
25#include "AST/Pass.hpp"
[c92bdcc]26#include "Common/UniqueName.hpp" // for UniqueName
27#include "InitTweak.hpp" // for isIntrinsicSingleArgCallStmt
[490fb92e]28
[711eee5]29namespace InitTweak {
[490fb92e]30
[8984003]31namespace {
32
33class GlobalFixer : public ast::WithShortCircuiting {
34public:
35 void previsit(const ast::ObjectDecl *);
36 void previsit(const ast::FunctionDecl *) { visit_children = false; }
37 void previsit(const ast::StructDecl *) { visit_children = false; }
38 void previsit(const ast::UnionDecl *) { visit_children = false; }
39 void previsit(const ast::EnumDecl *) { visit_children = false; }
40 void previsit(const ast::TraitDecl *) { visit_children = false; }
41 void previsit(const ast::TypeDecl *) { visit_children = false; }
42
[13481af0]43 bool pass = false;
[8984003]44 std::list< ast::ptr<ast::Stmt> > initStmts;
45 std::list< ast::ptr<ast::Stmt> > destroyStmts;
[13481af0]46 std::set< std::string > constDeclsMnames;
[8984003]47};
48
49void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
50 auto mutDecl = mutate(objDecl);
51 assertf(mutDecl == objDecl, "Global object decl must be unique");
[13481af0]52 if ( ! pass ) { // pass 1
53 auto ctorInit = objDecl->init.as<ast::ConstructorInit>();
54 if ( nullptr == ctorInit ) return;
55
56 // a decision should have been made by the resolver, so ctor and init are not both non-NULL
57 assert( !ctorInit->ctor || !ctorInit->init );
58
59 const ast::Stmt * dtor = ctorInit->dtor;
60 if ( dtor && !isIntrinsicSingleArgCallStmt( dtor ) ) {
61 // don't need to call intrinsic dtor, because it does nothing, but
62 // non-intrinsic dtors must be called
63 destroyStmts.push_front( dtor );
64 } // if
65 if ( const ast::Stmt * ctor = ctorInit->ctor ) {
66 if ( mutDecl->type->is_const() ) {
67 // Store names of all declarations with const qualifier and initializer for second pass.
68 constDeclsMnames.emplace( mutDecl->mangleName );
69 }
70 initStmts.push_back( ctor );
71 mutDecl->init = nullptr;
72 } else if ( const ast::Init * init = ctorInit->init ) {
73 mutDecl->init = init;
74 } else {
75 // no constructor and no initializer, which is okay
76 mutDecl->init = nullptr;
77 }
78 } else { // pass 2
79 // Remove const qualifier from matching names, covering all forward declaration(s) and definition.
80 if ( constDeclsMnames.find( objDecl->mangleName ) != constDeclsMnames.end() ) {
81 ast::Type * fred = const_cast<ast::Type *>(mutDecl->get_type());
82 fred->set_const( false );
83 } // if
[490fb92e]84 }
[8984003]85}
86
87} // namespace
88
89void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
90 ast::Pass<GlobalFixer> fixer;
[13481af0]91
92 // First pass fixes global initialization.
93 accept_all( translationUnit, fixer );
[8984003]94
95 // Say these magic declarations come at the end of the file.
96 CodeLocation const & location = translationUnit.decls.back()->location;
97
98 if ( !fixer.core.initStmts.empty() ) {
99 std::vector<ast::ptr<ast::Expr>> ctorParams;
100 if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
101 auto initFunction = new ast::FunctionDecl(location,
[37273c8]102 "__global_init__", {}, {}, {}, {},
[8984003]103 new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
104 ast::Storage::Static, ast::Linkage::C,
105 {new ast::Attribute("constructor", std::move(ctorParams))});
106
107 translationUnit.decls.emplace_back( initFunction );
108 } // if
109
110 if ( !fixer.core.destroyStmts.empty() ) {
111 std::vector<ast::ptr<ast::Expr>> dtorParams;
112 if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
113 auto destroyFunction = new ast::FunctionDecl( location,
[37273c8]114 "__global_destroy__", {}, {}, {}, {},
[8984003]115 new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
116 ast::Storage::Static, ast::Linkage::C,
117 {new ast::Attribute("destructor", std::move(dtorParams))});
118
119 translationUnit.decls.emplace_back(destroyFunction);
120 } // if
[13481af0]121
122 fixer.core.pass = ! fixer.core.pass;
123 // Second pass, removes const qualifiers so declarations appear in mutable .data section.
124 // Note, the resolver has already checked for const-ness, so C only has to get the initialization correct.
125 accept_all(translationUnit, fixer);
[8984003]126}
[490fb92e]127
[711eee5]128} // namespace InitTweak
129
130// Local Variables: //
131// tab-width: 4 //
132// mode: c++ //
133// compile-command: "make install" //
134// End: //
Note: See TracBrowser for help on using the repository browser.