Inferno
0.2
|
00001 00002 #include "cpptree.hpp" 00003 #include "type_db.hpp" 00004 #include "helpers/walk.hpp" 00005 #include "misc.hpp" 00006 #include "typeof.hpp" 00007 00008 using namespace CPPTree; 00009 00010 00011 #define INT 0 00012 00013 TreePtr<Type> TypeOf::Get( TreePtr<Expression> o ) 00014 { 00015 ASSERT(o); 00016 00017 if( TreePtr<SpecificInstanceIdentifier> ii = dynamic_pointer_cast<SpecificInstanceIdentifier>(o) ) // object or function instance 00018 { 00019 TreePtr<Node> n = GetDeclaration()(context, ii); 00020 TreePtr<Instance> i = dynamic_pointer_cast<Instance>(n); 00021 ASSERT(i); 00022 return i->type; 00023 } 00024 else if( TreePtr<NonCommutativeOperator> op = dynamic_pointer_cast<NonCommutativeOperator>(o) ) // operator 00025 { 00026 // Get the types of all the operands to the operator first 00027 Sequence<Type> optypes; 00028 FOREACH( TreePtr<Expression> o, op->operands ) 00029 optypes.push_back( Get(o) ); 00030 return Get( op, optypes ); 00031 } 00032 else if( TreePtr<CommutativeOperator> op = dynamic_pointer_cast<CommutativeOperator>(o) ) // operator 00033 { 00034 // Get the types of all the operands to the operator first 00035 Sequence<Type> optypes; 00036 FOREACH( TreePtr<Expression> o, op->operands ) 00037 optypes.push_back( Get(o) ); 00038 return Get( op, optypes ); 00039 } 00040 else if( TreePtr<Literal> l = dynamic_pointer_cast<Literal>(o) ) 00041 { 00042 return GetLiteral( l ); 00043 } 00044 else if( TreePtr<Call> c = dynamic_pointer_cast<Call>(o) ) 00045 { 00046 TreePtr<Type> t = Get(c->callee); // get type of the function itself 00047 ASSERT( dynamic_pointer_cast<Callable>(t) )( "Trying to call something that is not Callable"); 00048 if( TreePtr<Function> f = dynamic_pointer_cast<Function>(t) ) 00049 return f->return_type; 00050 else 00051 return MakeTreePtr<Void>(); 00052 } 00053 else if( TreePtr<Lookup> l = dynamic_pointer_cast<Lookup>(o) ) // a.b; just return type of b 00054 { 00055 TreePtr<Type> t = Get( l->member ); 00056 TRACE("TypeOf Lookup: ")(*(l->base))(" . ")(*(l->member))(" is ")(*t)("\n"); 00057 return t; 00058 } 00059 else if( TreePtr<Cast> c = dynamic_pointer_cast<Cast>(o) ) 00060 { 00061 return c->type; 00062 } 00063 else if( TreePtr<MakeRecord> rl = dynamic_pointer_cast<MakeRecord>(o) ) 00064 { 00065 return rl->type; 00066 } 00067 else if( dynamic_pointer_cast<LabelIdentifier>(o) ) 00068 { 00069 return MakeTreePtr<Type>(); // TODO labels need a type 00070 } 00071 else if( dynamic_pointer_cast<SizeOf>(o) || dynamic_pointer_cast<AlignOf>(o)) 00072 { 00073 TreePtr<Integral> n; 00074 if( TypeDb::int_default_signed ) 00075 n = MakeTreePtr<Signed>(); 00076 else 00077 n = MakeTreePtr<Unsigned>(); 00078 TreePtr<SpecificInteger> sz( new SpecificInteger(TypeDb::integral_bits[INT]) ); 00079 n->width = sz; 00080 return n; 00081 } 00082 else if( TreePtr<New> n = dynamic_pointer_cast<New>(o) ) 00083 { 00084 TreePtr<Pointer> p( new Pointer ); 00085 p->destination = n->type; 00086 return p; 00087 } 00088 else if( dynamic_pointer_cast<Delete>(o) ) 00089 { 00090 return MakeTreePtr<Type>(); 00091 } 00092 else if( TreePtr<CompoundExpression> ce = dynamic_pointer_cast<CompoundExpression>(o) ) 00093 { 00094 int sz = ce->statements.size(); 00095 if( !sz ) 00096 return MakeTreePtr<Type>(); 00097 TreePtr<Statement> last = ce->statements[sz-1]; 00098 if( TreePtr<Expression> e = dynamic_pointer_cast<Expression>(last) ) 00099 return Get(e); 00100 else 00101 return MakeTreePtr<Type>(); 00102 } 00103 else 00104 { 00105 ASSERT(0)("Unknown expression ")(*o)(", please add to TypeOf class"); 00106 ASSERTFAIL(""); 00107 } 00108 } 00109 00110 // Just discover the type of operators, where the types of the operands have already been determined 00111 // Note we always get a Sequence, even when the operator is commutative 00112 TreePtr<Type> TypeOf::Get( TreePtr<Operator> op, Sequence<Type> optypes ) 00113 { 00114 // Lower types that masquerade as other types in preparation for operand analysis 00115 // - References go to the referenced type 00116 // - Arrays go to pointers 00117 FOREACH( TreePtr<Type> &t, optypes ) 00118 { 00119 while( TreePtr<Reference> r = dynamic_pointer_cast<Reference>(t) ) 00120 t = r->destination; 00121 if( TreePtr<Array> a = dynamic_pointer_cast<Array>(t) ) 00122 { 00123 TreePtr<Pointer> p( new Pointer ); 00124 p->destination = a->element; 00125 t = p; 00126 } 00127 // Check we finished the job 00128 ASSERT( !dynamic_pointer_cast<Reference>(t) ); 00129 ASSERT( !dynamic_pointer_cast<Array>(t) ); 00130 } 00131 00132 // Turn an array literal into an array 00133 if( TreePtr<MakeArray> al = dynamic_pointer_cast<MakeArray>(op) ) 00134 { 00135 TreePtr<Array> a( new Array ); 00136 a->element = optypes[0]; 00137 TreePtr<SpecificInteger> sz( new SpecificInteger(optypes.size()) ); 00138 a->size = sz; 00139 return a; 00140 } 00141 00142 // Assignment operators return their left-hand operand type in all cases 00143 if( dynamic_pointer_cast<AssignmentOperator>(op) ) 00144 { 00145 return optypes[0]; 00146 } 00147 00148 // Pointer arithmetic: a subtract involving two pointers returns int 00149 // we are not bothering to check that the pointer types are compatible. 00150 if( dynamic_pointer_cast<Subtract>(op) ) 00151 { 00152 if( dynamic_pointer_cast<Pointer>(optypes[0]) && dynamic_pointer_cast<Pointer>(optypes[1]) ) 00153 { 00154 TreePtr<Signed> i = TreePtr<Signed>( new Signed ); 00155 TreePtr<SpecificInteger> nc( new SpecificInteger(TypeDb::integral_bits[INT]) ); 00156 i->width = nc; 00157 return i; 00158 } 00159 } 00160 00161 // Pointer arithmetic: an add or subtract involving a pointer returns that pointer type 00162 if( dynamic_pointer_cast<Add>(op) || dynamic_pointer_cast<Subtract>(op) ) 00163 { 00164 FOREACH( TreePtr<Type> t, optypes ) 00165 if( TreePtr<Pointer> p = dynamic_pointer_cast<Pointer>(t) ) 00166 return p; 00167 } 00168 00169 #define ARITHMETIC GetStandard( optypes ) 00170 #define BITWISE GetStandard( optypes ) 00171 #define LOGICAL MakeTreePtr<Boolean>() 00172 #define COMPARISON MakeTreePtr<Boolean>() 00173 #define SHIFT optypes[0] 00174 #define SPECIAL GetSpecial( op, optypes ) 00175 00176 if(0) {} 00177 #define INFIX(TOK, TEXT, NODE, BASE, CAT) \ 00178 else if( dynamic_pointer_cast<NODE>(op) ) \ 00179 return CAT; 00180 #define PREFIX(TOK, TEXT, NODE, BASE, CAT) \ 00181 else if( dynamic_pointer_cast<NODE>(op) ) \ 00182 return CAT; 00183 #define POSTFIX(TOK, TEXT, NODE, BASE, CAT) \ 00184 else if( dynamic_pointer_cast<NODE>(op) ) \ 00185 return CAT; 00186 #define OTHER(TOK, TEXT, NODE, BASE, CAT) \ 00187 else if( dynamic_pointer_cast<NODE>(op) ) \ 00188 return CAT; 00189 #include "tree/operator_db.inc" 00190 else 00191 { 00192 ASSERT(0)("Unknown operator ")(*op)(" (not in operator_db.inc), please add to TypeOf class"); 00193 ASSERTFAIL(""); 00194 } 00195 } 00196 00197 00198 TreePtr<Type> TypeOf::GetStandard( Sequence<Type> &optypes ) 00199 { 00200 Sequence<Numeric> nums; 00201 for( int i=0; i<optypes.size(); i++ ) 00202 if( TreePtr<Numeric> n = dynamic_pointer_cast<Numeric>(optypes[i]) ) 00203 nums.push_back(n); 00204 if( nums.size() == optypes.size() ) 00205 return GetStandard( nums ); 00206 00207 if( optypes.size() == 2 ) 00208 ASSERT(0)("Standard operator with operands ")(*optypes[0])(*optypes[1])(" is unknown usage, please add to TypeOf class"); 00209 else 00210 ASSERT(0)("Standard operator with ")(*optypes[0])(" is unknown usage, please add to TypeOf class"); 00211 ASSERTFAIL(); 00212 } 00213 00214 00215 TreePtr<Type> TypeOf::GetStandard( Sequence<Numeric> &optypes ) 00216 { 00217 // Start the width and signedness as per regular "int" since this is the 00218 // minimum result type for standard operators 00219 TreePtr<SpecificInteger> maxwidth_signed( new SpecificInteger(TypeDb::integral_bits[INT]) ); 00220 TreePtr<SpecificInteger> maxwidth_unsigned; 00221 TreePtr<SpecificFloatSemantics> maxwidth_float; 00222 00223 // Look at the operands in turn 00224 for( int i=0; i<optypes.size(); i++ ) 00225 { 00226 // Floats take priority 00227 if( TreePtr<Floating> f = dynamic_pointer_cast<Floating>(optypes[i]) ) 00228 { 00229 TreePtr<SpecificFloatSemantics> sfs = dynamic_pointer_cast<SpecificFloatSemantics>(f->semantics); 00230 ASSERT(sfs)("Floating point type seen with semantics not specific"); 00231 unsigned int sl = llvm::APFloat::semanticsPrecision( *sfs ); 00232 unsigned int sr = llvm::APFloat::semanticsPrecision( *maxwidth_float ); 00233 if( !maxwidth_float || sl > sr ) 00234 maxwidth_float = sfs; 00235 } 00236 00237 // Should only have Integrals from here on 00238 TreePtr<Integral> intop = dynamic_pointer_cast<Integral>(optypes[i]); 00239 ASSERT( intop )(*optypes[i])(" is not Floating or Integral, please add to TypeOf class" ); 00240 00241 // Do a max algorithm on the width 00242 TreePtr<SpecificInteger> width = dynamic_pointer_cast<SpecificInteger>(intop->width); 00243 ASSERT( width )( "Integral size ")(*(intop->width))(" is not specific, cannot decide result type"); 00244 00245 if( dynamic_pointer_cast<Signed>(optypes[i]) ) 00246 { 00247 if( *width >= *maxwidth_signed ) 00248 maxwidth_signed = width; 00249 } 00250 else if( dynamic_pointer_cast<Unsigned>(optypes[i]) ) 00251 { 00252 if( !maxwidth_unsigned || *width >= *maxwidth_unsigned ) 00253 maxwidth_unsigned = width; 00254 } 00255 else 00256 ASSERT( 0 )(*intop)(" is not Signed or Unsigned, please add to TypeOf class"); 00257 } 00258 00259 if( maxwidth_float ) 00260 { 00261 TreePtr<Floating> result; 00262 result->semantics = TreePtr<SpecificFloatSemantics>( new SpecificFloatSemantics(*maxwidth_float) ); 00263 return result; 00264 } 00265 00266 // Build the required integral result type 00267 TreePtr<Integral> result; 00268 if( maxwidth_unsigned && *maxwidth_unsigned >= *maxwidth_signed ) 00269 { 00270 result = TreePtr<Integral>( new Unsigned ); 00271 result->width = maxwidth_unsigned; 00272 } 00273 else 00274 { 00275 result = TreePtr<Integral>( new Signed ); 00276 result->width = maxwidth_signed; 00277 } 00278 return result; 00279 } 00280 00281 00282 TreePtr<Type> TypeOf::GetSpecial( TreePtr<Operator> op, Sequence<Type> &optypes ) 00283 { 00284 if( dynamic_pointer_cast<Dereference>(op) || dynamic_pointer_cast<Subscript>(op) ) 00285 { 00286 if( TreePtr<Pointer> o2 = dynamic_pointer_cast<Pointer>( optypes[0] ) ) 00287 return o2->destination; 00288 else if( TreePtr<Array> o2 = dynamic_pointer_cast<Array>( optypes[0] ) ) 00289 return o2->element; 00290 else 00291 ASSERTFAIL( "dereferencing non-pointer" ); 00292 } 00293 else if( dynamic_pointer_cast<AddressOf>(op) ) 00294 { 00295 TreePtr<Pointer> p( new Pointer ); 00296 p->destination = optypes[0]; 00297 return p; 00298 } 00299 else if( dynamic_pointer_cast<Comma>(op) ) 00300 { 00301 ASSERT( optypes.size() == 2 ); 00302 return optypes[1]; 00303 } 00304 else if( dynamic_pointer_cast<Multiplexor>(op) ) 00305 { 00306 return optypes[1]; // TODO do this properly, consider cond ? NULL : &x 00307 } 00308 else if( dynamic_pointer_cast<This>(op) ) 00309 { 00310 ASSERTFAIL(""); // TODO 00311 } 00312 else 00313 { 00314 ASSERT(0)("Unknown SPECIAL operator ")(*op)(", please add to TypeOf class"); 00315 ASSERTFAIL(""); 00316 } 00317 } 00318 00319 TreePtr<Type> TypeOf::GetLiteral( TreePtr<Literal> l ) 00320 { 00321 if( TreePtr<SpecificInteger> si = dynamic_pointer_cast<SpecificInteger>(l) ) 00322 { 00323 // Get the info from Clang, and make an Inferno type for it 00324 TreePtr<Integral> it; 00325 if( si->isSigned() ) 00326 it = MakeTreePtr<Signed>(); 00327 else 00328 it = MakeTreePtr<Unsigned>(); 00329 it->width = TreePtr<SpecificInteger>( new SpecificInteger( si->getBitWidth() ) ); 00330 return it; 00331 } 00332 else if( TreePtr<SpecificFloat> sf = dynamic_pointer_cast<SpecificFloat>(l) ) 00333 { 00334 // Get the info from Clang, and make an Inferno type for it 00335 MakeTreePtr<Floating> ft; 00336 ft->semantics = TreePtr<SpecificFloatSemantics>( new SpecificFloatSemantics(&sf->getSemantics()) ); 00337 return ft; 00338 } 00339 else if( dynamic_pointer_cast<Bool>(l) ) 00340 { 00341 return MakeTreePtr<Boolean>(); 00342 } 00343 else if( dynamic_pointer_cast<String>(l) ) 00344 { 00345 TreePtr<Integral> n; 00346 if( TypeDb::char_default_signed ) 00347 n = MakeTreePtr<Signed>(); 00348 else 00349 n = MakeTreePtr<Unsigned>(); 00350 TreePtr<SpecificInteger> sz( new SpecificInteger(TypeDb::char_bits) ); 00351 n->width = sz; 00352 MakeTreePtr<Pointer> p; 00353 p->destination = n; 00354 return p; 00355 } 00356 else 00357 { 00358 ASSERT(0)("Unknown literal ")(*l)(", please add to TypeOf class"); 00359 ASSERTFAIL(""); 00360 } 00361 } 00362 00363 00364 // Is this call really a constructor call? If so return the object being 00365 // constructed. Otherwise, return NULL 00366 TreePtr<Expression> TypeOf::IsConstructorCall( TreePtr<Node> c, TreePtr<Call> call ) 00367 { 00368 context = c; 00369 TreePtr<Expression> e; 00370 00371 if( TreePtr<Lookup> lf = dynamic_pointer_cast<Lookup>(call->callee) ) 00372 { 00373 ASSERT(lf->member); 00374 if( dynamic_pointer_cast<Constructor>( Get( lf->member ) ) ) 00375 e = lf->base; 00376 } 00377 00378 context = TreePtr<Node>(); 00379 return e; 00380 } 00381 00382 TypeOf TypeOf::instance; 00383