source: src/SymTab/TreeStruct.cc @ 6ea8748

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 6ea8748 was 6ea8748, checked in by Andrew Beach <ajbeach@…>, 4 years ago

That should be all the base code for 'tree structures' to work.

  • Property mode set to 100644
File size: 7.0 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// TreeStruct.cc --
8//
9// Author           : Andrew Beach
10// Created On       : Wed Jul 12 14:48:00 2017
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Jul 14 15:49:00 2017
13// Update Count     : 0
14//
15
16#include "Common/PassVisitor.h"
17#include "InitTweak/InitTweak.h"
18#include "SynTree/Attribute.h"
19#include "SynTree/Declaration.h"
20#include "SynTree/Expression.h"
21#include "SynTree/Statement.h"
22#include "SynTree/Type.h"
23#include "SynTree/Mutator.h"
24
25__attribute__((noinline))
26Declaration* searchDeclList(
27        const std::list< Declaration* > & lst,
28        const Declaration * val ) {
29    auto tmp = std::find( lst.begin(), lst.end(), val );
30        return (tmp == lst.end()) ? nullptr : *tmp;
31}
32
33
34class TreeStructExpanderCore : public WithDeclsToAdd {
35        typedef std::pair<StructDecl *, ObjectDecl *> map_pair;
36        typedef std::map<std::string, map_pair> map;
37        typedef std::pair<map::iterator, bool> insert_result;
38        // std::pair<std::map<std::string,
39        //                    std::pair<StructDecl *,
40        //                              ObjectDecl *> >,
41        //           bool>
42
43        // key_name     first first
44        std::string key_name( std::pair<map::iterator, bool> & result )
45        { return result.first->first; }
46        // struct_decl  first second first
47        StructDecl *& struct_decl( std::pair<map::iterator, bool> & result )
48        { return result.first->second.first; }
49        // type_object  first second second
50        ObjectDecl *& type_object( std::pair<map::iterator, bool> & result )
51        { return result.first->second.second; }
52        // key_name     first
53        std::string key_name( map::iterator & it ) { return it->first; }
54        // struct_decl  second first
55        StructDecl *& struct_decl( map::iterator & it )
56        { return it->second.first; }
57        // type_object  second second
58        ObjectDecl *& type_object( map::iterator & it )
59        { return it->second.second; }
60
61        StructDecl * type_object_type;
62
63        map known_structs;
64
65public:
66
67        TreeStructExpanderCore() : type_object_type( nullptr ) {}
68
69        std::string base_type_object_name( std::string struct_name ) {
70                return std::string("type_object_for_") + struct_name;
71        }
72
73        // Throws SemanticError if error is found.
74        Declaration * postmutate( StructDecl * node ) {
75                // Skip all untagged nodes.
76                if ( ! node->get_tagged() ) {
77                        // Although we do grap the type object first.
78                        if ( "__cfa__type_object" == node->get_name() ) {
79                                assert( !type_object_type && "repeated type_object definition" );
80                                type_object_type = node;
81                        }
82                        return node;
83                } else {
84                        assert( type_object_type && "missing type_object definition" );
85                }
86
87                // Track all of the tagged nodes.
88                std::pair<map::iterator, bool> target = known_structs.insert(
89                        std::make_pair( node->get_name(), map_pair( node, nullptr) ) );
90
91                // Validate no conflict (is that does elsewhere?)
92                // New declaration, no conflicting definition possible.
93                if ( target.second ) {
94                        ;
95                // Conflict if they have different parents.
96                } else if ( node->get_parentName() !=
97                            struct_decl( target )->get_parentName() ) {
98                        throw SemanticError("TreeStructs do not share parents.");
99                // Conflict if they both have a body.
100                } else if ( node->has_body() && struct_decl( target )->has_body() ) {
101                        throw SemanticError("TreeStructs with repeated bodies.");
102                // Update to the one with a body.
103                } else if ( node->has_body() ) {
104                        struct_decl( target ) = node;
105                }
106
107                // if ( node->get_name() == node->get_parent_name() )
108                // We might actually use this for a while to say no parent.
109
110                // Validate Parent exists:
111                map::iterator target_parent =
112                        known_structs.find( node->get_parentName() );
113                if ( known_structs.end() == target_parent && node->has_parent() ) {
114                        throw SemanticError( std::string( "No <parent> named " ) +
115                                             node->get_parentName() + " defined." );
116                }
117
118                static Attribute linkonce( "section", std::list<Expression *>{
119                        new NameExpr( "\".gnu.linkonce.exception\"" ) } );
120
121                Expression * parent_address = node->has_parent()
122                        ? (Expression *)new AddressExpr(
123                                new VariableExpr( target_parent->second.second ) )
124                        : (Expression *)new ConstantExpr( Constant::null(
125                                new PointerType( Type::Qualifiers(),
126                                        new StructInstType( Type::Qualifiers(),
127                                                            type_object_type ) ) ) );
128
129                // Insert the declaration of the type object.
130                ObjectDecl * type_object_inst = new ObjectDecl(
131                        base_type_object_name( node->get_name() ),
132                        Type::StorageClasses() /* I think this is none. */,
133                        node->get_linkage(),
134                        nullptr,
135                        new StructInstType(
136                                Type::Qualifiers(),
137                                type_object_type
138                                ),
139                        new ListInit({ new SingleInit( parent_address ) }),
140                        std::list<Attribute *>{ linkonce.clone() }
141                        );
142
143                declsToAddAfter.push_back( type_object_inst );
144
145                type_object( target ) = type_object_inst;
146
147                // Insert a field into the structure.
148                node->get_members().push_front( new ObjectDecl(
149                        "tag",
150                        Type::StorageClasses(),
151                        node->get_linkage(),
152                        nullptr,
153                        new PointerType(
154                                Type::Qualifiers( Type::Const ),
155                                new StructInstType(
156                                        Type::Qualifiers( Type::Const ),
157                                        type_object_type
158                                        )
159                                ),
160                        nullptr /*new SingleInit( new AddressExpr(
161                                new VariableExpr( type_object_inst ) ) )*/
162                        ) );
163
164                return node;
165        }
166
167        DeclarationWithType * postmutate( FunctionDecl * funcDecl ) {
168                if ( ! InitTweak::isConstructor( funcDecl->get_name() ) ) {
169                        return funcDecl;
170                }
171
172                if ( nullptr == funcDecl->get_statements() ) {
173                        return funcDecl;
174                }
175
176                DeclarationWithType * param_one =
177                        funcDecl->get_functionType()->get_parameters().front();
178                Type * param_one_t =
179                        InitTweak::getPointerBase( param_one->get_type() );
180                StructInstType * struct_one_t =
181                        dynamic_cast<StructInstType*>( param_one_t );
182
183                if ( struct_one_t && struct_one_t->get_baseStruct()->get_tagged() ) {
184                        map::iterator target =
185                    known_structs.find( struct_one_t->get_name() );
186                        assertf( known_structs.end() != target,
187                                 "Missing definition of structure." );
188
189                        DeclarationWithType * ptto_field =
190                                dynamic_cast<DeclarationWithType*>(
191                                        struct_decl( target )->get_members().front() );
192                        assertf( ptto_field, "Pointer to type object not found." );
193
194                        Type * mutptr = ptto_field->get_type()->clone();
195                        mutptr->set_const( false );
196                        mutptr = new PointerType(Type::Qualifiers(), mutptr);
197
198                        funcDecl->get_statements()->push_front( new ExprStmt( noLabels,
199                                new UntypedExpr( new NameExpr( "?{}" ),
200                                        std::list<Expression *>{
201                                                new CastExpr(
202                                                        new AddressExpr(
203                                                                new MemberExpr(
204                                                                        ptto_field,
205                                                                        UntypedExpr::createDeref(
206                                                                                new VariableExpr( param_one )
207                                                                                )
208                                                                        )
209                                                                ),
210                                                                mutptr
211                                                        ),
212                                                new AddressExpr(
213                                                        new VariableExpr( type_object( target ) )
214                                                        )
215                                                }
216                                        )
217                                ) );
218                }
219                return funcDecl;
220        }
221};
222
223// ?{}((type_object const**)&this->tag, &<type_object> )
224
225void expand_tree_structs( std::list<Declaration *> & translationUnit ) {
226        PassVisitor<TreeStructExpanderCore> translator;
227        mutateAll( translationUnit, translator );
228}
Note: See TracBrowser for help on using the repository browser.