Inferno  0.2
typeof.cpp
Go to the documentation of this file.
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