|
||
instruction.hGo to the documentation of this file.00001 // $Id: instruction.h,v 1.12 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 #ifndef __INSTRUCTION_H__ 00040 #define __INSTRUCTION_H__ 00041 00042 #include <c_breeze.h> 00043 #include "register.h" 00044 00045 // pseudo-RISC instruction mnemonics 00046 enum mnemonic 00047 { 00048 mn_undefined = 0, 00049 00050 /* data manipulation instructions */ 00051 00052 mn_ConvertType, // convert the contents of $opnd1 from $ptype 00053 // to $ctype and place result in $dest 00054 mn_Load, // read a value from memory ($base+$offset) 00055 // into $dest register 00056 mn_LoadImmediate, // read immediate value $opnd2 into $dest 00057 // register 00058 mn_LoadStatic, // loads the compile-time static data with 00059 // label $target into register $dest 00060 mn_Store, // store the value from $opnd1 to memory 00061 // ($base+$offset) 00062 mn_StoreStatic, // store the value from $opnd1 to memory 00063 // ($target + $offset) 00064 mn_GetEffectiveAddr, // compute effective address of 00065 // ($base+$offset) and store in $dest 00066 mn_GetGlobalAddr, // compute effective address of global @ 00067 // ($target + $offset) and store in $dest 00068 mn_Move, // move register $opnd1 into register $dest 00069 // (used for loading things like string constants or floating-point values) 00070 00071 /* arithmetic instructions */ 00072 00073 mn_Add, // store ($opnd1 + $opnd2) in $dest 00074 mn_Sub, // store ($opnd1 - $opnd2) in $dest 00075 mn_Mul, // store ($opnd1 * $opnd2) in $dest 00076 mn_Div, // store ($opnd1 / $opnd2) in $dest 00077 mn_Mod, // store ($opnd1 % $opnd2) in $dest 00078 mn_Neg, // store (-1 * $opnd1) in $dest 00079 00080 /* bitwise manipulation instructions */ 00081 00082 mn_BitwiseOR, // store ($opnd1 | $opnd2) in $dest 00083 mn_BitwiseAND, // store ($opnd1 & $opnd2) in $dest 00084 mn_BitwiseXOR, // store ($opnd1 ^ $opnd2) in $dest 00085 mn_BitwiseNOT, // store (! $opnd1) in $dest 00086 mn_BitwiseShiftLeft, // store ($opnd1 << $opnd2) in $dest 00087 mn_BitwiseShiftRight, // store ($opnd1 >> $opnd2) in $dest 00088 mn_BitwiseRotateRight, // store ($opnd1 rotated left by $opnd2 bits) 00089 // in $dest 00090 mn_BitwiseRotateLeft, // store ($opnd1 rotated right by $opnd2 00091 // bits) in $dest 00092 00093 /* flow control instructions */ 00094 // 00095 // NOTE: It is guaranteed that all conditional branch instructions will be 00096 // immediately preceded by a compare instruction. 00097 // 00098 00099 mn_Compare, // compare $opnd1, $opnd2, store result in 00100 // arch-specific manner 00101 mn_BranchEQ, // branch to $target if previous comparison 00102 // yielded == 00103 mn_BranchNE, // branch to $target if previous comparison 00104 // yielded != 00105 mn_BranchLT, // branch to $target if previous comparison 00106 // yielded < 00107 mn_BranchLE, // branch to $target if previous comparison 00108 // yielded <= 00109 mn_BranchGT, // branch to $target if previous comparison 00110 // yielded > 00111 mn_BranchGE, // branch to $target if previous comparison 00112 // yielded >= 00113 mn_Jmp, // branch to $target 00114 mn_Label, // declare label $target 00115 00116 /* procedure call stuff */ 00117 00118 mn_Call, // call function $target 00119 mn_IndirectCall, // call function $opnd1 00120 // (used for function ptrs) 00121 mn_Return, // return from procedure $target with stack 00122 // size $stacksize 00123 mn_CallPre, // for handling caller-save registers - 00124 // instruction inserted before call arguments 00125 // are setup 00126 00127 /* procedure control instructions */ 00128 // NOTE: architecture code template is responsible for setting up and 00129 // tearing down 00130 // the stack frame, including saving/restoring old stack and frame 00131 // pointers. stack 00132 // frame is usually setup by BeginProc and torn down by Return. 00133 00134 mn_BeginProc, // start of procedure named $target, with 00135 // stack size $stacksize. 00136 mn_EndProc, // end of procedure named $target 00137 00138 /* translation-unit control instructions */ 00139 00140 mn_BeginUnit, // beginning of translation unit 00141 mn_EndUnit, // end of translation unit 00142 00143 /* static data stuff */ 00144 // 00145 // for each of these things the template should emit the proper 00146 // macros for encoding the data, such as '.string' for strings and 00147 // '.long' for a 32-bit value. 00148 // 00149 // the template should not emit a label for the static data - this 00150 // will be handled automatically. 00151 // 00152 00153 mn_StaticDataString, // declaration of static string data $value 00154 // (formatted with no quotes) 00155 mn_StaticDataLong, // declaration of static long $value 00156 mn_StaticDataInt, // declaration of static int $value 00157 mn_StaticDataShort, // declaration of static short $value 00158 mn_StaticDataChar, // declaration of static char $value 00159 mn_StaticDataSingle, // declaration of static single precision 00160 // float $value 00161 mn_StaticDataDouble, // declaration of static double precision 00162 // float $value 00163 mn_StaticDataZero, // declaration of $size static bytes of zeroes 00164 mn_StaticDataUninit, // declaration of $size static bytes 00165 // uninitialized, at name $target 00166 00167 /* miscellaneous instructions */ 00168 00169 mn_DeclLocal, // declaration of block-local variable 00170 // $target (virtual instruction, not emitted) 00171 mn_DeclGlobal, // declaration of global variable 00172 // $target (virtual instruction, not emitted) 00173 mn_NOP, // empty operation 00174 00175 // placeholder - must always be last in enumeration 00176 mn__count 00177 }; 00178 00179 // information about instructions 00180 struct InstructionInfo 00181 { 00182 00183 InstructionInfo () 00184 { 00185 } 00186 InstructionInfo (const char *name, const char *opndFormat, bool hasDest, 00187 bool hasOp1, bool hasOp2, bool hasBase, bool hasOffset, 00188 bool hasTarget, bool shouldEmit):_name (name), 00189 _opndFormat (opndFormat), _hasDest (hasDest), _hasOpnd1 (hasOp1), 00190 _hasOpnd2 (hasOp2), _hasBase (hasBase), _hasOffset (hasOffset), 00191 _hasTarget (hasTarget), _shouldEmit (shouldEmit) 00192 { 00193 } 00194 00195 // friendly name 00196 const char *_name; 00197 00198 // operand format for pretty-printing an instruction 00199 // 00200 // format fields 00201 // 00202 // %dest - destination 00203 // %opnd1 - operand1 00204 // %opnd2 - operand2 00205 // %base - load-store base register 00206 // %offset - load-store offset register/constant 00207 // %target - branch target or label name (for Decl instruction, variable 00208 // name) 00209 // %ptype - primary data type (for type conversions, the source type) 00210 // %ctype - data type to convert to (used for type conversions) 00211 // 00212 const char *_opndFormat; 00213 00214 // whether or not the instruction has various things 00215 bool _hasDest; 00216 bool _hasOpnd1; 00217 bool _hasOpnd2; 00218 bool _hasBase; 00219 bool _hasOffset; 00220 bool _hasTarget; 00221 00222 // whether or not the instruction should be emitted 00223 bool _shouldEmit; 00224 }; 00225 00226 // information about all instructions - keyed by instruction mnemonic 00227 extern InstructionInfo instruction_info[mn__count]; 00228 00229 // types of comparisons this ennumeration will be set at binary nodes 00230 // if it is a conditional statement and it will be used when emitting 00231 // conditional and branch instructions 00232 enum Compare_type 00233 { 00234 cmp_unknown, 00235 cmp_GT, // cmp_greater cmp_than 00236 cmp_GE, // cmp_greater cmp_or cmp_equal 00237 cmp_LE, // cmp_less cmp_or cmp_equal 00238 cmp_LT, // cmp_less cmp_than 00239 cmp_EQ, // cmp_equal cmp_to 00240 cmp_NE // cmp_not cmp_equal cmp_to 00241 }; 00242 00243 00244 // Class LirInst contains all the useful information about an 00245 // instruction Here we specify the source registers, the destination 00246 // register, immediate values, mnuemonic for the instruction, symbolic 00247 // addresses (var_name), comparison type (for conditionals), and the 00248 // kind of instruction operands (Opnd_type) Most of these values are 00249 // set in LIR.cc If we find that the code generator contains 00250 // insufficient information about instructions or the machine-specific 00251 // instruction set, then we can eliminate ambiguity by adding fields 00252 // in this class. 00253 00254 class LirInst 00255 { 00256 // for base+offset instructions, if the base register is the stack or frame 00257 // pointer 00258 #define DATA_CONTENTS_STACKP ((declNode*)4) 00259 #define DATA_CONTENTS_FRAMEP ((declNode*)5) 00260 00261 // for operations involving arch-defined input/output regs 00262 #define DATA_CONTENTS_REG_IN ((declNode*)6) 00263 #define DATA_CONTENTS_REG_OUT ((declNode*)7) 00264 00265 // for function calls, the return value of the function 00266 #define DATA_CONTENTS_RETVAL ((declNode*)8) 00267 00268 // flag value 00269 #define DATA_CONTENTS__SPECIAL ((declNode*)10) 00270 00271 public: 00272 // instruction components 00273 00274 // operands (register or constant) 00275 Register opnd1; 00276 declNode *opnd1_contents; 00277 reg_or_const opnd2; 00278 declNode *opnd2_contents; 00279 00280 // destination register 00281 Register dest; 00282 declNode *dest_contents; 00283 00284 // base+offset registers for loads/stores 00285 Register memBase; 00286 declNode *memBase_contents; 00287 reg_or_const memOffset; 00288 declNode *memOffset_contents; 00289 00290 // instruction mnemonic 00291 mnemonic instruction; 00292 00293 // branch target, procedure name, variable name, or label name 00294 string target; 00295 00296 // contents for static variables 00297 // for strings, the string is formatted with no quotes 00298 // for binary, this is up to MAX_LIR_DATA_BYTES bytes, most significant 00299 // byte first 00300 /* string dataString; */ 00301 int dataSize; 00302 int dataAlign; 00303 constant dataValue; 00304 00305 // operand types 00306 typeNode * primaryType; // primary instruction datatype 00307 typeNode * convertType; // for conversions, destination datatype 00308 00309 public: 00310 // other handy stuff 00311 00312 // the basic block to which we belong 00313 LirBlock * block; 00314 00315 // for BeginProc, EndProc, and Return, the procNode of the current 00316 // procedure 00317 // for Call, the threeAddrNode of the function call 00318 // for DeclXxx, the declNode of the declaration 00319 // for LoadStatic, the declNode of the static variable 00320 Node *nodeExtra; 00321 00322 // for Call, indicates the number of bytes of stackspace used by arguments 00323 int _stack_arg_bytes; 00324 00325 // for jumps/branches, the target instruction (if branch taken) 00326 LirInst *targetInst; 00327 00328 // for dataflow problems that need to process all instructions, a visited 00329 // flag 00330 bool visited; 00331 00332 // for dataflow problems on per-instruction level, successors/predecessors 00333 // of each 00334 // instruction 00335 instruction_set succs; 00336 instruction_set preds; 00337 00338 public: 00339 // primary interface 00340 00341 // constructor/destructor 00342 LirInst (); 00343 LirInst (mnemonic instruction); 00344 00345 // for easier printing 00346 friend ostream & operator << (ostream & os, const LirInst & inst); 00347 00348 // stringize this thing 00349 string to_string () const; 00350 00351 // find out if this instruction should actually be included in assembly 00352 // generation 00353 bool should_emit () const; 00354 00355 // find out if this instruction type has various things 00356 // 00357 // declDefines - if true, declaration instructions for register 00358 // variables are considered to define that register. 00359 // 00360 // regOnly - if true, for components that can be a register or a 00361 // constant, return true only if the component is actually a 00362 // register. 00363 bool has_dest (bool declDefines = false) const; 00364 bool has_opnd1 () const; 00365 bool has_opnd2 (bool regOnly = true) const; 00366 bool has_base () const; 00367 bool has_offset (bool regOnly = true) const; 00368 bool has_target () const; 00369 00370 int stack_arg_bytes(void) { return _stack_arg_bytes; } 00371 void stack_arg_bytes(int bytes) { _stack_arg_bytes = bytes; } 00372 00373 // get our destination register - this is here so that if we are a 00374 // decl of a variable that is allocated to a register, we can 00375 // pretend to define that register 00376 Register get_dest (); 00377 00378 // stringize the contents of some part of an instruction 00379 static string contents_str (declNode * pDecl); 00380 static int contents_compiler_temp_index; 00381 00382 }; 00383 00384 00385 // represents a basic block at LIR level 00386 class LirBlock 00387 { 00388 public: 00389 // primary interface 00390 00391 // ctor 00392 LirBlock (int number) 00393 { 00394 // save number 00395 _number = number; 00396 00397 // init other values 00398 _next = NULL; 00399 _depth = 0; 00400 _visited = false; 00401 } 00402 00403 // access instruction list instructions 00404 const instruction_list & insts () const; 00405 void add_inst_before (LirInst * newInst, LirInst * otherInst); 00406 void add_inst_after (LirInst * newInst, LirInst * otherInst); 00407 void add_inst (LirInst * inst); 00408 void remove_inst (LirInst * inst); 00409 00410 // reset visitation flag on this and all successors 00411 void reset_visited (); 00412 00413 // successors/predecessors 00414 LirBlockSet _preds; 00415 LirBlockSet _succs; 00416 00417 // next block in linear block order 00418 LirBlock *_next; 00419 00420 // dominators of this block 00421 LirBlockSet _doms; // dominators 00422 00423 // block number 00424 unsigned int _number; 00425 00426 // loop depth 00427 unsigned int _depth; 00428 00429 // visitation flag 00430 // NOTE: this is just for the convenience of people that need to traverse 00431 // the CFG and not worry about getting into an infinite loop. 00432 bool _visited; 00433 00434 protected: 00435 00436 // instructions in this block 00437 instruction_list _instructions; 00438 }; 00439 00440 00441 #endif // __INSTRUCTION_H |
Generated on August 27, 2003
Back to the C-Breeze home page