source: src/ControlStruct/ExceptDeclNew.cpp @ 4eebbcc

ADTast-experimental
Last change on this file since 4eebbcc was e8616b6, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Changed the default Linkage on ast::ObjectDecl? from C to Cforall. There appears to be only one internal name that actually needed to be C.

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