source: src/Virtual/Tables.cpp @ d96f7c4

Last change on this file since d96f7c4 was d3cf623, checked in by Andrew Beach <ajbeach@…>, 4 weeks ago

Solved the requested warning with exceptions. Also went through the exceptions tests and managed to remove about 2/3rds of them from the lax list that now either didn't have any warnings or warnings because of the test itself.

  • Property mode set to 100644
File size: 6.6 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                        /* The parameter only exists to provide a type id. */ "",
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.