source: src/ControlStruct/ExceptDecl.cc @ 8c91088

ADTast-experimental
Last change on this file since 8c91088 was 11df881, checked in by Andrew Beach <ajbeach@…>, 23 months 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
RevLine 
[0c730d9]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//
[11df881]7// ExceptDecl.cc -- Handles declarations of exception types.
[0c730d9]8//
9// Author           : Henry Xue
10// Created On       : Tue Jul 20 04:10:50 2021
[c715e5f]11// Last Modified By : Andrew Beach
12// Last Modified On : Wed May 25 16:43:00 2022
13// Update Count     : 5
[0c730d9]14//
15
16#include "ExceptDecl.h"
17
[98233b3]18#include <cassert>               // for assert
19#include <string>                // for string
20#include <sstream>               // for stringstream
21
[0c730d9]22#include "Common/PassVisitor.h"  // for PassVisitor
[98233b3]23#include "Common/utility.h"      // for cloneAll
[0c730d9]24#include "SynTree/Mutator.h"     // for mutateAll
25#include "Virtual/Tables.h"      // for helpers
26
27namespace ControlStruct {
28
[98233b3]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                ) );
[0c730d9]37        }
[98233b3]38        return *parameters;
[0c730d9]39}
40
[c715e5f]41StructInstType * makeExceptInstType(
[98233b3]42        const std::string & exceptionName,
43        const std::list< Expression *> & parameters
44) {
[c715e5f]45        StructInstType * exceptInstType = new StructInstType(
[98233b3]46                noQualifiers,
[c715e5f]47                exceptionName
[0c730d9]48        );
[98233b3]49        cloneAll( parameters, exceptInstType->parameters );
50        return exceptInstType;
[0c730d9]51}
52
[98233b3]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) {
[0c730d9]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,
[98233b3]65                        makeExceptInstType( exceptionName, parameters ) ),
[0c730d9]66                nullptr
67        ) );
68        copyFnType->get_parameters().push_back( new ObjectDecl(
[98233b3]69                "that",
[0c730d9]70                noStorageClasses,
71                LinkageSpec::Cforall,
72                nullptr,
73                new PointerType( noQualifiers,
[98233b3]74                        makeExceptInstType( exceptionName, parameters ) ),
[0c730d9]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        ) );
[98233b3]85        return copyFnType;
86}
[0c730d9]87
[98233b3]88// void (*^?{})(exception_name parameters & this);
89FunctionType * makeDtorFnType(
90        const std::string & exceptionName,
91        const std::list< Expression *> & parameters
92) {
[0c730d9]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,
[98233b3]100                        makeExceptInstType( exceptionName, parameters ) ),
[0c730d9]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        ) );
[98233b3]111        return dtorFnType;
112}
[0c730d9]113
[98233b3]114// const char * (*msg)(exception_name parameters * this);
115FunctionType * makeMsgFnType(
116        const std::string & exceptionName,
117        const std::list< Expression *> & parameters
118) {
[0c730d9]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,
[98233b3]126                        makeExceptInstType( exceptionName, parameters ) ),
[0c730d9]127                nullptr
128        ) );
129        msgFnType->get_returnVals().push_back( new ObjectDecl(
130                "",
131                noStorageClasses,
132                LinkageSpec::Cforall,
133                nullptr,
[98233b3]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,
[c715e5f]152                        new StructInstType( Type::Const, "__cfavir_type_info" ) ),
[0c730d9]153                nullptr
154        ) );
[98233b3]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        );
[0c730d9]235        ObjectDecl * msg = new ObjectDecl(
236                "msg",
237                noStorageClasses,
238                LinkageSpec::Cforall,
239                nullptr,
[98233b3]240                new PointerType( noQualifiers,
241                        makeMsgFnType( exceptionName, parameters ) ),
[0c730d9]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 );
[98233b3]251        cloneAll( forallClause, structDecl->parameters );
[0c730d9]252        return structDecl;
253}
254
[98233b3]255StructDecl * ehmExceptionStruct(
256        const std::string & exceptionName,
257        const std::list< TypeDecl *> & forallClause,
[c715e5f]258        const std::list< Expression *> & parameters,
[98233b3]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 );
[0c730d9]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,
[98233b3]273                new PointerType( noQualifiers, vtableType ),
[0c730d9]274                nullptr
275        ) );
276        structDecl->set_body( true );
[98233b3]277        cloneAll( forallClause, structDecl->parameters );
[0c730d9]278        return structDecl;
279}
280
[da602aec]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
[98233b3]301ObjectDecl * ehmExternVtable(
302        const std::string & exceptionName,
[c715e5f]303        const std::list< Expression *> & parameters,
[98233b3]304        const std::string & tableName
305) {
306        StructInstType * vtableType = new StructInstType(
307                Type::Const,
308                Virtual::vtableTypeName( exceptionName )
309        );
310        cloneAll( parameters, vtableType->parameters );
[aa882e7e]311        return new ObjectDecl(
312                tableName,
313                Type::Extern,
314                LinkageSpec::Cforall,
315                nullptr,
[98233b3]316                vtableType,
[aa882e7e]317                nullptr
318        );
319}
320
[98233b3]321FunctionDecl * ehmDefineCopy(
322        const std::string & exceptionName,
323        const std::list< Expression *> & parameters
324) {
[aa882e7e]325        return new FunctionDecl(
326                "copy",
327                noStorageClasses,
328                LinkageSpec::Cforall,
[98233b3]329                makeCopyFnType( exceptionName, parameters ),
[aa882e7e]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
[98233b3]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        }
[aa882e7e]356        return new FunctionDecl(
357                "msg",
358                noStorageClasses,
359                LinkageSpec::Cforall,
[98233b3]360                makeMsgFnType( exceptionName, parameters ),
[aa882e7e]361                new CompoundStmt( {
[98233b3]362                        new ReturnStmt( new ConstantExpr( Constant::from_string( msg.str() ) ) )
[aa882e7e]363                } )
364        );
365}
366
[98233b3]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 );
[aa882e7e]374        std::list< Initializer *> inits {
375                new SingleInit( new AddressExpr(
376                        new NameExpr( Virtual::typeIdName( exceptionName ) ) ) ),
[98233b3]377                new SingleInit( new SizeofExpr( sizeofType ) ),
[aa882e7e]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        };
[98233b3]389        StructInstType * vtableType = new StructInstType(
390                Type::Const,
391                Virtual::vtableTypeName( exceptionName )
392        );
393        cloneAll( parameters, vtableType->parameters );
[aa882e7e]394        return new ObjectDecl(
395                tableName,
396                noStorageClasses,
397                LinkageSpec::Cforall,
398                nullptr,
[98233b3]399                vtableType,
[aa882e7e]400                new ListInit( inits, desig )
401        );
402}
403
[0c730d9]404class ExceptDeclCore : public WithDeclsToAdd {
405public:
[98233b3]406        // translates exception decls
407        Declaration * postmutate( StructDecl * structDecl );
408
409        // translates vtable decls
410        DeclarationWithType * postmutate( ObjectDecl * objectDecl );
[0c730d9]411};
412
413Declaration * ExceptDeclCore::postmutate( StructDecl * structDecl ) {
414        if ( structDecl->is_exception() ) {
[aa882e7e]415                const std::string & exceptionName = structDecl->get_name();
[98233b3]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 );
[0c730d9]427        }
428        return structDecl;
429}
430
[aa882e7e]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();
[98233b3]439                const std::list< Expression *> parameters = base->get_parameters();
440
441                if ( objectDecl->get_storageClasses().is_extern ) { // if extern
[da602aec]442                        if ( !parameters.empty() ) { // forall variant
443                                declsToAddBefore.push_back( ehmTypeIdExtern( exceptionName, parameters ) );
444                        }
[98233b3]445                        return ehmExternVtable( exceptionName, parameters, tableName );
446                }
447                // else, non-extern
448                if ( !parameters.empty() ) { // forall variant
449                        declsToAddBefore.push_back( ehmTypeIdValue( exceptionName, parameters ) );
[aa882e7e]450                }
[98233b3]451                declsToAddBefore.push_back( ehmDefineCopy( exceptionName, parameters ) );
452                declsToAddBefore.push_back( ehmDefineMsg( exceptionName, parameters ) );
453                return ehmVirtualTable( exceptionName, parameters, tableName );
[aa882e7e]454        }
455        return objectDecl;
456}
457
[c715e5f]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
[0c730d9]475void translateExcept( std::list< Declaration *> & translationUnit ) {
476        PassVisitor<ExceptDeclCore> translator;
477        mutateAll( translationUnit, translator );
[c715e5f]478        PassVisitor<VTableCore> typeTranslator;
479        mutateAll( translationUnit, typeTranslator );
[0c730d9]480}
481
482}
Note: See TracBrowser for help on using the repository browser.