source: src/Virtual/Tables.cpp@ fc276f3

Last change on this file since fc276f3 was 3e135c8, checked in by Andrew Beach <ajbeach@…>, 14 months ago

Not sure why we copy in the return values all the time, but we do. This prevents an unused error from appearing when the library is being compiled (shows up about 4 times right now). Switching some passes around might have also solved the problem, but I think we should be generating normalized code instead of mixing in the normalization and code generation.

  • Property mode set to 100644
File size: 6.5 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.cpp --
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
24namespace Virtual {
25
26std::string typeIdType( std::string const & type_name ) {
27 return "__cfatid_struct_" + type_name;
28}
29
30std::string typeIdName( std::string const & type_name ) {
31 return "__cfatid_" + type_name;
32}
33
34static std::string typeIdTypeToInstance( std::string const & type_name ) {
35 return typeIdName(type_name.substr(16));
36}
37
38std::string vtableTypeName( std::string const & name ) {
39 return name + "_vtable";
40}
41
42std::string baseTypeName( std::string const & vtable_type_name ) {
43 return vtable_type_name.substr(0, vtable_type_name.size() - 7);
44}
45
46std::string instanceName( std::string const & name ) {
47 return std::string("_") + name + "_instance";
48}
49
50std::string vtableInstanceName( std::string const & name ) {
51 return instanceName( vtableTypeName( name ) );
52}
53
54std::string concurrentDefaultVTableName() {
55 return "_default_vtable";
56}
57
58bool isVTableInstanceName( std::string const & name ) {
59 // There are some delicate length calculations here.
60 return 17 < name.size() && '_' == name[0] &&
61 std::string("_vtable_instance") == name.substr(1, name.size() - 17);
62}
63
64static ast::ObjectDecl * makeVtableDeclaration(
65 CodeLocation const & location, std::string const & name,
66 ast::StructInstType const * type, ast::Init const * init ) {
67 ast::Storage::Classes storage;
68 if ( nullptr == init ) {
69 storage.is_extern = true;
70 }
71 return new ast::ObjectDecl(
72 location,
73 name,
74 type,
75 init,
76 storage,
77 ast::Linkage::Cforall
78 );
79}
80
81ast::ObjectDecl * makeVtableForward(
82 CodeLocation const & location, std::string const & name,
83 ast::StructInstType const * vtableType ) {
84 assert( vtableType );
85 return makeVtableDeclaration( location, name, vtableType, nullptr );
86}
87
88static std::vector<ast::ptr<ast::Init>> buildInits(
89 CodeLocation const & location,
90 //std::string const & name,
91 ast::StructInstType const * vtableType,
92 ast::Type const * objectType ) {
93 ast::StructDecl const * vtableStruct = vtableType->base;
94
95 std::vector<ast::ptr<ast::Init>> inits;
96 inits.reserve( vtableStruct->members.size() );
97
98 // This is designed to run before the resolver.
99 for ( auto field : vtableStruct->members ) {
100 if ( std::string( "parent" ) == field->name ) {
101 // This will not work with polymorphic state.
102 auto oField = field.strict_as<ast::ObjectDecl>();
103 auto fieldType = oField->type.strict_as<ast::PointerType>();
104 auto parentType = fieldType->base.strict_as<ast::StructInstType>();
105 std::string const & parentInstance = instanceName( parentType->name );
106 inits.push_back(
107 new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) );
108 } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
109 std::string const & baseType = baseTypeName( vtableType->name );
110 std::string const & typeId = typeIdName( baseType );
111 inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) );
112 } else if ( std::string( "size" ) == field->name ) {
113 inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType )
114 ) );
115 } else if ( std::string( "align" ) == field->name ) {
116 inits.push_back( new ast::SingleInit( location,
117 new ast::AlignofExpr( location, objectType )
118 ) );
119 } else {
120 inits.push_back( new ast::SingleInit( location,
121 new ast::NameExpr( location, field->name )
122 ) );
123 }
124 }
125
126 return inits;
127}
128
129ast::ObjectDecl * makeVtableInstance(
130 CodeLocation const & location,
131 std::string const & name,
132 ast::StructInstType const * vtableType,
133 ast::Type const * objectType,
134 ast::Init const * init ) {
135 assert( vtableType );
136 assert( objectType );
137
138 // Build the initialization.
139 if ( nullptr == init ) {
140 init = new ast::ListInit( location,
141 buildInits( location, vtableType, objectType ) );
142
143 // The provided init should initialize everything except the parent
144 // pointer, the size-of and align-of fields. These should be inserted.
145 } else {
146 // Except this is not yet supported.
147 assert(false);
148 }
149 return makeVtableDeclaration( location, name, vtableType, init );
150}
151
152namespace {
153 std::string const functionName = "get_exception_vtable";
154}
155
156ast::FunctionDecl * makeGetExceptionForward(
157 CodeLocation const & location,
158 ast::Type const * vtableType,
159 ast::Type const * exceptType ) {
160 assert( vtableType );
161 assert( exceptType );
162
163 // If this is called after Fix Return Statements (currently it is in
164 // Implement Concurrent Keywords) then this must be marked as unused
165 // to avoid warnings.
166 ast::ObjectDecl * frontRet = new ast::ObjectDecl( location,
167 "_retvalue",
168 new ast::ReferenceType( vtableType )
169 );
170 frontRet->attributes.emplace_back( new ast::Attribute( "unused" ) );
171
172 return new ast::FunctionDecl(
173 location,
174 functionName,
175 { new ast::ObjectDecl(
176 location,
177 "__unused",
178 new ast::PointerType( exceptType )
179 ) },
180 { frontRet },
181 nullptr,
182 ast::Storage::Classes(),
183 ast::Linkage::Cforall,
184 { new ast::Attribute( "unused" ) }
185 );
186}
187
188ast::FunctionDecl * makeGetExceptionFunction(
189 CodeLocation const & location,
190 ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) {
191 assert( vtableInstance );
192 assert( exceptType );
193 ast::FunctionDecl * func = makeGetExceptionForward(
194 location, ast::deepCopy( vtableInstance->type ), exceptType );
195 func->stmts = new ast::CompoundStmt( location, {
196 new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) )
197 } );
198 return func;
199}
200
201ast::ObjectDecl * makeTypeIdInstance(
202 CodeLocation const & location,
203 ast::StructInstType const * typeIdType ) {
204 assert( typeIdType );
205 ast::StructInstType * type = ast::mutate( typeIdType );
206 type->set_const( true );
207 std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
208 return new ast::ObjectDecl(
209 location,
210 typeid_name,
211 type,
212 new ast::ListInit( location, {
213 new ast::SingleInit( location,
214 new ast::AddressExpr( location,
215 new ast::NameExpr( location, "__cfatid_exception_t" ) ) )
216 } ),
217 ast::Storage::Classes(),
218 ast::Linkage::Cforall,
219 nullptr,
220 { new ast::Attribute( "cfa_linkonce" ) }
221 );
222}
223
224}
Note: See TracBrowser for help on using the repository browser.