source: src/ControlStruct/ExceptDecl.cc @ 60f4919

Last change on this file since 60f4919 was 11df881, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Updated documentation on pre-resolver passes, moving code to headers instead of uses. Note that some comments were just copied over, I don't know if they are accurate.

  • Property mode set to 100644
File size: 13.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 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// ExceptDecl.cc -- Handles declarations of exception types.
8//
9// Author           : Henry Xue
10// Created On       : Tue Jul 20 04:10:50 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed May 25 16:43:00 2022
13// Update Count     : 5
14//
15
16#include "ExceptDecl.h"
17
18#include <cassert>               // for assert
19#include <string>                // for string
20#include <sstream>               // for stringstream
21
22#include "Common/PassVisitor.h"  // for PassVisitor
23#include "Common/utility.h"      // for cloneAll
24#include "SynTree/Mutator.h"     // for mutateAll
25#include "Virtual/Tables.h"      // for helpers
26
27namespace ControlStruct {
28
29const std::list< Expression *> & makeParameters(
30        const std::list< TypeDecl *> & forallClause
31) {
32        auto parameters = new std::list< Expression *>();
33        for ( auto it = forallClause.begin(); it != forallClause.end(); it++ ) {
34                parameters->emplace_back( new TypeExpr(
35                        new TypeInstType( noQualifiers, ( *it )->get_name(), false )
36                ) );
37        }
38        return *parameters;
39}
40
41StructInstType * makeExceptInstType(
42        const std::string & exceptionName,
43        const std::list< Expression *> & parameters
44) {
45        StructInstType * exceptInstType = new StructInstType(
46                noQualifiers,
47                exceptionName
48        );
49        cloneAll( parameters, exceptInstType->parameters );
50        return exceptInstType;
51}
52
53// void (*copy)(exception_name parameters * this, exception_name parameters * that);
54FunctionType * makeCopyFnType(
55        const std::string & exceptionName,
56        const std::list< Expression *> & parameters
57) {
58        FunctionType * copyFnType = new FunctionType( noQualifiers, false );
59        copyFnType->get_parameters().push_back( new ObjectDecl(
60                "this",
61                noStorageClasses,
62                LinkageSpec::Cforall,
63                nullptr,
64                new PointerType( noQualifiers,
65                        makeExceptInstType( exceptionName, parameters ) ),
66                nullptr
67        ) );
68        copyFnType->get_parameters().push_back( new ObjectDecl(
69                "that",
70                noStorageClasses,
71                LinkageSpec::Cforall,
72                nullptr,
73                new PointerType( noQualifiers,
74                        makeExceptInstType( exceptionName, parameters ) ),
75                nullptr
76        ) );
77        copyFnType->get_returnVals().push_back( new ObjectDecl(
78                "",
79                noStorageClasses,
80                LinkageSpec::Cforall,
81                nullptr,
82                new VoidType( noQualifiers ),
83                nullptr
84        ) );
85        return copyFnType;
86}
87
88// void (*^?{})(exception_name parameters & this);
89FunctionType * makeDtorFnType(
90        const std::string & exceptionName,
91        const std::list< Expression *> & parameters
92) {
93        FunctionType * dtorFnType = new FunctionType( noQualifiers, false );
94        dtorFnType->get_parameters().push_back( new ObjectDecl(
95                "this",
96                noStorageClasses,
97                LinkageSpec::Cforall,
98                nullptr,
99                new ReferenceType( noQualifiers,
100                        makeExceptInstType( exceptionName, parameters ) ),
101                nullptr
102        ) );
103        dtorFnType->get_returnVals().push_back( new ObjectDecl(
104                "",
105                noStorageClasses,
106                LinkageSpec::Cforall,
107                nullptr,
108                new VoidType( noQualifiers ),
109                nullptr
110        ) );
111        return dtorFnType;
112}
113
114// const char * (*msg)(exception_name parameters * this);
115FunctionType * makeMsgFnType(
116        const std::string & exceptionName,
117        const std::list< Expression *> & parameters
118) {
119        FunctionType * msgFnType = new FunctionType( noQualifiers, false );
120        msgFnType->get_parameters().push_back( new ObjectDecl(
121                "this",
122                noStorageClasses,
123                LinkageSpec::Cforall,
124                nullptr,
125                new PointerType( noQualifiers,
126                        makeExceptInstType( exceptionName, parameters ) ),
127                nullptr
128        ) );
129        msgFnType->get_returnVals().push_back( new ObjectDecl(
130                "",
131                noStorageClasses,
132                LinkageSpec::Cforall,
133                nullptr,
134                new PointerType( noQualifiers,
135                        new BasicType( Type::Const, BasicType::Char ) ),
136                nullptr
137        ) );
138        return msgFnType;
139}
140
141StructDecl * ehmTypeIdStruct(
142        const std::string & exceptionName,
143        const std::list< TypeDecl *> & forallClause
144) {
145        StructDecl * structDecl = new StructDecl( Virtual::typeIdType( exceptionName ) );
146        structDecl->members.push_back( new ObjectDecl(
147                "parent",
148                noStorageClasses,
149                LinkageSpec::Cforall,
150                nullptr,
151                new PointerType( noQualifiers,
152                        new StructInstType( Type::Const, "__cfavir_type_info" ) ),
153                nullptr
154        ) );
155        structDecl->set_body( true );
156        cloneAll( forallClause, structDecl->parameters );
157        return structDecl;
158}
159
160ObjectDecl * ehmTypeIdValue(
161        const std::string & exceptionName,
162        const std::list< Expression *> & parameters
163) {
164        StructInstType * typeIdType = new StructInstType(
165                Type::Const,
166                Virtual::typeIdType( exceptionName )
167        );
168        cloneAll( parameters, typeIdType->parameters );
169        return new ObjectDecl(
170                Virtual::typeIdName( exceptionName ),
171                noStorageClasses,
172                LinkageSpec::Cforall,
173                nullptr,
174                typeIdType,
175                new ListInit( { new SingleInit(
176                        new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
177                        ) }, {}, true ),
178                { new Attribute( "cfa_linkonce" ) }
179        );
180}
181
182StructDecl * ehmExceptionStructDecl(
183        const std::string & exceptionName,
184        const std::list< TypeDecl *> & forallClause
185) {
186        StructDecl * structDecl = new StructDecl( exceptionName );
187        cloneAll( forallClause, structDecl->parameters );
188        return structDecl;
189}
190
191StructDecl * ehmVirtualTableStruct(
192        const std::string & exceptionName,
193        const std::list< TypeDecl *> & forallClause,
194        const std::list< Expression *> & parameters
195) {
196        StructInstType * typeIdType = new StructInstType(
197                Type::Const,
198                Virtual::typeIdType( exceptionName )
199        );
200        cloneAll( parameters, typeIdType->parameters );
201        ObjectDecl * typeId = new ObjectDecl(
202                "__cfavir_typeid",
203                noStorageClasses,
204                LinkageSpec::Cforall,
205                nullptr,
206                new PointerType( noQualifiers, typeIdType ),
207                nullptr
208        );
209        ObjectDecl * size = new ObjectDecl(
210                "size",
211                noStorageClasses,
212                LinkageSpec::Cforall,
213                nullptr,
214                new TypeInstType( noQualifiers, "size_t", false ),
215                nullptr
216        );
217        ObjectDecl * copy = new ObjectDecl(
218                "copy",
219                noStorageClasses,
220                LinkageSpec::Cforall,
221                nullptr,
222                new PointerType( noQualifiers,
223                        makeCopyFnType( exceptionName, parameters ) ),
224                nullptr
225        );
226        ObjectDecl * dtor = new ObjectDecl(
227                "^?{}",
228                noStorageClasses,
229                LinkageSpec::Cforall,
230                nullptr,
231                new PointerType( noQualifiers,
232                        makeDtorFnType( exceptionName, parameters ) ),
233                nullptr
234        );
235        ObjectDecl * msg = new ObjectDecl(
236                "msg",
237                noStorageClasses,
238                LinkageSpec::Cforall,
239                nullptr,
240                new PointerType( noQualifiers,
241                        makeMsgFnType( exceptionName, parameters ) ),
242                nullptr
243        );
244        StructDecl * structDecl = new StructDecl( Virtual::vtableTypeName( exceptionName ) );
245        structDecl->members.push_back( typeId );
246        structDecl->members.push_back( size );
247        structDecl->members.push_back( copy );
248        structDecl->members.push_back( dtor );
249        structDecl->members.push_back( msg );
250        structDecl->set_body( true );
251        cloneAll( forallClause, structDecl->parameters );
252        return structDecl;
253}
254
255StructDecl * ehmExceptionStruct(
256        const std::string & exceptionName,
257        const std::list< TypeDecl *> & forallClause,
258        const std::list< Expression *> & parameters,
259        const std::list< Declaration *> & members
260) {
261        StructInstType * vtableType = new StructInstType(
262                Type::Const,
263                Virtual::vtableTypeName( exceptionName )
264        );
265        cloneAll( parameters, vtableType->parameters );
266        StructDecl * structDecl = new StructDecl( exceptionName );
267        structDecl->members = members;
268        structDecl->members.push_front( new ObjectDecl(
269                "virtual_table",
270                noStorageClasses,
271                LinkageSpec::Cforall,
272                nullptr,
273                new PointerType( noQualifiers, vtableType ),
274                nullptr
275        ) );
276        structDecl->set_body( true );
277        cloneAll( forallClause, structDecl->parameters );
278        return structDecl;
279}
280
281ObjectDecl * ehmTypeIdExtern(
282        const std::string & exceptionName,
283        const std::list< Expression *> & parameters
284) {
285        StructInstType * typeIdType = new StructInstType(
286                Type::Const,
287                Virtual::typeIdType( exceptionName )
288        );
289        cloneAll( parameters, typeIdType->parameters );
290        return new ObjectDecl(
291                Virtual::typeIdName( exceptionName ),
292                Type::Extern,
293                LinkageSpec::Cforall,
294                nullptr,
295                typeIdType,
296                nullptr,
297                { new Attribute( "cfa_linkonce" ) }
298        );
299}
300
301ObjectDecl * ehmExternVtable(
302        const std::string & exceptionName,
303        const std::list< Expression *> & parameters,
304        const std::string & tableName
305) {
306        StructInstType * vtableType = new StructInstType(
307                Type::Const,
308                Virtual::vtableTypeName( exceptionName )
309        );
310        cloneAll( parameters, vtableType->parameters );
311        return new ObjectDecl(
312                tableName,
313                Type::Extern,
314                LinkageSpec::Cforall,
315                nullptr,
316                vtableType,
317                nullptr
318        );
319}
320
321FunctionDecl * ehmDefineCopy(
322        const std::string & exceptionName,
323        const std::list< Expression *> & parameters
324) {
325        return new FunctionDecl(
326                "copy",
327                noStorageClasses,
328                LinkageSpec::Cforall,
329                makeCopyFnType( exceptionName, parameters ),
330                new CompoundStmt( {
331                        new ExprStmt( new UntypedExpr( new NameExpr( "?=?" ), {
332                                new UntypedExpr( new NameExpr( "*?" ), { new NameExpr( "this" ) } ),
333                                new UntypedExpr( new NameExpr( "*?" ), { new NameExpr( "that" ) } )
334                        } ) )
335                } )
336        );
337}
338
339FunctionDecl * ehmDefineMsg(
340        const std::string & exceptionName,
341        const std::list< Expression *> & parameters
342) {
343        std::stringstream msg;
344        msg << exceptionName;
345        if ( !parameters.empty() ) { // forall variant, add parameters
346                msg << "(";
347                for ( auto it = parameters.begin(); it != parameters.end(); it++ ) {
348                        ( *it )->print( msg );
349                        if ( it + 1 == parameters.end() ) {
350                                msg << ")"; // end of list, close bracket
351                        } else {
352                                msg << ", "; // otherwise use comma as separator
353                        }
354                }
355        }
356        return new FunctionDecl(
357                "msg",
358                noStorageClasses,
359                LinkageSpec::Cforall,
360                makeMsgFnType( exceptionName, parameters ),
361                new CompoundStmt( {
362                        new ReturnStmt( new ConstantExpr( Constant::from_string( msg.str() ) ) )
363                } )
364        );
365}
366
367ObjectDecl * ehmVirtualTable(
368        const std::string & exceptionName,
369        const std::list< Expression *> & parameters,
370        const std::string & tableName
371) {
372        StructInstType * sizeofType = new StructInstType( noQualifiers, exceptionName );
373        cloneAll( parameters, sizeofType->parameters );
374        std::list< Initializer *> inits {
375                new SingleInit( new AddressExpr(
376                        new NameExpr( Virtual::typeIdName( exceptionName ) ) ) ),
377                new SingleInit( new SizeofExpr( sizeofType ) ),
378                new SingleInit( new NameExpr( "copy" ) ),
379                new SingleInit( new NameExpr( "^?{}" ) ),
380                new SingleInit( new NameExpr( "msg" ) )
381        };
382        std::list< Designation *> desig {
383                new Designation( { new NameExpr( "__cfavir_typeid" ) } ),
384                new Designation( { new NameExpr( "size" ) } ),
385                new Designation( { new NameExpr( "copy" ) } ),
386                new Designation( { new NameExpr( "^?{}" ) } ),
387                new Designation( { new NameExpr( "msg" ) } )
388        };
389        StructInstType * vtableType = new StructInstType(
390                Type::Const,
391                Virtual::vtableTypeName( exceptionName )
392        );
393        cloneAll( parameters, vtableType->parameters );
394        return new ObjectDecl(
395                tableName,
396                noStorageClasses,
397                LinkageSpec::Cforall,
398                nullptr,
399                vtableType,
400                new ListInit( inits, desig )
401        );
402}
403
404class ExceptDeclCore : public WithDeclsToAdd {
405public:
406        // translates exception decls
407        Declaration * postmutate( StructDecl * structDecl );
408
409        // translates vtable decls
410        DeclarationWithType * postmutate( ObjectDecl * objectDecl );
411};
412
413Declaration * ExceptDeclCore::postmutate( StructDecl * structDecl ) {
414        if ( structDecl->is_exception() ) {
415                const std::string & exceptionName = structDecl->get_name();
416                const std::list< TypeDecl *> & forallClause = structDecl->get_parameters();
417                const std::list< Expression *> & parameters = makeParameters( forallClause );
418                const std::list< Declaration *> & members = structDecl->get_members();
419
420                declsToAddBefore.push_back( ehmTypeIdStruct( exceptionName, forallClause ) );
421                if ( forallClause.empty() ) { // non-forall variant
422                        declsToAddBefore.push_back( ehmTypeIdValue( exceptionName, parameters ) );
423                }
424                declsToAddBefore.push_back( ehmExceptionStructDecl( exceptionName, forallClause ) );
425                declsToAddBefore.push_back( ehmVirtualTableStruct( exceptionName, forallClause, parameters ) );
426                return ehmExceptionStruct( exceptionName, forallClause, parameters, members );
427        }
428        return structDecl;
429}
430
431DeclarationWithType * ExceptDeclCore::postmutate( ObjectDecl * objectDecl ) {
432        // Check if it is VTableType
433        VTableType * vtableType = dynamic_cast< VTableType *>( objectDecl->get_type() );
434        if ( vtableType ) {
435                TypeInstType * base = dynamic_cast< TypeInstType *>( vtableType->get_base() );
436                assert( base ); // should be a TypeInstType
437                const std::string & exceptionName = base->get_name();
438                const std::string & tableName = objectDecl->get_name();
439                const std::list< Expression *> parameters = base->get_parameters();
440
441                if ( objectDecl->get_storageClasses().is_extern ) { // if extern
442                        if ( !parameters.empty() ) { // forall variant
443                                declsToAddBefore.push_back( ehmTypeIdExtern( exceptionName, parameters ) );
444                        }
445                        return ehmExternVtable( exceptionName, parameters, tableName );
446                }
447                // else, non-extern
448                if ( !parameters.empty() ) { // forall variant
449                        declsToAddBefore.push_back( ehmTypeIdValue( exceptionName, parameters ) );
450                }
451                declsToAddBefore.push_back( ehmDefineCopy( exceptionName, parameters ) );
452                declsToAddBefore.push_back( ehmDefineMsg( exceptionName, parameters ) );
453                return ehmVirtualTable( exceptionName, parameters, tableName );
454        }
455        return objectDecl;
456}
457
458class VTableCore : public WithDeclsToAdd {
459public:
460        // Remove any remaining vtable type nodes in the tree.
461        Type * postmutate( VTableType * vtableType );
462};
463
464Type * VTableCore::postmutate( VTableType * vtableType ) {
465        auto inst = strict_dynamic_cast<ReferenceToType *>( vtableType->base );
466
467        std::string vtableName = Virtual::vtableTypeName( inst->name );
468        StructInstType * newType = new StructInstType( noQualifiers, vtableName );
469        cloneAll( inst->parameters, newType->parameters );
470
471        delete vtableType;
472        return newType;
473}
474
475void translateExcept( std::list< Declaration *> & translationUnit ) {
476        PassVisitor<ExceptDeclCore> translator;
477        mutateAll( translationUnit, translator );
478        PassVisitor<VTableCore> typeTranslator;
479        mutateAll( translationUnit, typeTranslator );
480}
481
482}
Note: See TracBrowser for help on using the repository browser.