source: src/ControlStruct/ExceptDeclNew.cpp@ 9317419

ADT ast-experimental
Last change on this file since 9317419 was 9feb34b, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Moved toString and toCString to a new header. Updated includes. cassert was somehow getting instances of toString before but that stopped working so I embedded the new smaller include.

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