source: src/ControlStruct/ExceptDecl.cc @ 0351e9f

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since 0351e9f was da602aec, checked in by Henry Xue <y58xue@…>, 3 years ago

Fix forall variant extern vtable decls

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