source: src/ControlStruct/ExceptDeclNew.cpp@ 25b0fde

ADT ast-experimental
Last change on this file since 25b0fde was e8616b6, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Changed the default Linkage on ast::ObjectDecl from C to Cforall. There appears to be only one internal name that actually needed to be C.

  • Property mode set to 100644
File size: 15.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 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// ExceptDeclNew.cpp --
8//
9// Author : Andrew Beach
10// Created On : Tue Jul 12 15:50:00 2022
11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Jul 18 11:01:00 2022
13// Update Count : 0
14//
15
16#include "ExceptDecl.h"
17
18#include "AST/Decl.hpp"
19#include "AST/Pass.hpp"
20#include "AST/Print.hpp"
21#include "AST/Type.hpp"
22#include "Virtual/Tables.h"
23
24namespace ControlStruct {
25
26namespace {
27
28std::vector<ast::ptr<ast::Expr>> forallToParams(
29 std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
30 return map_range<std::vector<ast::ptr<ast::Expr>>>( forall,
31 []( ast::ptr<ast::TypeDecl> const & decl ) {
32 return new ast::TypeExpr( decl->location,
33 new ast::TypeInstType( decl->name, decl->kind ) );
34 }
35 );
36}
37
38// A slightly argumented extra constructor, adds a deepCopy.
39ast::StructInstType * namedStructInstType(
40 std::string const & name, ast::CV::Qualifiers qualifiers,
41 std::vector<ast::ptr<ast::Expr>> const & params ) {
42 ast::StructInstType * type = new ast::StructInstType( name, qualifiers );
43 for ( ast::ptr<ast::Expr> const & param : params ) {
44 type->params.push_back( ast::deepCopy( param ) );
45 }
46 return type;
47}
48
49ast::StructInstType * createExceptionInstType(
50 std::string const & exceptionName,
51 std::vector<ast::ptr<ast::Expr>> const & params ) {
52 return namedStructInstType( exceptionName, ast::CV::Qualifiers(), params );
53}
54
55ast::StructInstType * createVTableInstType(
56 std::string const & exceptionName,
57 std::vector<ast::ptr<ast::Expr>> const & params ) {
58 std::string name = Virtual::vtableTypeName( exceptionName );
59 return namedStructInstType( name, ast::CV::Const, params );
60}
61
62ast::StructInstType * createTypeIdInstType(
63 std::string const & exceptionName,
64 std::vector<ast::ptr<ast::Expr>> const & params ) {
65 std::string name = Virtual::typeIdType( exceptionName );
66 return namedStructInstType( name, ast::CV::Const, params );
67}
68
69ast::FunctionType const * createCopyFuncType(
70 std::string const & exceptionName,
71 std::vector<ast::ptr<ast::Expr>> const & params ) {
72 ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
73 type->params.push_back( new ast::PointerType(
74 createExceptionInstType( exceptionName, params ) ) );
75 type->params.push_back( new ast::PointerType(
76 createExceptionInstType( exceptionName, params ) ) );
77 type->returns.push_back( new ast::VoidType() );
78 return type;
79}
80
81ast::FunctionType const * createDtorFuncType(
82 std::string const & exceptionName,
83 std::vector<ast::ptr<ast::Expr>> const & params ) {
84 ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
85 type->params.push_back( new ast::ReferenceType(
86 createExceptionInstType( exceptionName, params ) ) );
87 type->returns.push_back( new ast::VoidType() );
88 return type;
89}
90
91ast::FunctionType const * createMsgFuncType(
92 std::string const & exceptionName,
93 std::vector<ast::ptr<ast::Expr>> const & params ) {
94 ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
95 type->params.push_back( new ast::PointerType(
96 createExceptionInstType( exceptionName, params ) ) );
97 type->returns.push_back( new ast::PointerType(
98 new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) ) );
99 return type;
100}
101
102ast::StructDecl const * createTypeIdStruct(
103 CodeLocation const & location,
104 std::string const & exceptionName,
105 std::vector<ast::ptr<ast::TypeDecl>> const & forallClause ) {
106 ast::StructDecl * decl = new ast::StructDecl( location,
107 Virtual::typeIdType( exceptionName ) );
108 decl->members.push_back( new ast::ObjectDecl(
109 location,
110 "parent",
111 new ast::PointerType(
112 new ast::StructInstType( "__cfavir_type_info", ast::CV::Const ) )
113 ) );
114 decl->body = true;
115 for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
116 decl->params.push_back( ast::deepCopy( param ) );
117 }
118 return decl;
119}
120
121ast::ObjectDecl const * createTypeIdValue(
122 CodeLocation const & location,
123 std::string const & exceptionName,
124 std::vector<ast::ptr<ast::Expr>> const & params ) {
125 ast::StructInstType * typeIdType =
126 createTypeIdInstType( exceptionName, params );
127 return new ast::ObjectDecl(
128 location,
129 Virtual::typeIdName( exceptionName ),
130 typeIdType,
131 new ast::ListInit( location, {
132 new ast::SingleInit( location,
133 new ast::AddressExpr( location,
134 new ast::NameExpr( location, "__cfatid_exception_t" ) ),
135 ast::MaybeConstruct ),
136 }, {}, ast::MaybeConstruct ),
137 ast::Storage::Classes(),
138 ast::Linkage::Cforall,
139 nullptr,
140 { new ast::Attribute( "cfa_linkonce" ) }
141 );
142}
143
144ast::StructDecl const * createExceptionStructForward(
145 CodeLocation const & location,
146 std::string const & exceptionName,
147 std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
148 ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
149 for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
150 decl->params.push_back( ast::deepCopy( param ) );
151 }
152 return decl;
153}
154
155ast::StructDecl const * createVirtualTableStruct(
156 CodeLocation const & location,
157 std::string const & exceptionName,
158 std::vector<ast::ptr<ast::TypeDecl>> const & forall,
159 std::vector<ast::ptr<ast::Expr>> const & params ) {
160 ast::StructInstType * typeIdType =
161 createTypeIdInstType( exceptionName, params );
162 ast::ObjectDecl * typeId = new ast::ObjectDecl(
163 location,
164 "__cfavir_typeid",
165 new ast::PointerType( typeIdType )
166 );
167 ast::ObjectDecl * size = new ast::ObjectDecl(
168 location,
169 "size",
170 new ast::TypeInstType( "size_t", ast::TypeDecl::Dtype )
171 );
172 ast::ObjectDecl * copy = new ast::ObjectDecl(
173 location,
174 "copy",
175 new ast::PointerType( createCopyFuncType( exceptionName, params ) )
176 );
177 ast::ObjectDecl * dtor = new ast::ObjectDecl(
178 location,
179 "^?{}",
180 new ast::PointerType( createDtorFuncType( exceptionName, params ) )
181 );
182 ast::ObjectDecl * msg = new ast::ObjectDecl(
183 location,
184 "msg",
185 new ast::PointerType( createMsgFuncType( exceptionName, params ) )
186 );
187 ast::StructDecl * decl = new ast::StructDecl(
188 location,
189 Virtual::vtableTypeName( exceptionName ) );
190 decl->members.push_back( typeId );
191 decl->members.push_back( size );
192 decl->members.push_back( copy );
193 decl->members.push_back( dtor );
194 decl->members.push_back( msg );
195 decl->body = true;
196 for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
197 decl->params.push_back( param );
198 }
199 return decl;
200}
201
202ast::StructDecl const * createExceptionStruct(
203 CodeLocation const & location,
204 std::string const & exceptionName,
205 std::vector<ast::ptr<ast::TypeDecl>> const & forallClause,
206 std::vector<ast::ptr<ast::Expr>> const & params,
207 std::vector<ast::ptr<ast::Decl>> const & members ) {
208 ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
209 decl->members.push_back( new ast::ObjectDecl(
210 location,
211 "virtual_table",
212 new ast::PointerType(
213 createVTableInstType( exceptionName, params ) )
214 ) );
215 for ( ast::ptr<ast::Decl> const & member : members ) {
216 decl->members.push_back( ast::deepCopy( member ) );
217 }
218 decl->body = true;
219 for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
220 decl->params.push_back( ast::deepCopy( param ) );
221 }
222 return decl;
223}
224
225ast::ObjectDecl const * createExternTypeId(
226 CodeLocation const & location,
227 std::string const & exceptionName,
228 std::vector<ast::ptr<ast::Expr>> const & params ) {
229 return new ast::ObjectDecl(
230 location,
231 Virtual::typeIdName( exceptionName ),
232 createVTableInstType( exceptionName, params ),
233 nullptr,
234 ast::Storage::Extern,
235 ast::Linkage::Cforall,
236 nullptr,
237 { new ast::Attribute( "cfa_linkonce" ) }
238 );
239}
240
241ast::ObjectDecl const * createExternVTable(
242 CodeLocation const & location,
243 std::string const & exceptionName,
244 std::vector<ast::ptr<ast::Expr>> const & params,
245 std::string const & tableName ) {
246 return new ast::ObjectDecl(
247 location,
248 tableName,
249 createVTableInstType( exceptionName, params ),
250 nullptr,
251 ast::Storage::Extern,
252 ast::Linkage::Cforall
253 );
254}
255
256ast::FunctionDecl const * createCopy(
257 CodeLocation const & location,
258 std::string const & exceptionName,
259 std::vector<ast::ptr<ast::Expr>> const & params ) {
260 return new ast::FunctionDecl(
261 location,
262 "copy",
263 {/* forall */},
264 {/* assertions */},
265 {
266 new ast::ObjectDecl(
267 location,
268 "this",
269 new ast::PointerType(
270 createExceptionInstType( exceptionName, params ) )
271 ),
272 new ast::ObjectDecl(
273 location,
274 "that",
275 new ast::PointerType(
276 createExceptionInstType( exceptionName, params ) )
277 ),
278 },
279 {
280 new ast::ObjectDecl( location, "", new ast::VoidType() ),
281 },
282 new ast::CompoundStmt( location, {
283 new ast::ExprStmt( location,
284 new ast::UntypedExpr( location,
285 new ast::NameExpr( location, "?=?" ),
286 {
287 new ast::UntypedExpr( location,
288 new ast::NameExpr( location, "*?" ),
289 { new ast::NameExpr( location, "this" ) } ),
290 new ast::UntypedExpr( location,
291 new ast::NameExpr( location, "*?" ),
292 { new ast::NameExpr( location, "that" ) } ),
293 }
294 )
295 ),
296 } ),
297 ast::Storage::Classes(),
298 ast::Linkage::Cforall
299 );
300}
301
302ast::FunctionDecl const * createMsg(
303 CodeLocation const & location,
304 std::string const & exceptionName,
305 std::vector<ast::ptr<ast::Expr>> const & params ) {
306 std::stringstream msg;
307 msg << exceptionName;
308 // The forall variant, add parameters to the string.
309 if ( !params.empty() ) {
310 msg << "(";
311 bool first = true;
312 for ( auto & param : params ) {
313 // Seperator Logic: A comma proceeds all but the first object.
314 if ( first ) {
315 first = false;
316 } else {
317 msg << ", ";
318 }
319
320 ast::print( msg, param.get() );
321 }
322 msg << ")";
323 }
324 return new ast::FunctionDecl(
325 location,
326 "msg",
327 {/* forall */},
328 {/* assertions */},
329 {
330 new ast::ObjectDecl(
331 location,
332 "this",
333 new ast::PointerType(
334 createExceptionInstType( exceptionName, params ) )
335 ),
336 },
337 {
338 new ast::ObjectDecl(
339 location,
340 "",
341 new ast::PointerType(
342 new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) )
343 ),
344 },
345 new ast::CompoundStmt( location, {
346 new ast::ReturnStmt( location,
347 ast::ConstantExpr::from_string( location, msg.str() )
348 ),
349 } ),
350 ast::Storage::Classes(),
351 ast::Linkage::Cforall
352 );
353}
354
355ast::ObjectDecl const * createVirtualTable(
356 CodeLocation const & location,
357 std::string const & exceptionName,
358 std::vector<ast::ptr<ast::Expr>> const & params,
359 std::string const & tableName ) {
360 ast::StructInstType * sizeType = new ast::StructInstType( exceptionName );
361 for ( ast::ptr<ast::Expr> const & param : params ) {
362 sizeType->params.push_back( ast::deepCopy( param ) );
363 }
364 std::vector<ast::ptr<ast::Init>> inits {
365 new ast::SingleInit( location,
366 new ast::AddressExpr( location,
367 new ast::NameExpr( location,
368 Virtual::typeIdName( exceptionName ) ) ) ),
369 new ast::SingleInit( location,
370 new ast::SizeofExpr( location, sizeType ) ),
371 new ast::SingleInit( location,
372 new ast::NameExpr( location, "copy" ) ),
373 new ast::SingleInit( location,
374 new ast::NameExpr( location, "^?{}" ) ),
375 new ast::SingleInit( location,
376 new ast::NameExpr( location, "msg" ) ),
377 };
378 std::vector<ast::ptr<ast::Designation>> dsigs {
379 new ast::Designation( location, {
380 new ast::NameExpr( location, "__cfavir_typeid" ) } ),
381 new ast::Designation( location, {
382 new ast::NameExpr( location, "size" ) } ),
383 new ast::Designation( location, {
384 new ast::NameExpr( location, "copy" ) } ),
385 new ast::Designation( location, {
386 new ast::NameExpr( location, "^?{}" ) } ),
387 new ast::Designation( location, {
388 new ast::NameExpr( location, "msg" ) } ),
389 };
390 return new ast::ObjectDecl(
391 location,
392 tableName,
393 createVTableInstType( exceptionName, params ),
394 new ast::ListInit( location, std::move( inits ), std::move( dsigs ) )
395 );
396}
397
398struct ExceptDeclCore : public ast::WithDeclsToAdd<> {
399 ast::StructDecl const * transformExcept( ast::StructDecl const * decl );
400 ast::ObjectDecl const * transformVTable(
401 ast::ObjectDecl const * decl, ast::VTableType const * type );
402
403 ast::StructDecl const * postvisit( ast::StructDecl const * decl ) {
404 // Exceptions don't get their own node type, so filter that.
405 if ( ast::AggregateDecl::Exception == decl->kind ) {
406 return transformExcept( decl );
407 }
408 return decl;
409 }
410
411 ast::ObjectDecl const * postvisit( ast::ObjectDecl const * decl ) {
412 // Modify remaining objects that have a vtable type.
413 if ( auto * type = decl->type.as<ast::VTableType>() ) {
414 return transformVTable( decl, type );
415 }
416 return decl;
417 }
418};
419
420ast::StructDecl const * ExceptDeclCore::transformExcept(
421 ast::StructDecl const * decl ) {
422 CodeLocation const & location = decl->location;
423 std::string const & exceptionName = decl->name;
424 std::vector<ast::ptr<ast::TypeDecl>> const & forall = decl->params;
425 std::vector<ast::ptr<ast::Expr>> params = forallToParams( forall );
426 std::vector<ast::ptr<ast::Decl>> const & members = decl->members;
427
428 declsToAddBefore.push_back(
429 createTypeIdStruct( location, exceptionName, forall ) );
430 if ( forall.empty() ) {
431 // Non-forall variant.
432 declsToAddBefore.push_back(
433 createTypeIdValue( location, exceptionName, params ) );
434 }
435 declsToAddBefore.push_back(
436 createExceptionStructForward( location, exceptionName, forall ) );
437 declsToAddBefore.push_back(
438 createVirtualTableStruct( location, exceptionName, forall, params ) );
439 return createExceptionStruct( location, exceptionName, forall, params, members );
440}
441
442ast::ObjectDecl const * ExceptDeclCore::transformVTable(
443 ast::ObjectDecl const * decl, ast::VTableType const * type ) {
444 CodeLocation const & location = decl->location;
445 auto base = type->base.strict_as<ast::TypeInstType>();
446 std::string const & exceptionName = base->name;
447 std::vector<ast::ptr<ast::Expr>> const & params = base->params;
448 std::string const & tableName = decl->name;
449
450 if ( decl->storage.is_extern ) {
451 // Unique type-ids are only needed for polymorphic instances.
452 if ( !params.empty() ) {
453 declsToAddBefore.push_back(
454 createExternTypeId( location, exceptionName, params ) );
455 }
456 return createExternVTable( location, exceptionName, params, tableName );
457 } else {
458 // Unique type-ids are only needed for polymorphic instances.
459 if ( !params.empty() ) {
460 declsToAddBefore.push_back(
461 createTypeIdValue( location, exceptionName, params ) );
462 }
463 declsToAddBefore.push_back(
464 createCopy( location, exceptionName, params ) );
465 declsToAddBefore.push_back(
466 createMsg( location, exceptionName, params ) );
467 return createVirtualTable(
468 location, exceptionName, params, tableName );
469 }
470}
471
472struct VTableCore {
473 ast::StructInstType const * postvisit( ast::VTableType const * type ) {
474 auto inst = type->base.as<ast::BaseInstType>();
475
476 std::string vtableName = Virtual::vtableTypeName( inst->name );
477 auto newType = new ast::StructInstType( vtableName );
478 for ( ast::ptr<ast::Expr> const & param : inst->params ) {
479 newType->params.push_back( param );
480 }
481
482 return newType;
483 }
484};
485
486} // namespace
487
488void translateExcept( ast::TranslationUnit & translationUnit ) {
489 // Can I combine these?
490 // Second pass really only covers what the first has missed.
491 // Maybe if the first one is all previsits and the second all postvisit.
492 ast::Pass<ExceptDeclCore>::run( translationUnit );
493 ast::Pass<VTableCore>::run( translationUnit );
494}
495
496} // namespace ControlStruct
497
498// Local Variables: //
499// tab-width: 4 //
500// mode: c++ //
501// compile-command: "make install" //
502// End: //
Note: See TracBrowser for help on using the repository browser.