C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

basic_type.cc

Go to the documentation of this file.
00001 // $Id: basic_type.cc,v 1.5 2003/08/07 23:12:58 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 
00040 // ------------------------------------------------------------
00041 // Constant values
00042 // ------------------------------------------------------------
00043 
00044 // -- PRIVATE: Global values for basic type fields...
00045 
00046 // -- Basic types
00047 const unsigned int basic_type::NO_TYPE  = 0x0;
00048 const unsigned int basic_type::INT      = 0x1;
00049 const unsigned int basic_type::CHAR     = 0x2;
00050 const unsigned int basic_type::FLOAT    = 0x3;
00051 const unsigned int basic_type::VOID     = 0x4;
00052 const unsigned int basic_type::ELLIPSIS = 0x5;
00053 
00054 // -- Length
00055 const unsigned int basic_type::NO_LENGTH = 0x0;
00056 const unsigned int basic_type::SHORT     = 0x1;
00057 const unsigned int basic_type::LONG      = 0x2;
00058 const unsigned int basic_type::LONGLONG  = 0x3;
00059 
00060 // -- Sign
00061 
00062 const unsigned int basic_type::NO_SIGN  = 0x0;
00063 const unsigned int basic_type::SIGNED   = 0x1;
00064 const unsigned int basic_type::UNSIGNED = 0x2;
00065 
00066 // -- Used in parsing only
00067 const unsigned int basic_type::PARSE_ONLY = 0x1;
00068 
00069 // --- PRIVATE: Global values for basic type size and alignment...
00070 
00071 // -- target limits
00072 
00073 const unsigned int basic_type::TARGET_MAX_UCHAR = 256;
00074 const unsigned int basic_type::TARGET_MAX_INT   = INT_MAX;
00075 const unsigned int basic_type::TARGET_MAX_UINT  = UINT_MAX;
00076 const unsigned int basic_type::TARGET_MAX_LONG  = LONG_MAX;
00077 const unsigned int basic_type::TARGET_MAX_ULONG = ULONG_MAX;
00078 
00079 //-- Basic sizes and alignments */
00080 
00081 const unsigned int basic_type::CHAR_SIZE =         sizeof(char);
00082 const unsigned int basic_type::CHAR_ALIGN =        CHAR_SIZE;
00083 
00084 const unsigned int basic_type::SHORT_SIZE =        sizeof(short);
00085 const unsigned int basic_type::SHORT_ALIGN =       SHORT_SIZE;
00086 
00087 const unsigned int basic_type::INT_SIZE =          sizeof(int);
00088 const unsigned int basic_type::INT_ALIGN =         INT_SIZE;
00089 
00090 const unsigned int basic_type::FLOAT_SIZE =        sizeof(float);
00091 const unsigned int basic_type::FLOAT_ALIGN =       FLOAT_SIZE;
00092 
00093 const unsigned int basic_type::DOUBLE_SIZE =       sizeof(double);
00094 const unsigned int basic_type::DOUBLE_ALIGN =      DOUBLE_SIZE;
00095 
00096 const unsigned int basic_type::LONGDOUBLE_SIZE =   sizeof(long double);
00097 const unsigned int basic_type::LONGDOUBLE_ALIGN =  LONGDOUBLE_SIZE;
00098 
00099 const unsigned int basic_type::LONG_SIZE =         sizeof(long);
00100 const unsigned int basic_type::LONG_ALIGN =        LONG_SIZE;
00101 
00102 /*
00103 const unsigned int basic_type::LONGLONG_SIZE =     sizeof(long long);
00104 const unsigned int basic_type::LONGLONG_ALIGN =    LONGLONG_SIZE;
00105 */
00106 
00107 const unsigned int basic_type::POINTER_SIZE =      sizeof(void *);
00108 const unsigned int basic_type::POINTER_ALIGN =     POINTER_SIZE;
00109 
00110 const unsigned int basic_type::BYTE_LENGTH =   CHAR_BIT;
00111 const unsigned int basic_type::WORD_LENGTH =   (INT_SIZE * BYTE_LENGTH);
00112 
00113 // ------------------------------------------------------------
00114 // Initialize global basic types
00115 // ------------------------------------------------------------
00116 
00117 // -- Now the types...
00118 
00119 const basic_type basic_type::Void(0,0,basic_type::VOID);
00120 const basic_type basic_type::Ellipsis(0,0,basic_type::ELLIPSIS);
00121 
00122 const basic_type basic_type::SChar(basic_type::SIGNED, 0, basic_type::CHAR);
00123 const basic_type basic_type::UChar(basic_type::UNSIGNED, 0, basic_type::CHAR);
00124 
00125 const basic_type basic_type::SShort(basic_type::SIGNED, basic_type::SHORT, basic_type::INT);
00126 const basic_type basic_type::UShort(basic_type::UNSIGNED, basic_type::SHORT, basic_type::INT);
00127 
00128 const basic_type basic_type::SInt(basic_type::SIGNED, 0, basic_type::INT);
00129 const basic_type basic_type::UInt(basic_type::UNSIGNED, 0, basic_type::INT);
00130 
00131 const basic_type basic_type::SLong(basic_type::SIGNED, basic_type::LONG, basic_type::INT);
00132 const basic_type basic_type::ULong(basic_type::UNSIGNED, basic_type::LONG, basic_type::INT);
00133 
00134 const basic_type basic_type::SLongLong(basic_type::SIGNED, basic_type::LONGLONG, basic_type::INT);
00135 const basic_type basic_type::ULongLong(basic_type::UNSIGNED, basic_type::LONGLONG, basic_type::INT);
00136 const basic_type basic_type::Float(0, 0, basic_type::FLOAT);
00137 const basic_type basic_type::Double(0, basic_type::LONG, basic_type::FLOAT);
00138 const basic_type basic_type::LongDouble(0, basic_type::LONGLONG, basic_type::FLOAT);
00139 
00140 // -- These are only used in the parser...
00141 
00142 const basic_type basic_type::Char(0,0,basic_type::CHAR);
00143 const basic_type basic_type::Int(0, 0, basic_type::INT);
00144 
00145 const basic_type basic_type::Signed(basic_type::SIGNED, 0,0);
00146 const basic_type basic_type::Unsigned(basic_type::UNSIGNED, 0,0);
00147 
00148 const basic_type basic_type::Short(0,basic_type::SHORT,0);
00149 const basic_type basic_type::Long(0,basic_type::LONG,0);
00150 
00151 const basic_type basic_type::IntParseOnly(0,0,basic_type::INT, true);
00152 
00153 // ------------------------------------------------------------
00154 // MergePrimTypes from type.c
00155 // (the "other" object is deleted
00156 // ------------------------------------------------------------
00157 
00158 void basic_type::merge_in(basic_type & bt2, Coord coord)
00159 {
00160   basic_type & bt1 = * this;;
00161 
00162   // First merge base type (int, char, float, double, ...).
00163   // At most one base type may be specified. 
00164 
00165   if (! bt1.is_no_type() && ! bt2.is_no_type()) 
00166     CBZ::SyntaxError(coord,
00167                      string("conflicting type specifiers: `") + bt1.base_name() +
00168                      string("' and `") + bt2.base_name() + string("'"));
00169   else
00170     bt1._base_type += bt2._base_type;
00171 
00172   // Now merge signs.  At most one sign may be specified; it appears to
00173   // be legal in ANSI to repeat the same sign (as in 
00174   // "unsigned unsigned int"), but a warning is generated.
00175 
00176   if (! bt1.is_no_sign() && ! bt2.is_no_sign())
00177     if (bt1.sign() != bt2.sign())
00178       CBZ::SyntaxError(coord,
00179                        string("conflicting type specifiers: `") + bt1.sign_name() +
00180                        string("' and `") + bt2.sign_name() + string("'"));
00181     else
00182       CBZ::Warning(3, coord,
00183                    string("repeated type specifier: `") + bt1.sign_name() + string("'"));
00184   else
00185     bt1._sign += bt2._sign;
00186     
00187   // Check that the resulting sign is compatible with the resulting
00188   // base type.
00189   // Only int and char may have a sign specifier.
00190 
00191   if (! bt1.is_no_sign() && ! bt1.is_no_type())
00192     if ( ! bt1.is_int() && ! bt1.is_char()) {
00193       CBZ::SyntaxError(coord,
00194                        string("conflicting type specifiers: `") + bt1.base_name() +
00195                        string("' and `") + bt1.sign_name() + string("'"));
00196       bt1.set_no_sign();
00197     }
00198 
00199   // Merge lengths (short, long, long long).
00200 
00201   if ( ! bt1.is_no_length() && ! bt2.is_no_length()) {
00202     if (bt1.is_long() && bt2.is_long() && ! CBZ::ANSIOnly)
00203       bt1.set_longlong();
00204     else
00205       CBZ::SyntaxError(coord,
00206                        string("conflicting type specifiers: `") + bt1.length_name() +
00207                        string("' and `") + bt2.length_name() + string("'"));
00208   } else
00209     bt1._length += bt2._length;
00210     
00211   // Check that the resulting length is compatible with the resulting
00212   // base type.
00213   // Only int may have any length specifier; double and float may have long.
00214 
00215   if ( ! bt1.is_no_length() && ! bt1.is_no_type())
00216     if ( ! bt1.is_int() 
00217                 && ! (bt1.is_float() && bt1.is_long()) 
00218                 && ! (bt1.is_float() && bt1.is_longlong()) ) {
00219         /* bug here ### */
00220       CBZ::SyntaxError(coord,
00221                        string("conflicting type specifiers: `") + bt1.base_name() +
00222                        string("' and `") + bt1.length_name() + string("'"));
00223       bt1.set_no_length();
00224     }
00225 }
00226 
00227 // ------------------------------------------------------------
00228 // Finish (FinishPrimType type.c)
00229 // ------------------------------------------------------------
00230 
00231 void basic_type::finish()
00232 {
00233   // -- If no type is specified, then it's an int
00234 
00235   if (parse_only() || is_no_type())
00236     set_int();
00237 
00238   // -- If no sign is specified, then it's signed
00239 
00240   if ((is_int() || is_char()) && is_no_sign())
00241     set_signed();
00242 }
00243 
00244 // ------------------------------------------------------------
00245 // Size and Alignment information
00246 // ------------------------------------------------------------
00247 
00248 int basic_type::size()
00249 {
00250   switch (base_type()) {
00251   case CHAR: return CHAR_SIZE;
00252 
00253   case INT:
00254     switch (length()) {
00255     case SHORT: return SHORT_SIZE;
00256     case LONG:  return LONG_SIZE;
00257 //    case LONGLONG: return LONGLONG_SIZE;
00258     default: return INT_SIZE;
00259     }
00260     break;
00261 
00262   case FLOAT:
00263     switch (length()) {
00264     case LONG: return DOUBLE_SIZE;
00265  //   case LONGLONG: return LONGDOUBLE_SIZE;
00266     default: return FLOAT_SIZE;
00267     }
00268     break;
00269 
00270   case VOID:
00271     CBZ::SyntaxError("Can't compute size of type void");
00272     break;
00273 
00274   default:
00275     CBZ::SyntaxError("Size received unknown primitive type");
00276     break;
00277   }
00278 
00279   return 0;
00280 }
00281 
00282 int basic_type::alignment()
00283 {
00284   switch (base_type()) {
00285   case CHAR: return CHAR_ALIGN;
00286 
00287   case INT:
00288     switch (length()) {
00289     case SHORT: return SHORT_ALIGN;
00290     case LONG:  return LONG_ALIGN;
00291 //    case LONGLONG: return LONGLONG_ALIGN;
00292     default: return INT_ALIGN;
00293     }
00294     break;
00295 
00296   case FLOAT:
00297     switch (length()) {
00298     case LONG: return DOUBLE_ALIGN;
00299     case LONGLONG: return LONGDOUBLE_ALIGN;
00300     default: return FLOAT_ALIGN;
00301     }
00302     break;
00303 
00304   case VOID:
00305     CBZ::SyntaxError("Can't compute alignment of type void");
00306     break;
00307 
00308   default:
00309     CBZ::SyntaxError("Align received unknown primitive type");
00310     break;
00311   }
00312 
00313   return 0;
00314 }
00315 
00316 // ------------------------------------------------------------
00317 // String representation
00318 // ------------------------------------------------------------
00319 
00320 string basic_type::base_name() const
00321 {
00322   switch (base_type()) {
00323   case VOID:     return string("void");
00324   case ELLIPSIS: return string("...");
00325   case FLOAT:
00326     if (length() == LONG || length() == LONGLONG)
00327                  return string("double");
00328     else
00329                  return string("float");
00330   case CHAR:     return string("char"); 
00331   case INT:      return string("int");
00332   default:
00333     return string("");
00334   }
00335 }
00336 
00337 string basic_type::length_name() const
00338 {
00339   if (base_type() == FLOAT)
00340     if (length() == LONGLONG)
00341       return string("long");
00342     else
00343       return string("");
00344 
00345   switch (length()) {
00346   case SHORT:     return string("short");
00347   case LONG:      return string("long");
00348   case LONGLONG:  return string("long long");
00349   default:
00350     return string("");
00351   }
00352 }
00353 
00354 string basic_type::sign_name() const
00355 {
00356   switch (sign()) {
00357   case UNSIGNED:  return string("unsigned");
00358     // case SIGNED:    return string("signed");
00359   default:
00360     return string("");
00361   }
00362 }
00363 
00364 string basic_type::to_string() const
00365 {
00366   unsigned int bt = base_type();
00367   unsigned int l = length();
00368   bool us = is_unsigned();
00369   bool not_empty = false;
00370 
00371   if (parse_only())
00372     return string("int");
00373 
00374   string bn = base_name();
00375   string ln = length_name();
00376   string sn = sign_name();
00377   string out;
00378 
00379   if (bt == FLOAT) {
00380     if (! ln.empty()) {
00381       out += ln;
00382       not_empty = true;
00383     }
00384 
00385     if (! bn.empty()) {
00386       if (not_empty)
00387         out += " ";
00388       out += bn;
00389       not_empty = true;
00390     }
00391   }
00392 
00393   if ((bt == VOID) || (bt == ELLIPSIS))
00394     out += bn;
00395 
00396   if ((bt == CHAR) || (bt == INT)) {
00397     if (! sn.empty()) {
00398       if (not_empty)
00399         out += " ";
00400       out += sn;
00401       not_empty = true;
00402     }
00403 
00404     if (! ln.empty()) {
00405       if (not_empty)
00406         out += " ";
00407       out += ln;
00408       not_empty = true;
00409     }
00410 
00411     if (! bn.empty()) {
00412       if (not_empty)
00413         out += " ";
00414       out += bn;
00415       not_empty = true;
00416     }
00417   }
00418 
00419   return out;
00420 }
00421 
00422 int basic_type::to_num() const
00423 {
00424   int val = 0;
00425 
00426   val |= _base_type;
00427 
00428   val = val << 3; // Number of bits in the base type
00429 
00430   val |= _length;
00431 
00432   val = val << 2; // Number of bits in the length
00433 
00434   val |= _sign;
00435 
00436   val = val << 2; // Number of bits in the sign
00437 
00438   // -- Skip parse-only
00439 
00440   return val;
00441 }

Generated on August 27, 2003
Back to the C-Breeze home page