source: src/ControlStruct/ExceptDeclNew.cpp@ 0577df2

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since 0577df2 was 6a896b0, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Translated the Exception Declaration pass.

  • Property mode set to 100644
File size: 16.0 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 nullptr,
114 ast::Storage::Classes(),
115 ast::Linkage::Cforall
116 ) );
117 decl->body = true;
118 for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
119 decl->params.push_back( ast::deepCopy( param ) );
120 }
121 return decl;
122}
123
124ast::ObjectDecl const * createTypeIdValue(
125 CodeLocation const & location,
126 std::string const & exceptionName,
127 std::vector<ast::ptr<ast::Expr>> const & params ) {
128 ast::StructInstType * typeIdType =
129 createTypeIdInstType( exceptionName, params );
130 return new ast::ObjectDecl(
131 location,
132 Virtual::typeIdName( exceptionName ),
133 typeIdType,
134 new ast::ListInit( location, {
135 new ast::SingleInit( location,
136 new ast::AddressExpr( location,
137 new ast::NameExpr( location, "__cfatid_exception_t" ) ),
138 ast::MaybeConstruct ),
139 }, {}, ast::MaybeConstruct ),
140 ast::Storage::Classes(),
141 ast::Linkage::Cforall,
142 nullptr,
143 { new ast::Attribute( "cfa_linkonce" ) }
144 );
145}
146
147ast::StructDecl const * createExceptionStructForward(
148 CodeLocation const & location,
149 std::string const & exceptionName,
150 std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
151 ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
152 for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
153 decl->params.push_back( ast::deepCopy( param ) );
154 }
155 return decl;
156}
157
158ast::StructDecl const * createVirtualTableStruct(
159 CodeLocation const & location,
160 std::string const & exceptionName,
161 std::vector<ast::ptr<ast::TypeDecl>> const & forall,
162 std::vector<ast::ptr<ast::Expr>> const & params ) {
163 ast::StructInstType * typeIdType =
164 createTypeIdInstType( exceptionName, params );
165 ast::ObjectDecl * typeId = new ast::ObjectDecl(
166 location,
167 "__cfavir_typeid",
168 new ast::PointerType( typeIdType ),
169 nullptr,
170 ast::Storage::Classes(),
171 ast::Linkage::Cforall
172 );
173 ast::ObjectDecl * size = new ast::ObjectDecl(
174 location,
175 "size",
176 new ast::TypeInstType( "size_t", ast::TypeDecl::Dtype ),
177 nullptr,
178 ast::Storage::Classes(),
179 ast::Linkage::Cforall
180 );
181 ast::ObjectDecl * copy = new ast::ObjectDecl(
182 location,
183 "copy",
184 new ast::PointerType( createCopyFuncType( exceptionName, params ) ),
185 nullptr,
186 ast::Storage::Classes(),
187 ast::Linkage::Cforall
188 );
189 ast::ObjectDecl * dtor = new ast::ObjectDecl(
190 location,
191 "^?{}",
192 new ast::PointerType( createDtorFuncType( exceptionName, params ) ),
193 nullptr,
194 ast::Storage::Classes(),
195 ast::Linkage::Cforall
196 );
197 ast::ObjectDecl * msg = new ast::ObjectDecl(
198 location,
199 "msg",
200 new ast::PointerType( createMsgFuncType( exceptionName, params ) ),
201 nullptr,
202 ast::Storage::Classes(),
203 ast::Linkage::Cforall
204 );
205 ast::StructDecl * decl = new ast::StructDecl(
206 location,
207 Virtual::vtableTypeName( exceptionName ) );
208 decl->members.push_back( typeId );
209 decl->members.push_back( size );
210 decl->members.push_back( copy );
211 decl->members.push_back( dtor );
212 decl->members.push_back( msg );
213 decl->body = true;
214 for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
215 decl->params.push_back( param );
216 }
217 return decl;
218}
219
220ast::StructDecl const * createExceptionStruct(
221 CodeLocation const & location,
222 std::string const & exceptionName,
223 std::vector<ast::ptr<ast::TypeDecl>> const & forallClause,
224 std::vector<ast::ptr<ast::Expr>> const & params,
225 std::vector<ast::ptr<ast::Decl>> const & members ) {
226 ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
227 decl->members.push_back( new ast::ObjectDecl(
228 location,
229 "virtual_table",
230 new ast::PointerType(
231 createVTableInstType( exceptionName, params ) ),
232 nullptr,
233 ast::Storage::Classes(),
234 ast::Linkage::Cforall
235 ) );
236 for ( ast::ptr<ast::Decl> const & member : members ) {
237 decl->members.push_back( ast::deepCopy( member ) );
238 }
239 decl->body = true;
240 for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
241 decl->params.push_back( ast::deepCopy( param ) );
242 }
243 return decl;
244}
245
246ast::ObjectDecl const * createExternTypeId(
247 CodeLocation const & location,
248 std::string const & exceptionName,
249 std::vector<ast::ptr<ast::Expr>> const & params ) {
250 return new ast::ObjectDecl(
251 location,
252 Virtual::typeIdName( exceptionName ),
253 createVTableInstType( exceptionName, params ),
254 nullptr,
255 ast::Storage::Extern,
256 ast::Linkage::Cforall,
257 nullptr,
258 { new ast::Attribute( "cfa_linkonce" ) }
259 );
260}
261
262ast::ObjectDecl const * createExternVTable(
263 CodeLocation const & location,
264 std::string const & exceptionName,
265 std::vector<ast::ptr<ast::Expr>> const & params,
266 std::string const & tableName ) {
267 return new ast::ObjectDecl(
268 location,
269 tableName,
270 createVTableInstType( exceptionName, params ),
271 nullptr,
272 ast::Storage::Extern,
273 ast::Linkage::Cforall
274 );
275}
276
277ast::FunctionDecl const * createCopy(
278 CodeLocation const & location,
279 std::string const & exceptionName,
280 std::vector<ast::ptr<ast::Expr>> const & params ) {
281 return new ast::FunctionDecl(
282 location,
283 "copy",
284 {/* forall */},
285 {/* assertions */},
286 {
287 new ast::ObjectDecl(
288 location,
289 "this",
290 new ast::PointerType(
291 createExceptionInstType( exceptionName, params ) ),
292 nullptr,
293 ast::Storage::Classes(),
294 ast::Linkage::Cforall
295 ),
296 new ast::ObjectDecl(
297 location,
298 "that",
299 new ast::PointerType(
300 createExceptionInstType( exceptionName, params ) ),
301 nullptr,
302 ast::Storage::Classes(),
303 ast::Linkage::Cforall
304 ),
305 },
306 {
307 new ast::ObjectDecl(
308 location,
309 "",
310 new ast::VoidType(),
311 nullptr,
312 ast::Storage::Classes(),
313 ast::Linkage::Cforall
314 ),
315 },
316 new ast::CompoundStmt( location, {
317 new ast::ExprStmt( location,
318 new ast::UntypedExpr( location,
319 new ast::NameExpr( location, "?=?" ),
320 {
321 new ast::UntypedExpr( location,
322 new ast::NameExpr( location, "*?" ),
323 { new ast::NameExpr( location, "this" ) } ),
324 new ast::UntypedExpr( location,
325 new ast::NameExpr( location, "*?" ),
326 { new ast::NameExpr( location, "that" ) } ),
327 }
328 )
329 ),
330 } ),
331 ast::Storage::Classes(),
332 ast::Linkage::Cforall
333 );
334}
335
336ast::FunctionDecl const * createMsg(
337 CodeLocation const & location,
338 std::string const & exceptionName,
339 std::vector<ast::ptr<ast::Expr>> const & params ) {
340 std::stringstream msg;
341 msg << exceptionName;
342 // The forall variant, add parameters to the string.
343 if ( !params.empty() ) {
344 msg << "(";
345 bool first = true;
346 for ( auto & param : params ) {
347 // Seperator Logic: A comma proceeds all but the first object.
348 if ( first ) {
349 first = false;
350 } else {
351 msg << ", ";
352 }
353
354 ast::print( msg, param.get() );
355 }
356 msg << ")";
357 }
358 return new ast::FunctionDecl(
359 location,
360 "msg",
361 {/* forall */},
362 {/* assertions */},
363 {
364 new ast::ObjectDecl(
365 location,
366 "this",
367 new ast::PointerType(
368 createExceptionInstType( exceptionName, params ) ),
369 nullptr,
370 ast::Storage::Classes(),
371 ast::Linkage::Cforall
372 ),
373 },
374 {
375 new ast::ObjectDecl(
376 location,
377 "",
378 new ast::PointerType(
379 new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) ),
380 nullptr,
381 ast::Storage::Classes(),
382 ast::Linkage::Cforall
383 ),
384 },
385 new ast::CompoundStmt( location, {
386 new ast::ReturnStmt( location,
387 ast::ConstantExpr::from_string( location, msg.str() )
388 ),
389 } ),
390 ast::Storage::Classes(),
391 ast::Linkage::Cforall
392 );
393}
394
395ast::ObjectDecl const * createVirtualTable(
396 CodeLocation const & location,
397 std::string const & exceptionName,
398 std::vector<ast::ptr<ast::Expr>> const & params,
399 std::string const & tableName ) {
400 ast::StructInstType * sizeType = new ast::StructInstType( exceptionName );
401 for ( ast::ptr<ast::Expr> const & param : params ) {
402 sizeType->params.push_back( ast::deepCopy( param ) );
403 }
404 std::vector<ast::ptr<ast::Init>> inits {
405 new ast::SingleInit( location,
406 new ast::AddressExpr( location,
407 new ast::NameExpr( location,
408 Virtual::typeIdName( exceptionName ) ) ) ),
409 new ast::SingleInit( location,
410 new ast::SizeofExpr( location, sizeType ) ),
411 new ast::SingleInit( location,
412 new ast::NameExpr( location, "copy" ) ),
413 new ast::SingleInit( location,
414 new ast::NameExpr( location, "^?{}" ) ),
415 new ast::SingleInit( location,
416 new ast::NameExpr( location, "msg" ) ),
417 };
418 std::vector<ast::ptr<ast::Designation>> dsigs {
419 new ast::Designation( location, {
420 new ast::NameExpr( location, "__cfavir_typeid" ) } ),
421 new ast::Designation( location, {
422 new ast::NameExpr( location, "size" ) } ),
423 new ast::Designation( location, {
424 new ast::NameExpr( location, "copy" ) } ),
425 new ast::Designation( location, {
426 new ast::NameExpr( location, "^?{}" ) } ),
427 new ast::Designation( location, {
428 new ast::NameExpr( location, "msg" ) } ),
429 };
430 return new ast::ObjectDecl(
431 location,
432 tableName,
433 createVTableInstType( exceptionName, params ),
434 new ast::ListInit( location, std::move( inits ), std::move( dsigs ) ),
435 ast::Storage::Classes(),
436 ast::Linkage::Cforall
437 );
438}
439
440struct ExceptDeclCore : public ast::WithDeclsToAdd<> {
441 ast::StructDecl const * transformExcept( ast::StructDecl const * decl );
442 ast::ObjectDecl const * transformVTable(
443 ast::ObjectDecl const * decl, ast::VTableType const * type );
444
445 ast::StructDecl const * postvisit( ast::StructDecl const * decl ) {
446 // Exceptions don't get their own node type, so filter that.
447 if ( ast::AggregateDecl::Exception == decl->kind ) {
448 return transformExcept( decl );
449 }
450 return decl;
451 }
452
453 ast::ObjectDecl const * postvisit( ast::ObjectDecl const * decl ) {
454 // Modify remaining objects that have a vtable type.
455 if ( auto * type = decl->type.as<ast::VTableType>() ) {
456 return transformVTable( decl, type );
457 }
458 return decl;
459 }
460};
461
462ast::StructDecl const * ExceptDeclCore::transformExcept(
463 ast::StructDecl const * decl ) {
464 CodeLocation const & location = decl->location;
465 std::string const & exceptionName = decl->name;
466 std::vector<ast::ptr<ast::TypeDecl>> const & forall = decl->params;
467 std::vector<ast::ptr<ast::Expr>> params = forallToParams( forall );
468 std::vector<ast::ptr<ast::Decl>> const & members = decl->members;
469
470 declsToAddBefore.push_back(
471 createTypeIdStruct( location, exceptionName, forall ) );
472 if ( forall.empty() ) {
473 // Non-forall variant.
474 declsToAddBefore.push_back(
475 createTypeIdValue( location, exceptionName, params ) );
476 }
477 declsToAddBefore.push_back(
478 createExceptionStructForward( location, exceptionName, forall ) );
479 declsToAddBefore.push_back(
480 createVirtualTableStruct( location, exceptionName, forall, params ) );
481 return createExceptionStruct( location, exceptionName, forall, params, members );
482}
483
484ast::ObjectDecl const * ExceptDeclCore::transformVTable(
485 ast::ObjectDecl const * decl, ast::VTableType const * type ) {
486 CodeLocation const & location = decl->location;
487 auto base = type->base.strict_as<ast::TypeInstType>();
488 std::string const & exceptionName = base->name;
489 std::vector<ast::ptr<ast::Expr>> const & params = base->params;
490 std::string const & tableName = decl->name;
491
492 if ( decl->storage.is_extern ) {
493 // Unique type-ids are only needed for polymorphic instances.
494 if ( !params.empty() ) {
495 declsToAddBefore.push_back(
496 createExternTypeId( location, exceptionName, params ) );
497 }
498 return createExternVTable( location, exceptionName, params, tableName );
499 } else {
500 // Unique type-ids are only needed for polymorphic instances.
501 if ( !params.empty() ) {
502 declsToAddBefore.push_back(
503 createTypeIdValue( location, exceptionName, params ) );
504 }
505 declsToAddBefore.push_back(
506 createCopy( location, exceptionName, params ) );
507 declsToAddBefore.push_back(
508 createMsg( location, exceptionName, params ) );
509 return createVirtualTable(
510 location, exceptionName, params, tableName );
511 }
512}
513
514struct VTableCore {
515 ast::StructInstType const * postvisit( ast::VTableType const * type ) {
516 auto inst = type->base.as<ast::BaseInstType>();
517
518 std::string vtableName = Virtual::vtableTypeName( inst->name );
519 auto newType = new ast::StructInstType( vtableName );
520 for ( ast::ptr<ast::Expr> const & param : inst->params ) {
521 newType->params.push_back( param );
522 }
523
524 return newType;
525 }
526};
527
528} // namespace
529
530void translateExcept( ast::TranslationUnit & translationUnit ) {
531 // Can I combine these?
532 // Second pass really only covers what the first has missed.
533 // Maybe if the first one is all previsits and the second all postvisit.
534 ast::Pass<ExceptDeclCore>::run( translationUnit );
535 ast::Pass<VTableCore>::run( translationUnit );
536}
537
538} // namespace ControlStruct
539
540// Local Variables: //
541// tab-width: 4 //
542// mode: c++ //
543// compile-command: "make install" //
544// End: //
Note: See TracBrowser for help on using the repository browser.