source: src/CodeGen/LinkOnce.cpp@ d8a3073

stuck-waitfor-destruct
Last change on this file since d8a3073 was d8a3073, checked in by Matthew Au-Yeung <mw2auyeu@…>, 2 months ago

Set top level autogen cfa_linkonce

  • Remove default static and inline
  • Add pass to autogen functions in lib to have default visibility
  • Add fix for union ctor with array constructor passing pointer to array instead of array itself. Previous changes brought light the compilation error.
  • Note: found compilation trying to invoke union operator with array in cfa
  • Property mode set to 100644
File size: 4.3 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.cpp -- 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.hpp"
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 "CompilationState.hpp"
25#include "InitTweak/InitTweak.hpp"
26
27namespace CodeGen {
28
29namespace {
30
31bool is_cfa_linkonce( ast::Attribute const * attr ) {
32 return "cfa_linkonce" == attr->name;
33}
34
35bool is_section_attribute( ast::Attribute const * attr ) {
36 return "section" == attr->name;
37}
38
39bool is_visibility_attribute( ast::Attribute const * attr ) {
40 return "visibility" == attr->name;
41}
42
43struct LinkOnceCore : public ast::WithShortCircuiting {
44 void previsit( ast::Decl const * ) {
45 visit_children = false;
46 }
47
48 ast::DeclWithType const * postvisit( ast::DeclWithType const * decl ) {
49 // Check to see if we have to mutate, because should be uncommon.
50 {
51 auto & attributes = decl->attributes;
52 auto found = std::find_if( attributes.begin(), attributes.end(),
53 is_cfa_linkonce );
54 if ( attributes.end() == found ) return decl;
55 }
56 auto mutDecl = mutate( decl );
57 auto & attributes = mutDecl->attributes;
58
59 // Remove all conflicting section attributes.
60 erase_if( attributes, is_section_attribute );
61
62 // Get the attribute, and overwrite it as a section attribute.
63 auto found = std::find_if( attributes.begin(), attributes.end(),
64 is_cfa_linkonce );
65 assert( attributes.end() != found );
66 ast::Attribute * attribute = found->get_and_mutate();
67 assert( attribute->params.empty() );
68
69 attribute->name = "section";
70 attribute->params.push_back(
71 ast::ConstantExpr::from_string( mutDecl->location,
72 ".gnu.linkonce." + decl->mangleName
73 )
74 );
75
76 attributes.push_back( new ast::Attribute( "visibility", {
77 ast::ConstantExpr::from_string( mutDecl->location, "default" )
78 } ) );
79
80 // Mark as used so GCC does not warn about unused definitions
81 // in translation units that include but don't call the function.
82 attributes.push_back( new ast::Attribute( "used" ) );
83
84 return mutDecl;
85 }
86};
87
88/// Adds visibility("default") to autogen CFA autogen function definitions so they
89/// are exported from shared libraries compiled with -fvisibility=hidden.
90struct AutogenDefaultVisibility {
91 int funcDepth = 0;
92
93 void previsit( ast::FunctionDecl const * ) {
94 funcDepth++;
95 }
96
97 ast::FunctionDecl const * postvisit( ast::FunctionDecl const * decl ) {
98 funcDepth--;
99 // Only top-level function definitions (not nested).
100 if ( funcDepth > 0 ) return decl;
101 // Only CFA-mangled, non-builtin, non-static, non-inline functions.
102 if ( !decl->linkage.is_mangled ) return decl;
103 if ( decl->linkage.is_builtin ) return decl;
104 if ( decl->storage.is_static || decl->funcSpec.is_inline ) return decl;
105
106 // Only definitions (functions with bodies).
107 if ( !decl->stmts ) return decl;
108
109 // Only constructors, destructors, and assignment operators —
110 // the functions that cfa_linkonce autogen functions call on member types.
111 if ( !InitTweak::isDefaultConstructor( decl )
112 && !InitTweak::isCopyConstructor( decl )
113 && !InitTweak::isDestructor( decl )
114 && !InitTweak::isAssignment( decl ) ) return decl;
115
116 // Skip if already has a visibility attribute.
117 auto & attributes = decl->attributes;
118 auto found = std::find_if( attributes.begin(), attributes.end(),
119 is_visibility_attribute );
120 if ( attributes.end() != found ) return decl;
121
122 auto mutDecl = mutate( decl );
123 mutDecl->attributes.push_back( new ast::Attribute( "visibility", {
124 ast::ConstantExpr::from_string( mutDecl->location, "default" )
125 } ) );
126 return mutDecl;
127 }
128};
129
130} // namespace
131
132void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
133 ast::Pass<LinkOnceCore>::run( translationUnit );
134
135 // When building libcfa (-cfalib), add visibility("default") to CFA
136 // function definitions so they are exported despite -fvisibility=hidden.
137 if ( buildingLibrary() ) {
138 ast::Pass<AutogenDefaultVisibility>::run( translationUnit );
139 }
140}
141
142} // namespace CodeGen
Note: See TracBrowser for help on using the repository browser.