home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / bytecode.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-24  |  29.1 KB  |  900 lines

  1. // $Id: bytecode.h,v 1.22 2001/01/05 09:13:19 mdejong Exp $
  2. //
  3. // License Agreement available at the following URL:
  4. // http://www.ibm.com/research/jikes.
  5. // Copyright (C) 1996, 1998, International Business Machines Corporation
  6. // and others.  All Rights Reserved.
  7. // You must accept the terms of that agreement to use this software.
  8.  
  9. //
  10. #ifndef bytecode_INCLUDED
  11. #define bytecode_INCLUDED
  12.  
  13. #include "platform.h"
  14. #include "tuple.h"
  15. #include "ast.h"
  16. #include "class.h"
  17. #include "option.h"
  18. #include "long.h"
  19. #include "op.h"
  20. #include "segment.h"
  21.  
  22. #ifdef    HAVE_JIKES_NAMESPACE
  23. namespace Jikes {    // Open namespace Jikes block
  24. #endif
  25.  
  26. class TypeSymbol;
  27. class Control;
  28. class Semantic;
  29.  
  30. class Label
  31. {
  32. public:
  33.  
  34.     class LabelUse
  35.     {
  36.     public:
  37.         int use_length, // length of use (2 or 4 bytes)
  38.             op_offset,  // length of use from opcode starting instruction
  39.             use_offset; // offset in code stream of use
  40.  
  41.         LabelUse() : use_length(0), op_offset(0), use_offset(0) {}
  42.  
  43.         LabelUse(int _length, int _op_offset, int _use) : use_length(_length), op_offset(_op_offset), use_offset(_use) {}
  44.     };
  45.  
  46.     bool defined;   // boolean, set when value is known
  47.     int definition; // offset of definition point of label
  48.     Tuple<LabelUse> uses;
  49.  
  50.     Label() : defined(false), definition(0) {}
  51.  
  52.     void Reset()
  53.     {
  54.        uses.Reset();
  55.        defined = false;
  56.        definition = 0;
  57.     }
  58. };
  59.  
  60.  
  61. //
  62. //
  63. //
  64. class MethodStack
  65. {
  66. public:
  67.  
  68.     void Push(AstBlock *block)
  69.     {
  70.         assert(block -> nesting_level < stack_size &&
  71.               (top_index == 0 || ((block -> nesting_level - 1) == nesting_level[top_index - 1])));
  72.  
  73.         nesting_level[top_index] = block -> nesting_level;
  74.         break_labels[block -> nesting_level].uses.Reset();
  75.         continue_labels[block -> nesting_level].uses.Reset();
  76.         finally_labels[block -> nesting_level].uses.Reset();
  77.         monitor_labels[block -> nesting_level].uses.Reset();
  78.         blocks[block -> nesting_level] = block;
  79.  
  80. #ifdef JIKES_DEBUG
  81.         (void) memset(local_variables_start_pc[block -> nesting_level], 0xFF, size * sizeof(u2));
  82. #endif
  83.         top_index++;
  84.     }
  85.  
  86.     void Pop()
  87.     {
  88.         if (top_index > 0)
  89.         {
  90.             top_index--;
  91. #ifdef JIKES_DEBUG
  92.             int level = nesting_level[top_index];
  93.  
  94.             nesting_level[top_index] = 0;
  95.             break_labels[level].Reset();
  96.             continue_labels[level].Reset();
  97.             finally_labels[level].Reset();
  98.             monitor_labels[level].Reset();
  99.             blocks[level] = NULL;
  100.             (void) memset(local_variables_start_pc[level], 0xFF, size * sizeof(u2));
  101. #endif
  102.         }
  103.         else assert(false);
  104.     }
  105.  
  106.     int Size() { return top_index; }
  107.  
  108. #ifdef JIKES_DEBUG
  109.     void AssertIndex(int k)
  110.     {
  111.         for (int i = 0; i < Size(); i++)
  112.             if (nesting_level[i] == k)
  113.                 return;
  114.         assert(0);
  115.     }
  116. #else
  117. #define AssertIndex(x)
  118. #endif
  119.  
  120.     int TopNestingLevel()   { assert(top_index > 0); return nesting_level[top_index - 1]; }
  121.     int NestingLevel(int i) { AssertIndex(i); return nesting_level[i]; }
  122.  
  123.     Label &TopBreakLabel()    { return break_labels[TopNestingLevel()]; }
  124.     Label &BreakLabel(int i)  { AssertIndex(i); return break_labels[i]; }
  125.  
  126.     Label &TopContinueLabel()   { return continue_labels[TopNestingLevel()]; }
  127.     Label &ContinueLabel(int i) { AssertIndex(i); return continue_labels[i]; }
  128.  
  129.     Label &TopFinallyLabel()    { return finally_labels[TopNestingLevel()]; }
  130.     Label &FinallyLabel(int i)  { AssertIndex(i); return finally_labels[i]; }
  131.  
  132.     Label &TopMonitorLabel()   { return monitor_labels[TopNestingLevel()]; }
  133.     Label &MonitorLabel(int i) { AssertIndex(i); return monitor_labels[i]; }
  134.  
  135.     AstBlock *TopBlock()   { return blocks[TopNestingLevel()]; }
  136.     AstBlock *Block(int i) { AssertIndex(i); return blocks[i]; }
  137.  
  138.     //
  139.     //
  140.     //
  141.     u2 *TopLocalVariablesStartPc() { return (u2 *) local_variables_start_pc[TopNestingLevel()]; }
  142.     u2 &StartPc(VariableSymbol *variable)
  143.     {
  144.         assert(variable -> LocalVariableIndex() >= 0 && variable -> LocalVariableIndex() < size);
  145.         return TopLocalVariablesStartPc()[variable -> LocalVariableIndex()];
  146.     }
  147.  
  148.     MethodStack(int stack_size_, int size_) : stack_size(stack_size_),
  149.                                               size(size_),
  150.                                               top_index(0)
  151.     {
  152.         nesting_level = new int[stack_size];
  153.         break_labels = new Label[stack_size];
  154.         continue_labels = new Label[stack_size];
  155.         finally_labels = new Label[stack_size];
  156.         monitor_labels = new Label[stack_size];
  157.         blocks = new AstBlock *[stack_size];
  158.  
  159.         local_variables_start_pc = new u2*[stack_size];
  160.         for (int i = 0; i < stack_size; i++)
  161.             local_variables_start_pc[i] = new u2[size];
  162.     }
  163.     ~MethodStack()
  164.     {
  165.         delete [] nesting_level;
  166.  
  167.         delete [] break_labels;
  168.         delete [] continue_labels;
  169.         delete [] finally_labels;
  170.         delete [] monitor_labels;
  171.  
  172.         delete [] blocks;
  173.  
  174.         for (int i = 0; i < stack_size; i++)
  175.             delete [] local_variables_start_pc[i];
  176.         delete [] local_variables_start_pc;
  177.     }
  178.  
  179. private:
  180.     int *nesting_level;
  181.  
  182.     Label *break_labels,
  183.           *continue_labels,
  184.           *finally_labels,
  185.           *monitor_labels;
  186.  
  187.     AstBlock **blocks; // block symbols for current block
  188.  
  189.     u2 **local_variables_start_pc;
  190.     int stack_size,
  191.         size,
  192.         top_index;
  193. };
  194.  
  195.  
  196. class ByteCode : public ClassFile, public StringConstant, public Operators
  197. {
  198.     Control& this_control;
  199.     Semantic& this_semantic;
  200.  
  201.     void CompileClass();
  202.     void CompileInterface();
  203.  
  204.     int line_number,
  205.         last_label_pc,        // pc for last (closest to end) label
  206.         last_op_pc,           // pc of last operation emitted
  207.         last_op_nop,          // set if last operation was NOP.
  208.         stack_depth,          // current stack depth;
  209.         max_stack,
  210.         max_block_depth,
  211.         last_parameter_index; // set to local variable index of last parameter
  212.     MethodStack *method_stack;
  213.  
  214.     bool string_overflow,
  215.          library_method_not_found;
  216.  
  217.     Code_attribute *code_attribute; // code for current method ?
  218.     LineNumberTable_attribute *line_number_table_attribute;
  219.     LocalVariableTable_attribute *local_variable_table_attribute;
  220.     InnerClasses_attribute *inner_classes_attribute;
  221.  
  222.     void MethodInitialization()
  223.     {
  224.         last_label_pc = 0;
  225.         last_op_pc = 0;
  226.         last_op_nop = 0;
  227.  
  228.         stack_depth = 0;
  229.  
  230.         max_stack = 0;
  231.  
  232.         return;
  233.     }
  234.  
  235.     void    ProcessAbruptExit(int, TypeSymbol * = NULL);
  236.     void    CompleteLabel(Label &lab);
  237.     void    DefineLabel(Label &lab);
  238.     void    UseLabel(Label &lab, int length, int op_offset);
  239.  
  240.     bool IsLabelUsed(Label &lab)
  241.     {
  242.         return (lab.uses.Length() > 0);
  243.     }
  244.  
  245.  
  246.     //
  247.     // see if operand is null. The front-end will have inserted a cast
  248.     // of null to the present type
  249.     //
  250.     bool IsNull(AstExpression *p)
  251.     {
  252.         return (p -> CastExpressionCast() ? (p -> CastExpressionCast() -> expression -> Type() == this_control.null_type) : false);
  253.     }
  254.  
  255.  
  256.     //
  257.     // Does p refer to a non-null reference type?
  258.     //
  259.     bool IsReferenceType(TypeSymbol *p)
  260.     {
  261.         return (! (p -> Primitive() || p == this_control.null_type));
  262.     }
  263.  
  264.  
  265.     //
  266.     // see if operand is integer type and is zero
  267.     //
  268.     bool IsZero(AstExpression *p)
  269.     {
  270.         if (p -> IsConstant() && (p -> Type() == this_control.int_type || p -> Type() == this_control.boolean_type))
  271.         {
  272.             IntLiteralValue *vp = (IntLiteralValue *) (p -> value);
  273.             return (vp -> value == 0);
  274.         }
  275.  
  276.         return false;
  277.     }
  278.  
  279.  
  280.     //
  281.     // memory access: reference either
  282.     // constant (literal)
  283.     // name (includes local varable, or class variable, or field access)
  284.     // array
  285.     //
  286.     enum
  287.     {
  288.         LHS_LOCAL =  0, // local variable
  289.         LHS_ARRAY =  1, // array (of any kind)
  290.         LHS_FIELD =  2, // instance variable
  291.         LHS_STATIC = 3, // class variable
  292.         LHS_METHOD = 4 // access to private variable
  293.     };
  294.  
  295.     int GetLhsKind(AstExpression *expression)
  296.     {
  297.         AstAssignmentExpression *assignment = expression -> AssignmentExpressionCast();
  298.         AstPreUnaryExpression *pre = expression -> PreUnaryExpressionCast();
  299.         AstPostUnaryExpression *post = expression -> PostUnaryExpressionCast();
  300.  
  301.         AstExpression *lhs = assignment ? (assignment -> write_method ? (AstExpression *) NULL : assignment -> left_hand_side)
  302.                                         : pre ? (pre -> write_method ? (AstExpression *) NULL : pre -> expression)
  303.                                               : post ? (post -> write_method ? (AstExpression *) NULL : post -> expression)
  304.                                                      : expression;
  305.  
  306.         //
  307.         // Find symbol that is associated with expression. If the subexpression has
  308.         // to be referenced via an access method then the symbol is null
  309.         //
  310.         AstCastExpression *cast = (lhs ? lhs -> CastExpressionCast() : (AstCastExpression *) NULL);
  311.         Symbol *sym = cast ? cast -> expression -> symbol : (lhs ? lhs -> symbol : (Symbol *) NULL);
  312.  
  313.         //
  314.         // If the expression associated with the left-hand side is null,
  315.         // then we have an access method.
  316.         // Otherwise, a left-hand side is either an array access,
  317.         // a field access or a name. In the case of a FieldAccess
  318.         // or name, the left-hand side is resolved into a variable.
  319.         // In the case of an array access, it is resolved into a type.
  320.         //
  321.         VariableSymbol *var = (sym ? sym -> VariableCast() : (VariableSymbol *) NULL);
  322.         return ((! lhs) ? LHS_METHOD
  323.                         : (! var) ? LHS_ARRAY
  324.                                   : var -> owner -> MethodCast() ? LHS_LOCAL
  325.                                                                  : var -> ACC_STATIC() ? LHS_STATIC
  326.                                                                                        : LHS_FIELD);
  327.     }
  328.  
  329.  
  330.     int GetTypeWords(TypeSymbol *type)
  331.     {
  332.         return this_control.IsDoubleWordType(type) ? 2 : 1;
  333.     }
  334.  
  335.  
  336.     //
  337.     // methods to load and store values
  338.     //
  339.     void LoadLocal(int varno, TypeSymbol *);
  340.     void StoreLocal(int varno, TypeSymbol *);
  341.     void LoadReference(AstExpression *);
  342.     void LoadLiteral(LiteralValue *, TypeSymbol *);
  343.     void LoadImmediateInteger(int);
  344.     int  LoadVariable(int, AstExpression *);
  345.     int  LoadArrayElement(TypeSymbol *);
  346.     void StoreArrayElement(TypeSymbol *);
  347.     void StoreField(AstExpression *);
  348.     void StoreVariable(int, AstExpression *);
  349.  
  350.     void LoadConstantAtIndex(u2 index)
  351.     {
  352.         if (index <= 255)
  353.         {
  354.             PutOp(OP_LDC);
  355.             PutU1((u1) index);
  356.         }
  357.         else
  358.         {
  359.             PutOp(OP_LDC_W);
  360.             PutU2(index);
  361.         }
  362.  
  363.         return;
  364.     }
  365.  
  366.     //
  367.     // These pools are sets that keep track of elements that have
  368.     // already been inserted in the constant pool.
  369.     //
  370.     SegmentPool segment_pool;
  371.  
  372.     Pair *double_constant_pool_index,
  373.          *integer_constant_pool_index,
  374.          *long_constant_pool_index,
  375.          *float_constant_pool_index,
  376.          *string_constant_pool_index,
  377.  
  378.          utf8_constant_pool_index,
  379.          class_constant_pool_index;
  380.  
  381.     Triplet *name_and_type_constant_pool_index,
  382.             *fieldref_constant_pool_index,
  383.             *methodref_constant_pool_index;
  384.  
  385.     u2 RegisterNameAndType(Utf8LiteralValue *name, Utf8LiteralValue *type_name)
  386.     {
  387.         assert((name != NULL && type_name != NULL) && "null argument to RegisterNameAndType");
  388.  
  389.         if (! name_and_type_constant_pool_index)
  390.             name_and_type_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  391.  
  392.         u2 index = name_and_type_constant_pool_index -> Image(name -> index, type_name -> index);
  393.         if (index == 0)
  394.         {
  395.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  396.             index = i;
  397.             name_and_type_constant_pool_index -> Image(name -> index, type_name -> index) = index;
  398.             constant_pool[i] = new CONSTANT_NameAndType_info(CONSTANT_NameAndType, RegisterUtf8(name), RegisterUtf8(type_name));
  399.         }
  400.  
  401.         return index;
  402.     }
  403.  
  404.  
  405.     u2 RegisterFieldref(Utf8LiteralValue *class_name,
  406.                         Utf8LiteralValue *field_name,
  407.                         Utf8LiteralValue *field_type_name)
  408.     {
  409.         assert((class_name != NULL && field_name != NULL && field_type_name != NULL) && "null argument to RegisterFieldref");
  410.  
  411.         if (! fieldref_constant_pool_index)
  412.             fieldref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  413.  
  414.         u2 name_type_index = RegisterNameAndType(field_name, field_type_name),
  415.            index = fieldref_constant_pool_index -> Image(class_name -> index, name_type_index);
  416.         if (index == 0)
  417.         {
  418.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  419.             index = i;
  420.             fieldref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  421.             constant_pool[i] = new CONSTANT_Fieldref_info(CONSTANT_Fieldref, RegisterClass(class_name), name_type_index);
  422.         }
  423.  
  424.         return index;
  425.     }
  426.  
  427.  
  428.     u2 RegisterFieldref(TypeSymbol *type, VariableSymbol *variable_symbol)
  429.     {
  430.         assert(variable_symbol -> owner -> TypeCast());
  431.  
  432.         return RegisterFieldref(type -> fully_qualified_name,
  433.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  434.                                 variable_symbol -> Type() -> signature);
  435.     }
  436.  
  437.  
  438.     u2 RegisterFieldref(VariableSymbol *variable_symbol)
  439.     {
  440.         assert(variable_symbol -> owner -> TypeCast());
  441.  
  442.         return RegisterFieldref(variable_symbol -> owner -> TypeCast() -> fully_qualified_name,
  443.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  444.                                 variable_symbol -> Type() -> signature);
  445.     }
  446.  
  447.  
  448.     u2 RegisterMethodref(ConstantKind kind,
  449.                          Utf8LiteralValue *class_name,
  450.                          Utf8LiteralValue *method_name,
  451.                          Utf8LiteralValue *method_type_name)
  452.     {
  453.         assert((class_name != NULL && method_name != NULL && method_type_name != NULL) && "null argument to RegisterMethodref");
  454.  
  455.         if (! methodref_constant_pool_index)
  456.             methodref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  457.  
  458.         u2 name_type_index = RegisterNameAndType(method_name, method_type_name),
  459.            index = methodref_constant_pool_index -> Image(class_name -> index, name_type_index);
  460.         if (index == 0)
  461.         {
  462.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  463.             index = i;
  464.             methodref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  465.  
  466.             u2 class_name_index = RegisterClass(class_name);
  467.             constant_pool[i] = (kind == CONSTANT_Methodref
  468.                                       ? (cp_info *) new CONSTANT_Methodref_info(CONSTANT_Methodref,
  469.                                                                                 class_name_index,
  470.                                                                                 name_type_index)
  471.                                       : (cp_info *) new CONSTANT_InterfaceMethodref_info(CONSTANT_InterfaceMethodref,
  472.                                                                                          class_name_index,
  473.                                                                                          name_type_index));
  474.         }
  475.  
  476.         return index;
  477.     }
  478.  
  479.  
  480.     u2 RegisterMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  481.     {
  482.         return RegisterMethodref(CONSTANT_Methodref, class_name, method_name, method_type_name);
  483.     }
  484.  
  485.     u2 RegisterInterfaceMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  486.     {
  487.         return RegisterMethodref(CONSTANT_InterfaceMethodref, class_name, method_name, method_type_name);
  488.     }
  489.  
  490.  
  491.     u2 RegisterLibraryMethodref(MethodSymbol *method)
  492.     {
  493.         if (method) // The library method must exist. If it is not, flag an error.
  494.             return RegisterMethodref(CONSTANT_Methodref, method -> containing_type -> fully_qualified_name,
  495.                                                          method -> ExternalIdentity()-> Utf8_literal,
  496.                                                          method -> signature);
  497.         library_method_not_found = true;
  498.  
  499.         return 0;
  500.     }
  501.  
  502.     u2 RegisterDouble(DoubleLiteralValue *lit)
  503.     {
  504.         assert((lit != NULL) && "null argument to RegisterDouble");
  505.  
  506.         if (! double_constant_pool_index)
  507.             double_constant_pool_index = new Pair(segment_pool, this_control.double_pool.symbol_pool.Length());
  508.  
  509.         u2 index = (*double_constant_pool_index)[lit -> index];
  510.         if (index == 0)
  511.         {
  512.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  513.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  514.             index = i;
  515.             (*double_constant_pool_index)[lit -> index] = index;
  516.             constant_pool[i] = new CONSTANT_Double_info(CONSTANT_Double, lit -> value.HighWord(), lit -> value.LowWord());
  517.         }
  518.  
  519.         return index;
  520.     }
  521.  
  522.  
  523.     u2 RegisterInteger(IntLiteralValue *lit)
  524.     {
  525.         assert((lit != NULL) && "null argument to RegisterInteger");
  526.  
  527.         if (! integer_constant_pool_index)
  528.             integer_constant_pool_index = new Pair(segment_pool, this_control.int_pool.symbol_pool.Length());
  529.  
  530.         u2 index = (*integer_constant_pool_index)[lit -> index];
  531.         if (index == 0)
  532.         {
  533.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  534.             index = i;
  535.             (*integer_constant_pool_index)[lit -> index] = index;
  536.             int val = lit -> value;
  537.             u4 bytes = (((unsigned) (val >> 24)) << 24) | ((val >> 16 & 0xff) << 16) | ((val >> 8 & 0xff) ) << 8 | (val & 0xff);
  538.             constant_pool[i] = new CONSTANT_Integer_info(CONSTANT_Integer, bytes);
  539.         }
  540.  
  541.         return index;
  542.     }
  543.  
  544.  
  545.     u2 FindInteger(IntLiteralValue *lit)
  546.     {
  547.         return (lit && integer_constant_pool_index ? (*integer_constant_pool_index)[lit -> index] : 0);
  548.     }
  549.  
  550.  
  551.     u2 RegisterLong(LongLiteralValue *lit)
  552.     {
  553.         assert((lit != NULL) && "null argument to RegisterLong");
  554.  
  555.         if (! long_constant_pool_index)
  556.             long_constant_pool_index = new Pair(segment_pool, this_control.long_pool.symbol_pool.Length());
  557.  
  558.         u2 index = (*long_constant_pool_index)[lit -> index];
  559.         if (index == 0)
  560.         {
  561.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  562.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  563.             index = i;
  564.             (*long_constant_pool_index)[lit -> index] = index;
  565.             constant_pool[i] = new CONSTANT_Long_info(CONSTANT_Long, lit -> value.HighWord(), lit -> value.LowWord());
  566.         }
  567.  
  568.         return index;
  569.     }
  570.  
  571.  
  572.     u2 RegisterFloat(FloatLiteralValue *lit)
  573.     {
  574.         assert((lit != NULL) && "null argument to RegisterFloat");
  575.  
  576.         if (! float_constant_pool_index)
  577.             float_constant_pool_index = new Pair(segment_pool, this_control.float_pool.symbol_pool.Length());
  578.  
  579.         u2 index = (*float_constant_pool_index)[lit -> index];
  580.         if (index == 0)
  581.         {
  582.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  583.             index = i;
  584.             (*float_constant_pool_index)[lit -> index] = index;
  585.             constant_pool[i] = new CONSTANT_Float_info(CONSTANT_Float, lit -> value.Word());
  586.         }
  587.  
  588.         return index;
  589.     }
  590.  
  591.  
  592.     u2 RegisterUtf8(Utf8LiteralValue *lit)
  593.     {
  594.         assert((lit != NULL) && "null argument to RegisterUtf8");
  595.  
  596.         u2 index = utf8_constant_pool_index[lit -> index];
  597.         if (index == 0)
  598.         {
  599.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  600.             index = i;
  601.             utf8_constant_pool_index[lit -> index] = index;
  602.             constant_pool[i] = new CONSTANT_Utf8_info(CONSTANT_Utf8, lit -> value, lit -> length);
  603.         }
  604.  
  605.         return index;
  606.     }
  607.  
  608.  
  609.     u2 RegisterString(Utf8LiteralValue *lit)
  610.     {
  611.         assert((lit != NULL) && "null argument to RegisterString");
  612.  
  613.         //
  614.         // The domain of these maps is an index in the constant_pool.
  615.         // For a valid program, the size of the constant pool is limited
  616.         // to 65k elements.
  617.         //
  618.         if (! string_constant_pool_index)
  619.             string_constant_pool_index = new Pair(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  620.  
  621.         u2 index = (*string_constant_pool_index)[lit -> index];
  622.         if (index == 0)
  623.         {
  624.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  625.             index = i;
  626.             (*string_constant_pool_index)[lit -> index] = index;
  627.             constant_pool[i] = new CONSTANT_String_info(CONSTANT_String, RegisterUtf8(lit));
  628.         }
  629.  
  630.         return index;
  631.     }
  632.  
  633.  
  634.     u2 RegisterClass(Utf8LiteralValue *lit)
  635.     {
  636.         assert((lit != NULL) && "null argument to RegisterClass");
  637.  
  638.         u2 index = class_constant_pool_index[lit -> index];
  639.         if (index == 0)
  640.         {
  641.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  642.             index = i;
  643.             class_constant_pool_index[lit -> index] = index;
  644.             constant_pool[i] = new CONSTANT_Class_info(CONSTANT_Class, RegisterUtf8(lit));
  645.         }
  646.  
  647.         return index;
  648.     }
  649.  
  650.  
  651.     //
  652.     //  Methods to write out the byte code
  653.     //
  654.     Deprecated_attribute *CreateDeprecatedAttribute()
  655.     {
  656.         return new Deprecated_attribute(RegisterUtf8(this_control.Deprecated_literal));
  657.     }
  658.  
  659.  
  660.     Synthetic_attribute *CreateSyntheticAttribute()
  661.     {
  662.         return new Synthetic_attribute(RegisterUtf8(this_control.Synthetic_literal));
  663.     }
  664.  
  665.  
  666.     //
  667.     // Methods to generate expressions.
  668.     //
  669.     int  EmitExpression(AstExpression *);
  670.     int  EmitArrayCreationExpression(AstArrayCreationExpression *);
  671.     int  EmitAssignmentExpression(AstAssignmentExpression *, bool);
  672.     int  EmitBinaryExpression(AstBinaryExpression *);
  673.     int  EmitCastExpression(AstCastExpression *);
  674.     void EmitCast(TypeSymbol *, TypeSymbol *);
  675.     int  EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *, bool);
  676.     int  EmitConditionalExpression(AstConditionalExpression *);
  677.     int  EmitFieldAccess(AstFieldAccess *);
  678.     AstExpression *VariableExpressionResolution(AstExpression *);
  679.     TypeSymbol *VariableTypeResolution(AstExpression *, VariableSymbol *);
  680.     TypeSymbol *MethodTypeResolution(AstExpression *, MethodSymbol *);
  681.     void EmitFieldAccessLhsBase(AstExpression *);
  682.     void EmitFieldAccessLhs(AstExpression *);
  683.     void EmitMethodInvocation(AstMethodInvocation *);
  684.     void EmitNewArray(int, TypeSymbol *);
  685.     int  EmitPostUnaryExpression(AstPostUnaryExpression *, bool);
  686.     void EmitPostUnaryExpressionArray(AstPostUnaryExpression *, bool);
  687.     void EmitPostUnaryExpressionField(int, AstPostUnaryExpression *, bool);
  688.     void EmitPostUnaryExpressionSimple(int, AstPostUnaryExpression *, bool);
  689.     int  EmitPreUnaryExpression(AstPreUnaryExpression *, bool);
  690.     void EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, bool);
  691.     void EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, bool);
  692.     void EmitPreUnaryIncrementExpressionField(int, AstPreUnaryExpression *expression, bool);
  693.     void EmitPreUnaryIncrementExpressionSimple(int, AstPreUnaryExpression *expression, bool);
  694.     void EmitThisInvocation(AstThisCall *);
  695.     void EmitSuperInvocation(AstSuperCall *);
  696.     void ConcatenateString(AstBinaryExpression *);
  697.     void AppendString(AstExpression *);
  698.     void EmitStringAppendMethod(TypeSymbol *);
  699.     void GenerateAccessMethod(MethodSymbol *);
  700.     void ChangeStack (int);
  701.     void ResolveAccess(AstExpression *);
  702.     int  GenerateClassAccess(AstFieldAccess *);
  703.     void GenerateClassAccessMethod(MethodSymbol *);
  704.  
  705.     //
  706.     // Methods to process statements
  707.     //
  708.     void CompileConstructor(AstConstructorDeclaration *, Tuple<AstVariableDeclarator *> &);
  709.  
  710.     void BeginMethod(int, MethodSymbol *);
  711.     void EndMethod(int, MethodSymbol *);
  712.     void DeclareField(VariableSymbol *);
  713.     void InitializeClassVariable(AstVariableDeclarator *);
  714.     void InitializeInstanceVariable(AstVariableDeclarator *);
  715.     void InitializeArray(TypeSymbol *, AstArrayInitializer *);
  716.     void DeclareLocalVariable(AstVariableDeclarator *);
  717.     void EmitStatement(AstStatement *);
  718.     void EmitReturnStatement(AstReturnStatement *);
  719.     void EmitSynchronizedStatement(AstSynchronizedStatement *);
  720.     void EmitBlockStatement(AstBlock *);
  721.     void EmitStatementExpression(AstExpression *);
  722.     void EmitSwitchStatement(AstSwitchStatement *);
  723.     void EmitTryStatement(AstTryStatement *);
  724.     void EmitBranchIfExpression(AstExpression *, bool, Label &);
  725.     void CompleteCall(MethodSymbol *, int, TypeSymbol * = NULL);
  726.  
  727.  
  728.     //
  729.     // called when expression has been parenthesized to removed
  730.     // parantheses and expose true structure.
  731.     //
  732.     AstExpression *UnParenthesize(AstExpression *expr)
  733.     {
  734.         while(expr -> ParenthesizedExpressionCast())
  735.             expr = expr -> ParenthesizedExpressionCast() -> expression;
  736.  
  737.         return expr;
  738.     }
  739.  
  740.  
  741.     void EmitArrayAccessLhs(AstArrayAccess *expression)
  742.     {
  743.         LoadReference(expression -> base);
  744.         EmitExpression(expression -> expression);
  745.  
  746.         return;
  747.     }
  748.  
  749.  
  750.     int EmitArrayAccessRhs(AstArrayAccess *expression)
  751.     {
  752.         EmitArrayAccessLhs(expression); // get array address and index
  753.         return LoadArrayElement(expression -> Type());
  754.     }
  755.  
  756.  
  757.     void EmitBranch(unsigned int opc, Label& lab)
  758.     {
  759.         PutOp(opc);
  760.         UseLabel(lab, 2, 1);
  761.  
  762.         return;
  763.     }
  764.  
  765.  
  766.     void GenerateReturn(TypeSymbol *type)
  767.     {
  768.         PutOp(this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type
  769.                   ? OP_IRETURN
  770.                   : type == this_control.long_type
  771.                           ? OP_LRETURN
  772.                           : type == this_control.float_type
  773.                                   ? OP_FRETURN
  774.                                   : type == this_control.double_type
  775.                                           ? OP_DRETURN
  776.                                           : OP_ARETURN);
  777.         return;
  778.     }
  779.  
  780.  
  781. #ifdef JIKES_DEBUG
  782.     void PrintCode();
  783. #endif
  784.  
  785.     void PutOp(unsigned char opc);
  786.  
  787.     void PutOpWide(unsigned char opc, u2 var);
  788.  
  789.     void PutOpIINC(u2 var, int val);
  790.  
  791.     //
  792.     //  Methods to insert values into byte code
  793.     //
  794.     void PutI1(i1 i)
  795.     {
  796.         code_attribute -> AddCode(i & 0xff);
  797.  
  798.         return;
  799.     }
  800.  
  801.  
  802.     void PutI2(i2 i)
  803.     {
  804.         code_attribute -> AddCode((i >> 8) & 0xff);
  805.         code_attribute -> AddCode(i & 0xff);
  806.  
  807.         return;
  808.     }
  809.  
  810.  
  811.     void PutU1(u1 u)
  812.     {
  813.         code_attribute -> AddCode(u & 0xff);
  814.  
  815.         return;
  816.     }
  817.  
  818.  
  819.     void PutU2(u2 u)
  820.     {
  821.         code_attribute -> AddCode((u >> 8) & 0xff);
  822.         code_attribute -> AddCode(u & 0xff);
  823.  
  824.         return;
  825.     }
  826.  
  827.  
  828.     void PutU4(u4 u)
  829.     {
  830.         code_attribute -> AddCode((u >> 24));
  831.         code_attribute -> AddCode((u >> 16) & 0xff);
  832.         code_attribute -> AddCode((u >>  8) & 0xff);
  833.         code_attribute -> AddCode(u & 0xff);
  834.  
  835.         return;
  836.     }
  837.  
  838.  
  839.     //
  840.     // emit NOP. The NOP can be replaced by the next instruction if
  841.     // optional is set; otherwise it must be kept.
  842.     //
  843.     void PutNop(int optional)
  844.     {
  845.         PutOp(OP_NOP);
  846.  
  847.         //
  848.         // this optimization is causing more trouble than it's worth.
  849.         // latest problem (27 jan 97) was reported by Derek, in that
  850.         // nop just before label definition, resulted in operation generated
  851.         // after label def. being moved before the def! Since it's such a sin
  852.         // to generate junk code, disable the "nop" optimization.
  853.         //  if (optional) last_op_nop = 1;
  854.         //
  855.  
  856.         return;
  857.     }
  858.  
  859.     void FinishCode(TypeSymbol *);
  860.  
  861.     void Reset()
  862.     {
  863.         constant_pool.Reset();
  864.         fields.Reset();
  865.         methods.Reset();
  866.         attributes.Reset();
  867.         this_class = super_class = 0;
  868.     }
  869.  
  870. public:
  871.     ByteCode(TypeSymbol *);
  872.  
  873.     ~ByteCode()
  874.     {
  875.         delete double_constant_pool_index;
  876.         delete integer_constant_pool_index;
  877.         delete long_constant_pool_index;
  878.         delete float_constant_pool_index;
  879.         delete string_constant_pool_index;
  880.  
  881.         delete name_and_type_constant_pool_index;
  882.         delete fieldref_constant_pool_index;
  883.         delete methodref_constant_pool_index;
  884.     }
  885.  
  886.     inline void GenerateCode()
  887.     {
  888.         if (unit_type -> ACC_INTERFACE())
  889.              CompileInterface();
  890.         else CompileClass();
  891.     }
  892. };
  893.  
  894. #ifdef    HAVE_JIKES_NAMESPACE
  895. }            // Close namespace Jikes block
  896. #endif
  897.  
  898. #endif
  899.  
  900.