source: src/ControlStruct/ExceptDeclNew.cpp @ 6a896b0

ADTast-experimentalpthread-emulationqualifiedEnum
Last change on this file since 6a896b0 was 6a896b0, checked in by Andrew Beach <ajbeach@…>, 2 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.