source: src/SymTab/TreeStruct.cc@ ea5023c

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since ea5023c was 6ea87486, checked in by Andrew Beach <ajbeach@…>, 8 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.