source: src/Virtual/Tables.cc @ 8a97248

ADTast-experimental
Last change on this file since 8a97248 was 4f6dda0, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Converted Implement Concurrent Keywords to the new AST. Includes updates to various helpers, including the virtual table and a lot of examine helpers.

  • Property mode set to 100644
File size: 10.4 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// Tables.cc --
8//
9// Author           : Andrew Beach
10// Created On       : Mon Aug 31 11:11:00 2020
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Mar 11 10:40:00 2022
13// Update Count     : 3
14//
15
16#include "AST/Attribute.hpp"
17#include "AST/Copy.hpp"
18#include "AST/Decl.hpp"
19#include "AST/Expr.hpp"
20#include "AST/Init.hpp"
21#include "AST/Stmt.hpp"
22#include "AST/Type.hpp"
23#include <SynTree/Attribute.h>
24#include <SynTree/Declaration.h>
25#include <SynTree/Expression.h>
26#include <SynTree/Statement.h>
27#include <SynTree/Type.h>
28
29namespace Virtual {
30
31std::string typeIdType( std::string const & type_name ) {
32        return "__cfatid_struct_" + type_name;
33}
34
35std::string typeIdName( std::string const & type_name ) {
36        return "__cfatid_" + type_name;
37}
38
39static std::string typeIdTypeToInstance( std::string const & type_name ) {
40        return typeIdName(type_name.substr(16));
41}
42
43std::string vtableTypeName( std::string const & name ) {
44        return name + "_vtable";
45}
46
47std::string baseTypeName( std::string const & vtable_type_name ) {
48        return vtable_type_name.substr(0, vtable_type_name.size() - 7);
49}
50
51std::string instanceName( std::string const & name ) {
52        return std::string("_") + name + "_instance";
53}
54
55std::string vtableInstanceName( std::string const & name ) {
56        return instanceName( vtableTypeName( name ) );
57}
58
59std::string concurrentDefaultVTableName() {
60        return "_default_vtable";
61}
62
63bool isVTableInstanceName( std::string const & name ) {
64        // There are some delicate length calculations here.
65        return 17 < name.size() && '_' == name[0] &&
66                std::string("_vtable_instance") == name.substr(1, name.size() - 17);
67}
68
69static ObjectDecl * makeVtableDeclaration(
70                std::string const & name,
71                StructInstType * type, Initializer * init ) {
72        Type::StorageClasses storage = noStorageClasses;
73        if ( nullptr == init ) {
74                storage.is_extern = true;
75        }
76        return new ObjectDecl(
77                name,
78                storage,
79                LinkageSpec::Cforall,
80                nullptr,
81                type,
82                init
83        );
84}
85
86static ast::ObjectDecl * makeVtableDeclaration(
87                CodeLocation const & location, std::string const & name,
88                ast::StructInstType const * type, ast::Init const * init ) {
89        ast::Storage::Classes storage;
90        if ( nullptr == init ) {
91                storage.is_extern = true;
92        }
93        return new ast::ObjectDecl(
94                location,
95                name,
96                type,
97                init,
98                storage,
99                ast::Linkage::Cforall
100        );
101}
102
103ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
104        assert( type );
105        return makeVtableDeclaration( name, type, nullptr );
106}
107
108ast::ObjectDecl * makeVtableForward(
109                CodeLocation const & location, std::string const & name,
110                ast::StructInstType const * vtableType ) {
111        assert( vtableType );
112        return makeVtableDeclaration( location, name, vtableType, nullptr );
113}
114
115ObjectDecl * makeVtableInstance(
116                std::string const & name, StructInstType * vtableType,
117                Type * objectType, Initializer * init ) {
118        assert( vtableType );
119        assert( objectType );
120        StructDecl * vtableStruct = vtableType->baseStruct;
121        // Build the initialization
122        if ( nullptr == init ) {
123                std::list< Initializer * > inits;
124
125                // This is going to have to be run before the resolver to connect expressions.
126                for ( auto field : vtableStruct->members ) {
127                        if ( std::string( "parent" ) == field->name ) {
128                                // This will not work with polymorphic state.
129                                auto oField = strict_dynamic_cast< ObjectDecl * >( field );
130                                auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
131                                auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
132                                std::string const & parentInstance = instanceName( parentType->name );
133                                inits.push_back(
134                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
135                        } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
136                                std::string const & baseType = baseTypeName( vtableType->name );
137                                std::string const & typeId = typeIdName( baseType );
138                                inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
139                        } else if ( std::string( "size" ) == field->name ) {
140                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
141                        } else if ( std::string( "align" ) == field->name ) {
142                                inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
143                        } else {
144                                inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
145                        }
146                }
147                init = new ListInit( inits );
148        // This should initialize everything except the parent pointer, the
149        // size-of and align-of fields. These should be inserted.
150        } else {
151                assert(false);
152        }
153        return makeVtableDeclaration( name, vtableType, init );
154}
155
156static std::vector<ast::ptr<ast::Init>> buildInits(
157                CodeLocation const & location,
158                //std::string const & name,
159                ast::StructInstType const * vtableType,
160                ast::Type const * objectType ) {
161        ast::StructDecl const * vtableStruct = vtableType->base;
162
163        std::vector<ast::ptr<ast::Init>> inits;
164        inits.reserve( vtableStruct->members.size() );
165
166        // This is designed to run before the resolver.
167        for ( auto field : vtableStruct->members ) {
168                if ( std::string( "parent" ) == field->name ) {
169                        // This will not work with polymorphic state.
170                        auto oField = field.strict_as<ast::ObjectDecl>();
171                        auto fieldType = oField->type.strict_as<ast::PointerType>();
172                        auto parentType = fieldType->base.strict_as<ast::StructInstType>();
173                        std::string const & parentInstance = instanceName( parentType->name );
174                        inits.push_back(
175                                        new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) );
176                } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
177                        std::string const & baseType = baseTypeName( vtableType->name );
178                        std::string const & typeId = typeIdName( baseType );
179                        inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) );
180                } else if ( std::string( "size" ) == field->name ) {
181                        inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType )
182                        ) );
183                } else if ( std::string( "align" ) == field->name ) {
184                        inits.push_back( new ast::SingleInit( location,
185                                new ast::AlignofExpr( location, objectType )
186                        ) );
187                } else {
188                        inits.push_back( new ast::SingleInit( location,
189                                new ast::NameExpr( location, field->name )
190                        ) );
191                }
192                //ast::Expr * expr = buildInitExpr(...);
193                //inits.push_back( new ast::SingleInit( location, expr ) )
194        }
195
196        return inits;
197}
198
199ast::ObjectDecl * makeVtableInstance(
200                CodeLocation const & location,
201                std::string const & name,
202                ast::StructInstType const * vtableType,
203                ast::Type const * objectType,
204                ast::Init const * init ) {
205        assert( vtableType );
206        assert( objectType );
207
208        // Build the initialization.
209        if ( nullptr == init ) {
210                init = new ast::ListInit( location,
211                        buildInits( location, vtableType, objectType ) );
212
213        // The provided init should initialize everything except the parent
214        // pointer, the size-of and align-of fields. These should be inserted.
215        } else {
216                // Except this is not yet supported.
217                assert(false);
218        }
219        return makeVtableDeclaration( location, name, vtableType, init );
220}
221
222namespace {
223        std::string const functionName = "get_exception_vtable";
224}
225
226FunctionDecl * makeGetExceptionForward(
227                Type * vtableType, Type * exceptType ) {
228        assert( vtableType );
229        assert( exceptType );
230        FunctionType * type = new FunctionType( noQualifiers, false );
231        vtableType->tq.is_const = true;
232        type->returnVals.push_back( new ObjectDecl(
233                "_retvalue",
234                noStorageClasses,
235                LinkageSpec::Cforall,
236                nullptr,
237                new ReferenceType( noQualifiers, vtableType ),
238                nullptr,
239                { new Attribute("unused") }
240        ) );
241        type->parameters.push_back( new ObjectDecl(
242                "__unused",
243                noStorageClasses,
244                LinkageSpec::Cforall,
245                nullptr,
246                new PointerType( noQualifiers, exceptType ),
247                nullptr,
248                { new Attribute("unused") }
249        ) );
250        return new FunctionDecl(
251                functionName,
252                noStorageClasses,
253                LinkageSpec::Cforall,
254                type,
255                nullptr
256        );
257}
258
259ast::FunctionDecl * makeGetExceptionForward(
260                CodeLocation const & location,
261                ast::Type const * vtableType,
262                ast::Type const * exceptType ) {
263        assert( vtableType );
264        assert( exceptType );
265        return new ast::FunctionDecl(
266                location,
267                functionName,
268                { /* forall */ },
269                { new ast::ObjectDecl(
270                        location,
271                        "__unused",
272                        new ast::PointerType( exceptType )
273                ) },
274                { new ast::ObjectDecl(
275                        location,
276                        "_retvalue",
277                        new ast::ReferenceType( vtableType )
278                ) },
279                nullptr,
280                ast::Storage::Classes(),
281                ast::Linkage::Cforall,
282                { new ast::Attribute( "unused" ) }
283        );
284}
285
286FunctionDecl * makeGetExceptionFunction(
287                ObjectDecl * vtableInstance, Type * exceptType ) {
288        assert( vtableInstance );
289        assert( exceptType );
290        FunctionDecl * func = makeGetExceptionForward(
291                vtableInstance->type->clone(), exceptType );
292        func->statements = new CompoundStmt( {
293                new ReturnStmt( new VariableExpr( vtableInstance ) ),
294        } );
295        return func;
296}
297
298ast::FunctionDecl * makeGetExceptionFunction(
299                CodeLocation const & location,
300                ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) {
301        assert( vtableInstance );
302        assert( exceptType );
303        ast::FunctionDecl * func = makeGetExceptionForward(
304                        location, ast::deepCopy( vtableInstance->type ), exceptType );
305        func->stmts = new ast::CompoundStmt( location, {
306                new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) )
307        } );
308        return func;
309}
310
311ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
312        assert( typeIdType );
313        StructInstType * type = typeIdType->clone();
314        type->tq.is_const = true;
315        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
316        return new ObjectDecl(
317                typeid_name,
318                noStorageClasses,
319                LinkageSpec::Cforall,
320                /* bitfieldWidth */ nullptr,
321                type,
322                new ListInit( { new SingleInit(
323                        new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
324                        ) } ),
325                { new Attribute( "cfa_linkonce", {} ) },
326                noFuncSpecifiers
327        );
328}
329
330ast::ObjectDecl * makeTypeIdInstance(
331                CodeLocation const & location,
332                ast::StructInstType const * typeIdType ) {
333        assert( typeIdType );
334        ast::StructInstType * type = ast::mutate( typeIdType );
335        type->set_const( true );
336        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
337        return new ast::ObjectDecl(
338                location,
339                typeid_name,
340                type,
341                new ast::ListInit( location, {
342                        new ast::SingleInit( location,
343                                new ast::AddressExpr( location,
344                                        new ast::NameExpr( location, "__cfatid_exception_t" ) ) )
345                } ),
346                ast::Storage::Classes(),
347                ast::Linkage::Cforall,
348                nullptr,
349                { new ast::Attribute( "cfa_linkonce" ) }
350        );
351}
352
353}
Note: See TracBrowser for help on using the repository browser.