source: src/SymTab/GenImplicitCall.cpp @ 60c5b6d

Last change on this file since 60c5b6d was 4e2f1b2, checked in by Andrew Beach <ajbeach@…>, 9 months ago

Clean-up of GenImplicitCall? module. Changing the return type for consistency spilled out into some other files, but that should also saves some operations. The other big one is the template instances were reduced to one and then the templates removed.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 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// GenImplicitCall.cpp -- Generate code for implicit operator calls.
8//
9// Author           : Andrew Beach
10// Created On       : Fri Apr 14 14:38:00 2023
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Apr 14 14:46:00 2023
13// Update Count     : 0
14//
15
16#include "GenImplicitCall.hpp"
17
18#include "AST/Copy.hpp"                  // for deepCopy
19#include "AST/Decl.hpp"                  // for ObjectDecl
20#include "AST/Expr.hpp"                  // for ConstantExpr, UntypedExpr,...
21#include "AST/Init.hpp"                  // for SingleInit
22#include "AST/Inspect.hpp"               // for isUnnamedBitfield
23#include "AST/Stmt.hpp"                  // for ExprStmt
24#include "AST/Type.hpp"                  // for ArrayType, BasicType, ...
25#include "CodeGen/OperatorTable.h"       // for isCtorDtor
26#include "Common/UniqueName.h"           // for UniqueName
27#include "Common/utility.h"              // for splice
28
29namespace SymTab {
30
31namespace {
32
33using Inserter = std::back_insert_iterator<std::list<ast::ptr<ast::Stmt>>>;
34
35ast::ptr< ast::Stmt > genCall(
36        InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
37        const CodeLocation & loc, const std::string & fname, Inserter && out,
38        const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
39
40/// inserts into out a generated call expression to function fname with arguments dstParam and
41/// srcParam. Should only be called with non-array types.
42/// optionally returns a statement which must be inserted prior to the containing loop, if
43/// there is one
44ast::ptr< ast::Stmt > genScalarCall(
45        InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
46        const CodeLocation & loc, std::string fname, Inserter && out, const ast::Type * type,
47        const ast::Type * addCast = nullptr
48) {
49        bool isReferenceCtorDtor = false;
50        if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
51                // reference constructors are essentially application of the rebind operator.
52                // apply & to both arguments, do not need a cast
53                fname = "?=?";
54                dstParam = new ast::AddressExpr( dstParam );
55                addCast = nullptr;
56                isReferenceCtorDtor = true;
57        }
58
59        // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
60        // "?=?", "?{}", or "^?{}"
61        ast::UntypedExpr * fExpr = new ast::UntypedExpr( loc, new ast::NameExpr( loc, fname ) );
62
63        if ( addCast ) {
64                // cast to T& with qualifiers removed, so that qualified objects can be constructed and
65                // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
66                // is considered a qualifier - for AddressExpr to resolve, its argument must have an
67                // lvalue-qualified type, so remove all qualifiers except lvalue.
68                // xxx -- old code actually removed lvalue too...
69                ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
70                ast::ptr< ast::Type > castType = addCast;
71                ast::remove_qualifiers(
72                        castType,
73                        ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
74                        dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
75        }
76        fExpr->args.emplace_back( dstParam );
77
78        ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
79
80        // fetch next set of arguments
81        ++srcParam;
82
83        // return if adding reference fails -- will happen on default ctor and dtor
84        if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
85
86        std::vector< ast::ptr< ast::Expr > > args = *srcParam;
87        splice( fExpr->args, args );
88
89        *out++ = new ast::ExprStmt{ loc, fExpr };
90
91        srcParam.clearArrayIndices();
92
93        return listInit;
94}
95
96
97/// Store in out a loop which calls fname on each element of the array with srcParam and
98/// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
99void genArrayCall(
100        InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
101        const CodeLocation & loc, const std::string & fname, Inserter && out,
102        const ast::ArrayType * array, const ast::Type * addCast = nullptr,
103        LoopDirection forward = LoopForward
104) {
105        static UniqueName indexName( "_index" );
106
107        // for a flexible array member nothing is done -- user must define own assignment
108        if ( ! array->dimension ) return;
109
110        if ( addCast ) {
111                // peel off array layer from cast
112                addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
113        }
114
115        ast::ptr< ast::Expr > begin, end;
116        std::string cmp, update;
117
118        const ast::Expr * dimension = deepCopy( array->dimension );
119        if ( forward ) {
120                // generate: for ( int i = 0; i < N; ++i )
121                begin = ast::ConstantExpr::from_int( loc, 0 );
122                end = dimension;
123                cmp = "?<?";
124                update = "++?";
125        } else {
126                // generate: for ( int i = N-1; i >= 0; --i )
127                begin = ast::UntypedExpr::createCall( loc, "?-?",
128                        { dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
129                end = ast::ConstantExpr::from_int( loc, 0 );
130                cmp = "?>=?";
131                update = "--?";
132        }
133
134        ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl(
135                loc, indexName.newName(), new ast::BasicType( ast::BasicType::SignedInt ),
136                new ast::SingleInit( loc, begin ) );
137        ast::ptr< ast::Expr > indexVar = new ast::VariableExpr( loc, index );
138
139        ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
140                loc, cmp, { indexVar, end } );
141
142        ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
143                loc, update, { indexVar } );
144
145        ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
146                loc, "?[?]", { dstParam, indexVar } );
147
148        // srcParam must keep track of the array indices to build the source parameter and/or
149        // array list initializer
150        srcParam.addArrayIndex( indexVar, array->dimension );
151
152        // for stmt's body, eventually containing call
153        ast::CompoundStmt * body = new ast::CompoundStmt( loc );
154        ast::ptr< ast::Stmt > listInit = genCall(
155                srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
156                forward );
157
158        // block containing the stmt and index variable
159        ast::CompoundStmt * block = new ast::CompoundStmt( loc );
160        block->push_back( new ast::DeclStmt( loc, index ) );
161        if ( listInit ) { block->push_back( listInit ); }
162        block->push_back( new ast::ForStmt( loc, {}, cond, inc, body ) );
163
164        *out++ = block;
165}
166
167ast::ptr< ast::Stmt > genCall(
168        InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
169        const CodeLocation & loc, const std::string & fname, Inserter && out,
170        const ast::Type * type, const ast::Type * addCast, LoopDirection forward
171) {
172        if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
173                genArrayCall(
174                        srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), at, addCast,
175                        forward );
176                return {};
177        } else {
178                return genScalarCall(
179                        srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), type, addCast );
180        }
181}
182
183} // namespace
184
185const ast::Stmt * genImplicitCall(
186        InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
187        const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
188        LoopDirection forward
189) {
190        // unnamed bit fields are not copied as they cannot be accessed
191        if ( isUnnamedBitfield( obj ) ) return nullptr;
192
193        ast::ptr< ast::Type > addCast;
194        if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
195                assert( dstParam->result );
196                addCast = dstParam->result;
197        }
198
199        std::list< ast::ptr< ast::Stmt > > stmts;
200        genCall(
201                srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
202
203        if ( stmts.empty() ) return nullptr;
204        assert( stmts.size() == 1 );
205
206        const ast::Stmt * callStmt = stmts.front().release();
207        // Implicitly generated ctor/dtor calls should be wrapped so that
208        // later passes are aware they were generated.
209        if ( addCast ) {
210                callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt );
211        }
212        return callStmt;
213}
214
215} // namespace SymTab
216
217// Local Variables: //
218// tab-width: 4 //
219// mode: c++ //
220// compile-command: "make install" //
221// End: //
Note: See TracBrowser for help on using the repository browser.