source: src/CodeGen/LinkOnce.cc @ d3652df

Last change on this file since d3652df was 3cbe320, checked in by Andrew Beach <ajbeach@…>, 8 months ago

Translated the Link-Once pass to the new ast.

  • Property mode set to 100644
File size: 3.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2021 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// LinkOnce.cc -- Translate the cfa_linkonce attribute.
8//
9// Author           : Andrew Beach
10// Created On       : Thur May 13 10:10:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Oct  4 10:52:00 2023
13// Update Count     : 1
14//
15
16#include "LinkOnce.h"
17
18#include <algorithm>
19
20#include "AST/Attribute.hpp"
21#include "AST/Decl.hpp"
22#include "AST/Expr.hpp"
23#include "AST/Pass.hpp"
24#include "Common/PassVisitor.h"       // for PassVisitor, WithShortCircuiting
25
26namespace CodeGen {
27
28namespace {
29
30bool is_cfa_linkonce_old( Attribute const * attr ) {
31        return std::string("cfa_linkonce") == attr->name;
32}
33
34bool is_section_attribute_old( Attribute const * attr ) {
35        return std::string("section") == attr->name;
36}
37
38class LinkOnceVisitorCore : public WithShortCircuiting {
39public:
40        void previsit( Declaration * ) {
41                visit_children = false;
42        }
43
44        void previsit( DeclarationWithType * decl ) {
45                std::list< Attribute * > & attributes = decl->attributes;
46                // See if we can find the element:
47                auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );
48                if ( attributes.end() != found ) {
49                        // Remove any other sections:
50                        attributes.remove_if( is_section_attribute_old );
51                        // Iterator to the cfa_linkonce attribute should still be valid.
52                        Attribute * attribute = *found;
53                        assert( attribute->parameters.empty() );
54                        assert( !decl->mangleName.empty() );
55                        // Overwrite the attribute in place.
56                        const std::string section_name = ".gnu.linkonce." + decl->mangleName;
57                        attribute->name = "section";
58                        attribute->parameters.push_back(
59                                new ConstantExpr( Constant::from_string( section_name ) )
60                        );
61
62                        // Unconditionnaly add "visibility(default)" to anything with gnu.linkonce
63                        // visibility is a mess otherwise
64                        attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));
65
66                }
67                visit_children = false;
68        }
69};
70
71bool is_cfa_linkonce( ast::Attribute const * attr ) {
72        return "cfa_linkonce" == attr->name;
73}
74
75bool is_section_attribute( ast::Attribute const * attr ) {
76        return "section" == attr->name;
77}
78
79struct LinkOnceCore : public ast::WithShortCircuiting {
80        void previsit( ast::Decl const * ) {
81                visit_children = false;
82        }
83
84        ast::DeclWithType const * postvisit( ast::DeclWithType const * decl ) {
85                // Check to see if we have to mutate, because should be uncommon.
86                {
87                        auto & attributes = decl->attributes;
88                        auto found = std::find_if( attributes.begin(), attributes.end(),
89                                        is_cfa_linkonce );
90                        if ( attributes.end() == found ) return decl;
91                }
92                auto mutDecl = mutate( decl );
93                auto & attributes = mutDecl->attributes;
94
95                // Remove all conflicting section attributes.
96                erase_if( attributes, is_section_attribute );
97
98                // Get the attribute, and overwrite it as a section attribute.
99                auto found = std::find_if( attributes.begin(), attributes.end(),
100                                is_cfa_linkonce );
101                assert( attributes.end() != found );
102                ast::Attribute * attribute = found->get_and_mutate();
103                assert( attribute->params.empty() );
104                assert( !decl->mangleName.empty() );
105
106                attribute->name = "section";
107                attribute->params.push_back(
108                        ast::ConstantExpr::from_string( mutDecl->location,
109                                ".gnu.linkonce." + decl->mangleName
110                        )
111                );
112
113                // Unconditionnaly add "visibility(default)" to anything with
114                // .gnu.linkonce visibility is a mess otherwise.
115                attributes.push_back( new ast::Attribute( "visibility", {
116                        ast::ConstantExpr::from_string( mutDecl->location, "default" )
117                } ) );
118                return mutDecl;
119        }
120};
121
122} // namespace
123
124void translateLinkOnce( std::list< Declaration *> & translationUnit ) {
125        PassVisitor<LinkOnceVisitorCore> translator;
126        acceptAll( translationUnit, translator );
127}
128
129void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
130        ast::Pass<LinkOnceCore>::run( translationUnit );
131}
132
133} // namespace CodeGen
Note: See TracBrowser for help on using the repository browser.