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
RevLine 
[51587aa]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//
[906e24d]7// Lvalue.cc --
[51587aa]8//
9// Author : Richard C. Bilson
10// Created On : Mon May 18 07:44:20 2015
[01aeade]11// Last Modified By : Peter A. Buhr
[615a096]12// Last Modified On : Fri Mar 17 09:11:18 2017
13// Update Count : 5
[51587aa]14//
[51b73452]15
16#include <cassert>
17
18#include "Lvalue.h"
19
[02ad3f5]20#include "GenPoly.h"
21
[51b73452]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
[d3b7937]32#include "Common/UniqueName.h"
33#include "Common/utility.h"
[ce8c12f]34#include "InitTweak/InitTweak.h"
[51b73452]35
[1d776fd]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
[51b73452]41namespace GenPoly {
[01aeade]42 namespace {
[1d776fd]43 struct ReferenceConversions final {
44 Expression * postmutate( CastExpr * castExpr );
[01aeade]45 };
46
[1d776fd]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 );
[01aeade]56 };
[b6fd751]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)
[1d776fd]61 struct GeneralizedLvalue final {
62 Expression * postmutate( AddressExpr * addressExpr );
[b6fd751]63 };
[01aeade]64 } // namespace
65
66 void convertLvalue( std::list< Declaration* >& translationUnit ) {
[1d776fd]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 );
[b6fd751]75 mutateAll( translationUnit, genLval );
[01aeade]76 }
77
78 namespace {
[02ad3f5]79 Type* isLvalueRet( FunctionType *function ) {
80 if ( function->get_returnVals().empty() ) return 0;
81 Type *ty = function->get_returnVals().front()->get_type();
[1d776fd]82 return dynamic_cast< ReferenceType * >( ty ) ;
[01aeade]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
[1d776fd]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 ) == "*?";
[01aeade]99 }
[1d776fd]100 }
101 return false;
[ce8c12f]102 }
103
[1d776fd]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 }
[ce8c12f]112 }
[1d776fd]113 return false;
[ce8c12f]114 }
115
[1d776fd]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 }
[01aeade]128
[1d776fd]129 // }
130 }
[01aeade]131
[1d776fd]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 }
[baba5d8]149 }
[1d776fd]150 }
151 return appExpr;
[01aeade]152 }
153
[1d776fd]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;
[01aeade]194 } else {
[1d776fd]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;
[01aeade]217 }
[b6fd751]218
[1d776fd]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 );
[ce8c12f]224 }
225
[1d776fd]226 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
[b6fd751]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 }
[01aeade]241 } // namespace
[51b73452]242} // namespace GenPoly
[01aeade]243
[51587aa]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.