00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00077 string
00078 LirInst::to_string () const
00079 {
00080 InstructionInfo info = instruction_info[instruction];
00081
00082
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
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
00115 return cbz_util::string_format ("%-14s : %s", info._name,
00116 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
00127 if (!pDecl)
00128 return "??";
00129
00130
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
00143 return pDecl->name ();
00144 }
00145
00146
00147 ostream & operator << (ostream & os, const LirInst & inst)
00148 {
00149
00150 os << inst.to_string ();
00151 return os;
00152 }
00153
00154 bool
00155 LirInst::has_dest (bool declDefines) const
00156 {
00157
00158 if (instruction_info[instruction]._hasDest)
00159 {
00160
00161 return dest.isValid ();
00162 }
00163
00164
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
00215 if (dest.isValid ())
00216 return dest;
00217
00218
00219
00220
00221
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
00228 return Register ();
00229 }
00230
00231
00232 InstructionInfo instruction_info[mn__count];
00233
00234
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
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
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
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
00361 assert (otherInst->block == this);
00362 newInst->block = this;
00363
00364
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
00374 assert (false);
00375 }
00376
00377 void
00378 LirBlock::add_inst_after (LirInst * newInst, LirInst * otherInst)
00379 {
00380
00381 assert (otherInst->block == this);
00382 newInst->block = this;
00383
00384
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
00394 assert (false);
00395 }
00396
00397 void
00398 LirBlock::add_inst (LirInst * inst)
00399 {
00400
00401 inst->block = this;
00402 _instructions.push_back (inst);
00403 }
00404
00405 void
00406 LirBlock::remove_inst (LirInst * inst)
00407 {
00408
00409 assert (inst->block == this);
00410
00411
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
00426 if (!_visited)
00427 return;
00428
00429
00430 _visited = false;
00431
00432
00433 LirBlockSet_p it;
00434 for (it = _succs.begin (); it != _succs.end (); ++it)
00435 (*it)->reset_visited ();
00436 }