source: src/ControlStruct/ExceptDeclNew.cpp@ 00b046f

Last change on this file since 00b046f was bccd70a, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Removed internal code from TypeSubstitution header. It caused a chain of include problems, which have been corrected.

  • Property mode set to 100644
File size: 15.2 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 <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 const * 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 );
303}
304
305ast::FunctionDecl const * createMsg(
306 CodeLocation const & location,
307 std::string const & exceptionName,
308 std::vector<ast::ptr<ast::Expr>> const & params ) {
309 std::stringstream msg;
310 msg << exceptionName;
311 // The forall variant, add parameters to the string.
312 if ( !params.empty() ) {
313 msg << "(";
314 bool first = true;
315 for ( auto & param : params ) {
316 // Seperator Logic: A comma proceeds all but the first object.
317 if ( first ) {
318 first = false;
319 } else {
320 msg << ", ";
321 }
322
323 ast::print( msg, param.get() );
324 }
325 msg << ")";
326 }
327 return new ast::FunctionDecl(
328 location,
329 "msg",
330 {/* forall */},
331 {/* assertions */},
332 {
333 new ast::ObjectDecl(
334 location,
335 "this",
336 new ast::PointerType(
337 createExceptionInstType( exceptionName, params ) )
338 ),
339 },
340 {
341 new ast::ObjectDecl(
342 location,
343 "",
344 new ast::PointerType(
345 new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) )
346 ),
347 },
348 new ast::CompoundStmt( location, {
349 new ast::ReturnStmt( location,
350 ast::ConstantExpr::from_string( location, msg.str() )
351 ),
352 } ),
353 ast::Storage::Classes(),
354 ast::Linkage::Cforall
355 );
356}
357
358ast::ObjectDecl const * createVirtualTable(
359 CodeLocation const & location,
360 std::string const & exceptionName,
361 std::vector<ast::ptr<ast::Expr>> const & params,
362 std::string const & tableName ) {
363 ast::StructInstType * sizeType = new ast::StructInstType( exceptionName );
364 for ( ast::ptr<ast::Expr> const & param : params ) {
365 sizeType->params.push_back( ast::deepCopy( param ) );
366 }
367 std::vector<ast::ptr<ast::Init>> inits {
368 new ast::SingleInit( location,
369 new ast::AddressExpr( location,
370 new ast::NameExpr( location,
371 Virtual::typeIdName( exceptionName ) ) ) ),
372 new ast::SingleInit( location,
373 new ast::SizeofExpr( location, sizeType ) ),
374 new ast::SingleInit( location,
375 new ast::NameExpr( location, "copy" ) ),
376 new ast::SingleInit( location,
377 new ast::NameExpr( location, "^?{}" ) ),
378 new ast::SingleInit( location,
379 new ast::NameExpr( location, "msg" ) ),
380 };
381 std::vector<ast::ptr<ast::Designation>> dsigs {
382 new ast::Designation( location, {
383 new ast::NameExpr( location, "__cfavir_typeid" ) } ),
384 new ast::Designation( location, {
385 new ast::NameExpr( location, "size" ) } ),
386 new ast::Designation( location, {
387 new ast::NameExpr( location, "copy" ) } ),
388 new ast::Designation( location, {
389 new ast::NameExpr( location, "^?{}" ) } ),
390 new ast::Designation( location, {
391 new ast::NameExpr( location, "msg" ) } ),
392 };
393 return new ast::ObjectDecl(
394 location,
395 tableName,
396 createVTableInstType( exceptionName, params ),
397 new ast::ListInit( location, std::move( inits ), std::move( dsigs ) )
398 );
399}
400
401struct ExceptDeclCore : public ast::WithDeclsToAdd<> {
402 ast::StructDecl const * transformExcept( ast::StructDecl const * decl );
403 ast::ObjectDecl const * transformVTable(
404 ast::ObjectDecl const * decl, ast::VTableType const * type );
405
406 ast::StructDecl const * postvisit( ast::StructDecl const * decl ) {
407 // Exceptions don't get their own node type, so filter that.
408 if ( ast::AggregateDecl::Exception == decl->kind ) {
409 return transformExcept( decl );
410 }
411 return decl;
412 }
413
414 ast::ObjectDecl const * postvisit( ast::ObjectDecl const * decl ) {
415 // Modify remaining objects that have a vtable type.
416 if ( auto * type = decl->type.as<ast::VTableType>() ) {
417 return transformVTable( decl, type );
418 }
419 return decl;
420 }
421};
422
423ast::StructDecl const * ExceptDeclCore::transformExcept(
424 ast::StructDecl const * decl ) {
425 CodeLocation const & location = decl->location;
426 std::string const & exceptionName = decl->name;
427 std::vector<ast::ptr<ast::TypeDecl>> const & forall = decl->params;
428 std::vector<ast::ptr<ast::Expr>> params = forallToParams( forall );
429 std::vector<ast::ptr<ast::Decl>> const & members = decl->members;
430
431 declsToAddBefore.push_back(
432 createTypeIdStruct( location, exceptionName, forall ) );
433 if ( forall.empty() ) {
434 // Non-forall variant.
435 declsToAddBefore.push_back(
436 createTypeIdValue( location, exceptionName, params ) );
437 }
438 declsToAddBefore.push_back(
439 createExceptionStructForward( location, exceptionName, forall ) );
440 declsToAddBefore.push_back(
441 createVirtualTableStruct( location, exceptionName, forall, params ) );
442 return createExceptionStruct( location, exceptionName, forall, params, members );
443}
444
445ast::ObjectDecl const * ExceptDeclCore::transformVTable(
446 ast::ObjectDecl const * decl, ast::VTableType const * type ) {
447 CodeLocation const & location = decl->location;
448 auto base = type->base.strict_as<ast::TypeInstType>();
449 std::string const & exceptionName = base->name;
450 std::vector<ast::ptr<ast::Expr>> const & params = base->params;
451 std::string const & tableName = decl->name;
452
453 if ( decl->storage.is_extern ) {
454 // Unique type-ids are only needed for polymorphic instances.
455 if ( !params.empty() ) {
456 declsToAddBefore.push_back(
457 createExternTypeId( location, exceptionName, params ) );
458 }
459 return createExternVTable( location, exceptionName, params, tableName );
460 } else {
461 // Unique type-ids are only needed for polymorphic instances.
462 if ( !params.empty() ) {
463 declsToAddBefore.push_back(
464 createTypeIdValue( location, exceptionName, params ) );
465 }
466 declsToAddBefore.push_back(
467 createCopy( location, exceptionName, params ) );
468 declsToAddBefore.push_back(
469 createMsg( location, exceptionName, params ) );
470 return createVirtualTable(
471 location, exceptionName, params, tableName );
472 }
473}
474
475struct VTableCore {
476 ast::StructInstType const * postvisit( ast::VTableType const * type ) {
477 auto inst = type->base.as<ast::BaseInstType>();
478
479 std::string vtableName = Virtual::vtableTypeName( inst->name );
480 auto newType = new ast::StructInstType( vtableName );
481 for ( ast::ptr<ast::Expr> const & param : inst->params ) {
482 newType->params.push_back( param );
483 }
484
485 return newType;
486 }
487};
488
489} // namespace
490
491void translateExcept( ast::TranslationUnit & translationUnit ) {
492 // Can I combine these?
493 // Second pass really only covers what the first has missed.
494 // Maybe if the first one is all previsits and the second all postvisit.
495 ast::Pass<ExceptDeclCore>::run( translationUnit );
496 ast::Pass<VTableCore>::run( translationUnit );
497}
498
499} // namespace ControlStruct
500
501// Local Variables: //
502// tab-width: 4 //
503// mode: c++ //
504// compile-command: "make install" //
505// End: //
Note: See TracBrowser for help on using the repository browser.