source: src/ControlStruct/ExceptDeclNew.cpp @ 8463136

ast-experimental
Last change on this file since 8463136 was 9feb34b, checked in by Andrew Beach <ajbeach@…>, 19 months 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.