source: src/Virtual/Tables.cc@ 34ed17b

ADT ast-experimental
Last change on this file since 34ed17b was 4f6dda0, checked in by Andrew Beach <ajbeach@…>, 4 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.