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  

instruction.cc

Go to the documentation of this file.
00001 // $Id: instruction.cc,v 1.13 2003/08/11 17:38:51 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2002 University of Texas at Austin
00008 // 
00009 //  Chuck Tsen
00010 //  Charles Nevill
00011 //  Paul Arthur Navratil
00012 //  Calvin Lin
00013 // 
00014 //  Permission is hereby granted, free of charge, to any person
00015 //  obtaining a copy of this software and associated documentation
00016 //  files (the "Software"), to deal in the Software without
00017 //  restriction, including without limitation the rights to use, copy,
00018 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00019 //  of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //  
00022 //  The above copyright notice and this permission notice shall be
00023 //  included in all copies or substantial portions of the Software.
00024 //  
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00026 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00027 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00028 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00029 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00030 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00031 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00032 //  THE SOFTWARE.
00033 //
00034 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00035 //  Computer Science for inspiring parts of the C-Breeze design.
00036 //
00037 // ----------------------------------------------------------------------
00038 
00039 #include "c_breeze.h"
00040 #include "instruction.h"
00041 #include "lirutil.h"
00042 #include <stdarg.h>
00043 
00044 LirInst::LirInst () :
00045   instruction(mn_undefined),
00046   primaryType(NULL),
00047   convertType(NULL),
00048   targetInst(NULL),
00049   visited(false),
00050   opnd1_contents(NULL),
00051   opnd2_contents(NULL),
00052   dest_contents(NULL),
00053   memBase_contents(NULL),
00054   memOffset_contents(NULL),
00055   nodeExtra(NULL),
00056   block(NULL)
00057 {}
00058 
00059 LirInst::LirInst (mnemonic inst) :
00060   instruction(inst),
00061   primaryType(NULL),
00062   convertType(NULL),
00063   targetInst(NULL),
00064   visited(false),
00065   opnd1_contents(NULL),
00066   opnd2_contents(NULL),
00067   dest_contents(NULL),
00068   memBase_contents(NULL),
00069   memOffset_contents(NULL),
00070   nodeExtra(NULL),
00071   block(NULL)
00072 {}
00073 
00074 //-------------------------------------------------------
00075 
00076 // stringize an instruction
00077 string
00078 LirInst::to_string () const
00079 {
00080   InstructionInfo info = instruction_info[instruction];
00081 
00082   // make pretty format string for this thing
00083   string pretty (info._opndFormat);
00084   cbz_util::string_replace (pretty, "$dest", contents_str (dest_contents));
00085   cbz_util::string_replace (pretty, "$opnd1", contents_str (opnd1_contents));
00086   cbz_util::string_replace (pretty, "$opnd2",
00087                             opnd2._is_const ? opnd2.
00088                             to_string (false) :
00089                             contents_str (opnd2_contents));
00090   cbz_util::string_replace (pretty, "$base", contents_str (memBase_contents));
00091   cbz_util::string_replace (pretty, "$offset",
00092                             memOffset._is_const ? memOffset.
00093                             to_string (false) :
00094                             contents_str (memOffset_contents));
00095   cbz_util::string_replace (pretty, "$target", target);
00096   cbz_util::string_replace (pretty, "$ptype",
00097                             LirUtil::getTypeString (primaryType));
00098   cbz_util::string_replace (pretty, "$ctype",
00099                             LirUtil::getTypeString (convertType));
00100 
00101   // make ugly format string for this thing
00102   string ugly (info._opndFormat);
00103   cbz_util::string_replace (ugly, "$dest", dest.to_string ());
00104   cbz_util::string_replace (ugly, "$opnd1", opnd1.to_string ());
00105   cbz_util::string_replace (ugly, "$opnd2", opnd2.to_string (false));
00106   cbz_util::string_replace (ugly, "$base", memBase.to_string ());
00107   cbz_util::string_replace (ugly, "$offset", memOffset.to_string (false));
00108   cbz_util::string_replace (ugly, "$target", target);
00109   cbz_util::string_replace (ugly, "$ptype",
00110                             LirUtil::getTypeString (primaryType));
00111   cbz_util::string_replace (ugly, "$ctype",
00112                             LirUtil::getTypeString (convertType));
00113 
00114   // make the full string
00115   return cbz_util::string_format ("%-14s : %s", info._name,
00116                                   /* pretty.c_str(), */ ugly.c_str ());
00117 }
00118 
00119 int
00120   LirInst::contents_compiler_temp_index =
00121   1;
00122 
00123 string
00124 LirInst::contents_str (declNode * pDecl)
00125 {
00126   // any contents?
00127   if (!pDecl)
00128     return "??";
00129 
00130   // special?
00131   if (pDecl == DATA_CONTENTS_STACKP)
00132     return "sp";
00133   else if (pDecl == DATA_CONTENTS_FRAMEP)
00134     return "fp";
00135   else if (pDecl == DATA_CONTENTS_REG_IN)
00136     return "in";
00137   else if (pDecl == DATA_CONTENTS_REG_OUT)
00138     return "out";
00139   else if (pDecl == DATA_CONTENTS_RETVAL)
00140     return "retval";
00141 
00142   // get its name
00143   return pDecl->name ();
00144 }
00145 
00146 // handy print operator for LirInst
00147 ostream & operator << (ostream & os, const LirInst & inst)
00148 {
00149   // just stringize it
00150   os << inst.to_string ();
00151   return os;
00152 }
00153 
00154 bool
00155 LirInst::has_dest (bool declDefines) const
00156 {
00157   // does it think it has a destination?
00158   if (instruction_info[instruction]._hasDest)
00159     {
00160       // make sure it has a real destination
00161       return dest.isValid ();
00162     }
00163 
00164   // is it a decl that lives in a register?
00165   if (declDefines && instruction == mn_DeclLocal &&
00166       ((declNode *) nodeExtra)->storage_location ()._type ==
00167       declNode::Storage_location::storageloc_register)
00168     return true;
00169 
00170   return false;
00171 }
00172 
00173 bool
00174 LirInst::has_opnd1 () const
00175 {
00176   return instruction_info[instruction]._hasOpnd1;
00177 }
00178 
00179 bool
00180 LirInst::has_opnd2 (bool regOnly) const
00181 {
00182   return (instruction_info[instruction]._hasOpnd2
00183           && (!regOnly || !opnd2._is_const));
00184 }
00185 
00186 bool
00187 LirInst::has_base () const
00188 {
00189   return instruction_info[instruction]._hasBase;
00190 }
00191 
00192 bool
00193 LirInst::has_offset (bool regOnly) const
00194 {
00195   return (instruction_info[instruction]._hasOffset
00196           && (!regOnly || !memOffset._is_const));
00197 }
00198 
00199 bool
00200 LirInst::has_target () const
00201 {
00202   return instruction_info[instruction]._hasTarget;
00203 }
00204 
00205 bool
00206 LirInst::should_emit () const
00207 {
00208   return instruction_info[instruction]._shouldEmit;
00209 }
00210 
00211 Register
00212 LirInst::get_dest ()
00213 {
00214   // do we have a real destination?
00215   if (dest.isValid ())
00216     return dest;
00217 
00218   // are we a decl that lives in a register? if so we will pretend this
00219   // instruction
00220   // defines that register so that we are sure to have at least one
00221   // definition of it.
00222   if (instruction == mn_DeclLocal
00223       && ((declNode *) nodeExtra)->storage_location ()._type ==
00224       declNode::Storage_location::storageloc_register)
00225     return ((declNode *) nodeExtra)->storage_location ()._register;
00226 
00227   // return junk register
00228   return Register ();
00229 }
00230 
00231 // instruction information
00232 InstructionInfo instruction_info[mn__count];
00233 
00234 // handy thingy that sets up instruction info
00235 struct InstructionInfo_Setup
00236 {
00237   InstructionInfo_Setup ()
00238   {
00239 #define INST( mnemonic, format, hd, ho1, ho2, hb, hof, ht, emit ) \
00240   instruction_info[ mn_##mnemonic ] = \
00241     InstructionInfo( #mnemonic, format, hd, ho1, ho2, hb, hof, ht, emit );
00242 
00243 /* mnemonic format-string dest opnd1 opnd2 base offset target emit */
00244     INST (NOP, "", false, false, false, false, false, false, true);
00245     INST (ConvertType, "$dest {$ctype} <- $opnd1 {$ptype}", true, true, false,
00246           false, false, false, true);
00247     INST (Load, "$dest <- $base[$offset]", true, false, false, true, true, 
00248           false, true);
00249     INST (LoadImmediate, "$dest <- $opnd2", true, false, true, false, false,
00250           false, true);
00251     INST (LoadStatic, "$dest <- $target[$offset]", true, false, false, false,
00252           true, false, true);
00253     INST (Store, "$base[$offset] <- $opnd1", false, true, false, true, true,
00254           false, true);
00255     INST (StoreStatic, "$target[$offset] <- $opnd1", false, true, false, false,
00256           true, true, true);
00257     INST (GetEffectiveAddr, "$dest <- addr($base[$offset])", true, false,
00258           false, true, true, false, true);
00259     INST (GetGlobalAddr, "$dest <- addr($target[$offset])", true, false, false,
00260           false, true, true, true);
00261     INST (Move, "$dest <- $opnd1", true, true, false, false, false, false,
00262           true);
00263     INST (Add, "$dest <- ($opnd1 + $opnd2)", true, true, true, false, false,
00264           false, true);
00265     INST (Sub, "$dest <- ($opnd1 - $opnd2)", true, true, true, false, false,
00266           false, true);
00267     INST (Mul, "$dest <- ($opnd1 * $opnd2)", true, true, true, false, false, 
00268           false, true);
00269     INST (Div, "$dest <- ($opnd1 / $opnd2)", true, true, true, false, false,
00270           false, true);
00271     INST (Mod, "$dest <- ($opnd1 $ $opnd2)", true, true, true, false, false,
00272           false, true);
00273     INST (Neg, "$dest <- (-1 * $opnd1)", true, true, false, false, false, 
00274           false, true);
00275     INST (BitwiseOR, "$dest <- ($opnd1 | $opnd2)", true, true, true, false, 
00276           false, false, true);
00277     INST (BitwiseAND, "$dest <- ($opnd1 & $opnd2)", true, true, true, false, 
00278           false, false, true);
00279     INST (BitwiseXOR, "$dest <- ($opnd1 ^ $opnd2)", true, true, true, false,
00280           false, false, true);
00281     INST (BitwiseNOT, "$dest <- (! $opnd1)", true, true, false, false, false, 
00282           false, true);
00283     INST (BitwiseShiftLeft, "$dest <- ($opnd1 << $opnd2)", true, true, true, 
00284           false, false, false, true);
00285     INST (BitwiseShiftRight, "$dest <- ($opnd1 >> $opnd2)", true, true, true, 
00286           false, false, false, true);
00287     INST (BitwiseRotateRight, "$dest <- (<$opnd1 << $opnd2>)", true, true,
00288           true, false, false, false, true);
00289     INST (BitwiseRotateLeft, "$dest <- (<$opnd1 >> $opnd2>)", true, true, 
00290           true, false, false, false, true);
00291     INST (Compare, "cmp $opnd1 $opnd2", false, true, true, false, false, false,
00292           true);
00293     INST (BranchEQ, "(op1 == op2) ? $target", false, false, false, false,
00294           false, true, true);
00295     INST (BranchNE, "(op1 != op2) ? $target", false, false, false, false, 
00296           false, true, true);
00297     INST (BranchLT, "(op1 <  op2) ? $target", false, false, false, false,
00298           false, true, true);
00299     INST (BranchLE, "(op1 <= op2) ? $target", false, false, false, false,
00300           false, true, true);
00301     INST (BranchGT, "(op1 >  op2) ? $target", false, false, false, false,
00302           false, true, true);
00303     INST (BranchGE, "(op1 >= op2) ? $target", false, false, false, false, 
00304           false, true, true);
00305     INST (Jmp, "goto $target:", false, false, false, false, false, true, true);
00306     INST (Label, "$target:", false, false, false, false, false, true, true);
00307     INST (Call, "call '$target'", true, false, false, false, false, true,
00308           true);
00309 
00310     // TODO: INST (IndirectCall
00311 
00312     INST (Return, "ret", false, false, false, false, false, false, true);
00313     INST (CallPre, ".precall", false, false, false, false, false, false, 
00314           false);
00315     INST (BeginProc, ".begin $target", false, false, false, false, false, 
00316           false, true);
00317     INST (EndProc, ".end $target", false, false, false, false, false, false,
00318           true);
00319     INST (BeginUnit, ".beginunit", false, false, false, false, false, false,
00320           true);
00321     INST (EndUnit, ".endunit", false, false, false, false, false, false, true);
00322     INST (StaticDataString, ".data string", false, false, false, false, false,
00323           false, true);
00324     INST (StaticDataLong, ".data long", false, false, false, false, false,
00325           false, true);
00326     INST (StaticDataInt, ".data int", false, false, false, false, false,
00327           false, true);
00328     INST (StaticDataShort, ".data short", false, false, false, false, false,
00329           false, true);
00330     INST (StaticDataChar, ".data char", false, false, false, false, false,
00331           false, true);
00332     INST (StaticDataSingle, ".data single", false, false, false, false, false,
00333           false, true);
00334     INST (StaticDataDouble, ".data double", false, false, false, false, false,
00335           false, true);
00336     INST (StaticDataZero, ".data zero", false, false, false, false, false,
00337           false, true);
00338     INST (StaticDataUninit, ".data uninit", false, false, false, false, false,
00339           false, true);
00340     INST (DeclLocal, "var $target", false, false, false, false, false, false, 
00341           false);
00342     INST (DeclGlobal, "global $target", false, false, false, false, false,
00343           false, true);
00344 #undef INST
00345   }
00346 };
00347 
00348 // instantiate one of these at global scope so instruction info will get setup
00349 InstructionInfo_Setup setup;
00350 
00351 const instruction_list &
00352 LirBlock::insts () const
00353 {
00354   return _instructions;
00355 }
00356 
00357 void
00358 LirBlock::add_inst_before (LirInst * newInst, LirInst * otherInst)
00359 {
00360   // fix blocks
00361   assert (otherInst->block == this);
00362   newInst->block = this;
00363 
00364   // find the one we're putting it before
00365   instruction_list_p it;
00366   for (it = _instructions.begin (); it != _instructions.end (); ++it)
00367     if (*it == otherInst)
00368       {
00369         _instructions.insert (it, newInst);
00370         return;
00371       }
00372 
00373   // if we get here we did not find otherInst in our list - that is bad
00374   assert (false);
00375 }
00376 
00377 void
00378 LirBlock::add_inst_after (LirInst * newInst, LirInst * otherInst)
00379 {
00380   // fix blocks
00381   assert (otherInst->block == this);
00382   newInst->block = this;
00383 
00384   // find the one we're putting it after
00385   instruction_list_p it;
00386   for (it = _instructions.begin (); it != _instructions.end (); ++it)
00387     if (*it == otherInst)
00388       {
00389         _instructions.insert (++it, newInst);
00390         return;
00391       }
00392 
00393   // if we get here we did not find otherInst in our list - that is bad
00394   assert (false);
00395 }
00396 
00397 void
00398 LirBlock::add_inst (LirInst * inst)
00399 {
00400   // add to end of list
00401   inst->block = this;
00402   _instructions.push_back (inst);
00403 }
00404 
00405 void
00406 LirBlock::remove_inst (LirInst * inst)
00407 {
00408   // sanity check
00409   assert (inst->block == this);
00410 
00411   // find it and remove it
00412   inst->block = NULL;
00413   instruction_list_p it = _instructions.begin ();
00414   for (; it != _instructions.end (); ++it)
00415     if (*it == inst)
00416       {
00417         _instructions.erase (it);
00418         return;
00419       }
00420 }
00421 
00422 void
00423 LirBlock::reset_visited ()
00424 {
00425   // to avoid infinite recursion
00426   if (!_visited)
00427     return;
00428 
00429   // reset our flag
00430   _visited = false;
00431 
00432   // reset all successors
00433   LirBlockSet_p it;
00434   for (it = _succs.begin (); it != _succs.end (); ++it)
00435     (*it)->reset_visited ();
00436 }

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