source: src/Virtual/Tables.cc

Last change on this file was aff7e86, checked in by Andrew Beach <ajbeach@…>, 5 months ago

Added a new attribute 'cfa_linkonce'.

  • Property mode set to 100644
File size: 5.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.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 : Wed Apr 21 15:36:00 2021
13// Update Count     : 2
14//
15
16#include <SynTree/Attribute.h>
17#include <SynTree/Declaration.h>
18#include <SynTree/Expression.h>
19#include <SynTree/Statement.h>
20#include <SynTree/Type.h>
21
22namespace Virtual {
23
24std::string typeIdType( std::string const & type_name ) {
25        return "__cfatid_struct_" + type_name;
26}
27
28std::string typeIdName( std::string const & type_name ) {
29        return "__cfatid_" + type_name;
30}
31
32static std::string typeIdTypeToInstance( std::string const & type_name ) {
33        return typeIdName(type_name.substr(16));
34}
35
36std::string vtableTypeName( std::string const & name ) {
37        return name + "_vtable";
38}
39
40std::string baseTypeName( std::string const & vtable_type_name ) {
41        return vtable_type_name.substr(0, vtable_type_name.size() - 7);
42}
43
44std::string instanceName( std::string const & name ) {
45        return std::string("_") + name + "_instance";
46}
47
48std::string vtableInstanceName( std::string const & name ) {
49        return instanceName( vtableTypeName( name ) );
50}
51
52std::string concurrentDefaultVTableName() {
53        return "_default_vtable";
54}
55
56bool isVTableInstanceName( std::string const & name ) {
57        // There are some delicate length calculations here.
58        return 17 < name.size() && '_' == name[0] &&
59                std::string("_vtable_instance") == name.substr(1, name.size() - 17);
60}
61
62static ObjectDecl * makeVtableDeclaration(
63                std::string const & name,
64                StructInstType * type, Initializer * init ) {
65        Type::StorageClasses storage = noStorageClasses;
66        if ( nullptr == init ) {
67                storage.is_extern = true;
68        }
69        return new ObjectDecl(
70                name,
71                storage,
72                LinkageSpec::Cforall,
73                nullptr,
74                type,
75                init
76        );
77}
78
79ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
80        assert( type );
81        return makeVtableDeclaration( name, type, nullptr );
82}
83
84ObjectDecl * makeVtableInstance(
85                std::string const & name, StructInstType * vtableType,
86                Type * objectType, Initializer * init ) {
87        assert( vtableType );
88        assert( objectType );
89        StructDecl * vtableStruct = vtableType->baseStruct;
90        // Build the initialization
91        if ( nullptr == init ) {
92                std::list< Initializer * > inits;
93
94                // This is going to have to be run before the resolver to connect expressions.
95                for ( auto field : vtableStruct->members ) {
96                        if ( std::string( "parent" ) == field->name ) {
97                                // This will not work with polymorphic state.
98                                auto oField = strict_dynamic_cast< ObjectDecl * >( field );
99                                auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
100                                auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
101                                std::string const & parentInstance = instanceName( parentType->name );
102                                inits.push_back(
103                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
104                        } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
105                                std::string const & baseType = baseTypeName( vtableType->name );
106                                std::string const & typeId = typeIdName( baseType );
107                                inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
108                        } else if ( std::string( "size" ) == field->name ) {
109                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
110                        } else if ( std::string( "align" ) == field->name ) {
111                                inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
112                        } else {
113                                inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
114                        }
115                }
116                init = new ListInit( inits );
117        // This should initialize everything except the parent pointer, the
118        // size-of and align-of fields. These should be inserted.
119        } else {
120                assert(false);
121        }
122        return makeVtableDeclaration( name, vtableType, init );
123}
124
125namespace {
126        std::string const functionName = "get_exception_vtable";
127}
128
129FunctionDecl * makeGetExceptionForward(
130                Type * vtableType, Type * exceptType ) {
131        assert( vtableType );
132        assert( exceptType );
133        FunctionType * type = new FunctionType( noQualifiers, false );
134        vtableType->tq.is_const = true;
135        type->returnVals.push_back( new ObjectDecl(
136                "_retvalue",
137                noStorageClasses,
138                LinkageSpec::Cforall,
139                nullptr,
140                new ReferenceType( noQualifiers, vtableType ),
141                nullptr,
142        { new Attribute("unused") }
143        ) );
144        type->parameters.push_back( new ObjectDecl(
145                "__unused",
146                noStorageClasses,
147                LinkageSpec::Cforall,
148                nullptr,
149                new PointerType( noQualifiers, exceptType ),
150                nullptr,
151                { new Attribute("unused") }
152        ) );
153        return new FunctionDecl(
154                functionName,
155                noStorageClasses,
156                LinkageSpec::Cforall,
157                type,
158                nullptr
159        );
160}
161
162FunctionDecl * makeGetExceptionFunction(
163                ObjectDecl * vtableInstance, Type * exceptType ) {
164        assert( vtableInstance );
165        assert( exceptType );
166        FunctionDecl * func = makeGetExceptionForward(
167                vtableInstance->type->clone(), exceptType );
168        func->statements = new CompoundStmt( {
169                new ReturnStmt( new VariableExpr( vtableInstance ) ),
170        } );
171        return func;
172}
173
174ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
175        assert( typeIdType );
176        StructInstType * type = typeIdType->clone();
177        type->tq.is_const = true;
178        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
179        return new ObjectDecl(
180                typeid_name,
181                noStorageClasses,
182                LinkageSpec::Cforall,
183                /* bitfieldWidth */ nullptr,
184                type,
185                new ListInit( { new SingleInit(
186                        new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
187                        ) } ),
188                { new Attribute( "cfa_linkonce", {} ) },
189                noFuncSpecifiers
190        );
191}
192
193}
Note: See TracBrowser for help on using the repository browser.