source: src/ControlStruct/ExceptDecl.cpp@ cd79053

Last change on this file since cd79053 was 83fd57d, checked in by Andrew Beach <ajbeach@…>, 22 months ago

Removed 'New' suffixes, they are no longer needed for disambiguation.

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