source: src/GenPoly/Lvalue.cc@ bf30ab3

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since bf30ab3 was 1d776fd, checked in by Rob Schluntz <rschlunt@…>, 8 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.