source: src/ControlStruct/ExceptDeclNew.cpp @ 8f31be6

Last change on this file since 8f31be6 was bccd70a, checked in by Andrew Beach <ajbeach@…>, 13 months 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.