source: src/Virtual/Tables.cpp @ 876739f

Last change on this file since 876739f was 3e135c8, checked in by Andrew Beach <ajbeach@…>, 2 weeks 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.