source: src/GenPoly/Lvalue.cc @ f19339e

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since f19339e was 1d776fd, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Implement reference conversion translation for basic reference conversions

  • Property mode set to 100644
File size: 9.4 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 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// Lvalue.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Mar 17 09:11:18 2017
13// Update Count     : 5
14//
15
16#include <cassert>
17
18#include "Lvalue.h"
19
20#include "GenPoly.h"
21
22#include "SynTree/Declaration.h"
23#include "SynTree/Type.h"
24#include "SynTree/Expression.h"
25#include "SynTree/Statement.h"
26#include "SynTree/Visitor.h"
27#include "SynTree/Mutator.h"
28#include "SymTab/Indexer.h"
29#include "ResolvExpr/Resolver.h"
30#include "ResolvExpr/typeops.h"
31
32#include "Common/UniqueName.h"
33#include "Common/utility.h"
34#include "InitTweak/InitTweak.h"
35
36#include "Common/PassVisitor.h"
37
38// need to be careful about polymorphic references... e.g. in *? (___operator_deref__A0_1_0_0__Fd0_Pd0_intrinsic___1)
39// the variable is automatically dereferenced and this causes errors dereferencing void*.
40
41namespace GenPoly {
42        namespace {
43                struct ReferenceConversions final {
44                        Expression * postmutate( CastExpr * castExpr );
45                };
46
47                /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
48                struct FixIntrinsicArgs final {
49                        Expression * postmutate( ApplicationExpr *appExpr );
50                };
51
52
53                /// Replace reference types with pointer types
54                struct ReferenceTypeElimination final {
55                        Type * postmutate( ReferenceType * refType );
56                };
57
58                /// GCC-like Generalized Lvalues (which have since been removed from GCC)
59                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
60                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
61                struct GeneralizedLvalue final {
62                        Expression * postmutate( AddressExpr * addressExpr );
63                };
64        } // namespace
65
66        void convertLvalue( std::list< Declaration* >& translationUnit ) {
67                std::cerr << "convertLvalue" << std::endl;
68                PassVisitor<ReferenceConversions> refCvt;
69                PassVisitor<ReferenceTypeElimination> elim;
70                PassVisitor<GeneralizedLvalue> genLval;
71                PassVisitor<FixIntrinsicArgs> fixer;
72                mutateAll( translationUnit, refCvt );
73                mutateAll( translationUnit, fixer );
74                mutateAll( translationUnit, elim );
75                mutateAll( translationUnit, genLval );
76        }
77
78        namespace {
79                Type* isLvalueRet( FunctionType *function ) {
80                        if ( function->get_returnVals().empty() ) return 0;
81                        Type *ty = function->get_returnVals().front()->get_type();
82                        return dynamic_cast< ReferenceType * >( ty ) ;
83                }
84
85                bool isIntrinsicApp( ApplicationExpr *appExpr ) {
86                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
87                                return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
88                        } else {
89                                return false;
90                        } // if
91                }
92
93                bool isDeref( Expression * expr ) {
94                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
95                                return InitTweak::getFunctionName( untyped ) == "*?";
96                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
97                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
98                                        return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "*?";
99                                }
100                        }
101                        return false;
102                }
103
104                bool isIntrinsicReference( Expression * expr ) {
105                        if ( isDeref( expr ) ) return true;
106                        else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
107                                return InitTweak::getFunctionName( untyped ) == "?[?]";
108                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
109                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
110                                        return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "?[?]";
111                                }
112                        }
113                        return false;
114                }
115
116                void fixArg( Expression *& arg, Type * formal ) {
117                        // if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
118                                if ( dynamic_cast<ReferenceType*>( formal ) ) { // xxx - but might be deref, in which case result isn't REALLY a reference, at least not in the sense that we need to add another deref...
119                                        // doesn't work, for some reason left arg is skipped in assign
120                                        ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() ) ;
121                                        std::cerr << "appexpr arg is non-deref/index intrinsic call" << std::endl;
122                                        std::cerr << arg << std::endl;
123                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), refType->get_base()->clone() );
124                                        delete refType;
125                                        arg->set_result( ptrType );
126                                        arg = UntypedExpr::createDeref( arg );
127                                }
128
129                        // }
130                }
131
132                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
133                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
134                                if ( function->get_linkage() == LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
135                                        FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
136                                        assertf( ftype, "Function declaration does not have function type." );
137                                        for ( auto p : group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
138                                                Expression *& arg = std::get<0>( p );
139                                                DeclarationWithType * formal = std::get<1>( p );
140                                                std::cerr << "pair<0>: " << arg << std::endl;
141                                                std::cerr << "pair<1>: " << formal->get_type() << std::endl;
142                                                if ( isIntrinsicReference( arg ) ) {
143                                                        std::cerr << "skipping intrinsic reference" << std::endl;
144                                                        continue;
145                                                } else {
146                                                        fixArg( arg, formal->get_type() );
147                                                }
148                                        }
149                                }
150                        }
151                        return appExpr;
152                }
153
154                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
155                        // conversion to reference type
156                        if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
157                                (void)refType;
158                                if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
159                                        // nothing to do if casting from reference to reference.
160                                        (void)otherRef;
161                                        std::cerr << "convert reference to reference -- nop" << std::endl;
162                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
163                                                Expression * callExpr = castExpr->get_arg();
164                                                Expression ** arg = nullptr;
165                                                Expression *& arg0 = InitTweak::getCallArg( callExpr, 0 );
166                                                if ( dynamic_cast<PointerType *>( arg0->get_result() ) ) {
167                                                        arg = &arg0;
168                                                } else {
169                                                        arg = &InitTweak::getCallArg( callExpr, 1 );
170                                                }
171
172                                                castExpr->set_arg( *arg );
173                                                *arg = castExpr;
174                                                std::cerr << "but arg is deref -- &" << std::endl;
175                                                std::cerr << callExpr << std::endl;
176                                                // castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) );
177
178                                                // move environment out to new top-level
179                                                callExpr->set_env( castExpr->get_env() );
180                                                castExpr->set_env( nullptr );
181                                                return callExpr;
182                                        }
183                                        std::cerr << castExpr << std::endl;
184                                        return castExpr;
185                                } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
186                                        // conversion from lvalue to reference
187                                        // xxx - keep cast, but turn into pointer cast??
188                                        // xxx - memory
189                                        std::cerr << "convert lvalue to reference -- &" << std::endl;
190                                        std::cerr << castExpr->get_arg() << std::endl;
191                                        castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) );
192                                        // return new AddressExpr( castExpr->get_arg() );
193                                        return castExpr;
194                                } else {
195                                        // rvalue to reference conversion -- introduce temporary
196                                }
197                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
198                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
199                                // should be easy, just need to move deref code up here?
200                                std::cerr << "convert reference to rvalue -- *" << std::endl;
201                                if ( isIntrinsicReference( castExpr->get_arg() ) ) {
202                                        std::cerr << "but arg is intrinsic reference -- nop" << std::endl;
203                                        return castExpr;
204                                }
205                                std::cerr << castExpr << std::endl;
206
207                                PointerType * ptrType = new PointerType( refType->get_qualifiers(), refType->get_base()->clone() );
208                                delete castExpr->get_result();
209                                castExpr->set_result( ptrType );
210                                Expression * deref = UntypedExpr::createDeref( castExpr );
211                                deref->set_env( castExpr->get_env() );
212                                castExpr->set_env( nullptr );
213                                return deref;
214                                // assertf( false, "Conversions from reference types are not currently supported." );
215                        }
216                        return castExpr;
217                }
218
219                Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
220                        Type * base = refType->get_base();
221                        refType->set_base( nullptr );
222                        delete refType;
223                        return new PointerType( Type::Qualifiers(), base );
224                }
225
226                Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
227                        if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( addrExpr->get_arg() ) ) {
228                                Expression * arg1 = commaExpr->get_arg1()->clone();
229                                Expression * arg2 = commaExpr->get_arg2()->clone();
230                                delete addrExpr;
231                                return new CommaExpr( arg1, new AddressExpr( arg2 ) );
232                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
233                                Expression * arg1 = condExpr->get_arg1()->clone();
234                                Expression * arg2 = condExpr->get_arg2()->clone();
235                                Expression * arg3 = condExpr->get_arg3()->clone();
236                                delete addrExpr;
237                                return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) );
238                        }
239                        return addrExpr;
240                }
241        } // namespace
242} // namespace GenPoly
243
244// Local Variables: //
245// tab-width: 4 //
246// mode: c++ //
247// compile-command: "make install" //
248// End: //
Note: See TracBrowser for help on using the repository browser.