// $Id: bytecode.h,v 1.4 1999/03/09 14:37:15 shields Exp $ copyright notice #ifndef bytecode_INCLUDED #define bytecode_INCLUDED #include <stdio.h> #include "tuple.h" #include "ast.h" #include "class.h" #include "option.h" #include "long.h" #include "op.h" class TypeSymbol; class Control; class Semantic; class LabelUse { public: int use_length; // length of use (2 or 4 bytes) int op_offset; // length of use from opcode starting instruction int use_offset; // offset in code stream of use LabelUse() : use_length(0),op_offset(0), use_offset(0) {} LabelUse(int _length, int _op_offset, int _use) : use_length(_length),op_offset(_op_offset),use_offset(_use) {} }; class Label { public: int defined; // boolean, set when value is known int definition; // offset of definition point of label Tuple<LabelUse> uses; Label() : defined(0), definition(0) {} }; class ByteCode : public ClassFile, public StringConstant { public: Control& this_control; Semantic& this_semantic; int class_id; // int bytes; // number of bytes written to file (so far) // Many java virtual machines, notably Sun's JDK 1.*, don't properly // handle the case where non-final static fields are initialized // using the Constant attribute, even though the documentation says // that this should be done. Define initialize_statics_in_clinit // to get this behavior to initialize such fields in clinit; otherwise // fields are initialized using the Constant attribute. int initialize_statics_in_clinit; int null_constructor_seen; // set if user supplied null constructor // if not set, we have to supply null constructor int line_number; int last_label_pc; // pc for last (closest to end) label int last_op_pc; // pc of last operation emitted int last_op_nop; // set if last operation was NOP. int this_block_depth; // depth of current block Code_attribute * code_attribute; // code for current method/?? int stack_depth; // current stack depth; LineNumberTable_attribute * line_number_table_attribute; LocalVariableTable_attribute * local_variable_table_attribute; // Synthetic_attribute * synthetic_attribute; InnerClasses_attribute * inner_classes_attribute; MethodSymbol * class_literal_method; #define METHOD_CLONE 0 #define METHOD_CLONE_GETMESSAGE 1 #define METHOD_CLONE_INIT 2 #define METHOD_STRINGBUFFER_TOSTRING 3 #define METHOD_STRINGBUFFER_INIT 4 #define METHOD_STRINGBUFFER_APPENDCHARARRAY 5 #define METHOD_STRINGBUFFER_APPENDCHAR 6 #define METHOD_STRINGBUFFER_APPENDBOOLEAN 7 #define METHOD_STRINGBUFFER_APPENDINT 8 #define METHOD_STRINGBUFFER_APPENDLONG 9 #define METHOD_STRINGBUFFER_APPENDFLOAT 10 #define METHOD_STRINGBUFFER_APPENDDOUBLE 11 #define METHOD_STRINGBUFFER_APPENDSTRING 12 #define METHOD_STRINGBUFFER_APPENDOBJECT 13 #define METHOD_NUMBER 14 int registered_methods[METHOD_NUMBER]; u2 name_StringNull; int max_block_depth; int last_parameter_index; // set to local variable index of last parameter Label * begin_labels; Label * break_labels; Label * continue_labels; Label * final_labels; Label * monitor_labels; Label * test_labels; int * has_finally_clause; int * is_synchronized; int synchronized_blocks; // number of outstanding synchronized blocks int finally_blocks; // number of outstanding synchronized blocks BlockSymbol ** block_symbols; // block symbols for current block int block_depth; // need to reset at start of each method TypeSymbol * method_type; // return type of method being compiled void chaos(char *msg); // called when can't proceed void ProcessAbruptExit(int); void CompleteLabel(Label& lab); void DefineLabel(Label& lab); int IsLabelUsed(Label& lab); void UseLabel(Label & lab,int length, int op_offset); // methods to determine type int IsLocal(AstExpression *); int IsNull(AstExpression *p); int IsReferenceType(TypeSymbol *p); int IsDefaultValue(AstExpression *p); int IsZero(AstExpression *p); int GetLHSKind(AstExpression *, MethodSymbol *); int GetTypeWords(TypeSymbol *); // methods to load and store values void LoadLocalVariable(VariableSymbol *); void LoadLocal(int varno, TypeSymbol * type); void StoreLocalVariable(VariableSymbol *); void StoreLocal(int varno, TypeSymbol * type); int GetConstant(LiteralValue *, TypeSymbol *); int LoadConstant(AstExpression *); int LoadLiteral(LiteralValue *,TypeSymbol *); void LoadReference(AstExpression *); void LoadShort(int val); void LoadInteger(int val); int LoadSimple(int,AstExpression *); int LoadArrayElement(TypeSymbol * type); void StoreArrayElement(TypeSymbol * type); void StoreField(AstExpression *); void StoreSimple(int,AstExpression *); // These methods build entries in the constant pool. u2 BuildDouble(IEEEdouble val); u2 BuildFieldref(u2 cl_index, u2 nt_index); u2 BuildFloat(IEEEfloat val); u2 BuildInteger(int val); u2 BuildInterfaceMethodref(u2 cl_index, u2 nt_index); u2 BuildLong(LongInt val); u2 BuildMethodref(u2 cl_index, u2 nt_index); u2 BuildNameAndType(u2 name, u2 type); // make entry in constant pool from wchar string and return its index. u2 BuildString(u2 si); u2 BuildUtf8(char *name,int length); // unlike most methods, which always build a new entry, the // 'register' methods only build a new entry for a literal if one has net // yet been built. u2 RegisterClass(Utf8LiteralValue *); u2 RegisterClass(char *, int ); u2 RegisterDouble(DoubleLiteralValue *); u2 RegisterFloat(FloatLiteralValue *); u2 RegisterInteger(IntLiteralValue *); u2 RegisterLong(LongLiteralValue *); u2 RegisterMethod(int); u2 RegisterString(Utf8LiteralValue *); u2 RegisterUtf8(Utf8LiteralValue *); u2 RegisterUtf8(char *, int); void AddLocalVariableTableEntry(u2,u2,u2,u2,u2); // make entry in local variable table void SetInnerAttribute(TypeSymbol *); // make entry for InnerClasses attribute Synthetic_attribute * CreateSyntheticAttribute(); Deprecated_attribute * CreateDeprecatedAttribute(); // // memory access: reference either // constant (literal) // name (includes local varable, or class variable, or field access) // array #define LHS_LOCAL 0 // local variable #define LHS_ARRAY 1 // array (of any kind) #define LHS_FIELD 2 // instance variable #define LHS_STATIC 3 // class variable #define LHS_CLASS_METHOD 4 // access to private variable via class method call #define LHS_STATIC_METHOD 5 // access to private variable via static method call // Methods in bc_expr.cpp int EmitExpression(AstExpression * ast); void EmitArrayAccessLHS(AstArrayAccess *); int EmitArrayAccessRHS(AstArrayAccess *); int EmitArrayCreationExpression(AstArrayCreationExpression *); int EmitAssignmentExpression(AstAssignmentExpression *, int); int EmitBinaryExpression(AstBinaryExpression *); void EmitBinaryOp(AstBinaryExpression *, int iop, int lop, int fop, int dop); int EmitCastExpression(AstCastExpression *); void EmitCast(TypeSymbol *, TypeSymbol *); int EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *, int); int EmitConditionalExpression(AstConditionalExpression *); int EmitFieldAccess(AstFieldAccess *); void EmitFieldAccessLHS(AstExpression *); void EmitFieldAccessLHSBase(AstExpression *); int EmitMethodInvocation(AstMethodInvocation *, int); void EmitNewArray(int,TypeSymbol *); void EmitCloneArray(AstMethodInvocation *); int EmitPostUnaryExpression(AstPostUnaryExpression *,int); void EmitPostUnaryExpressionArray(AstPostUnaryExpression *expression, int); void EmitPostUnaryExpressionArrayCode(int, int, int, int, int, int, int, int, int); void EmitPostUnaryExpressionField(int,AstPostUnaryExpression *expression, int); void EmitPostUnaryExpressionSimple(int,AstPostUnaryExpression *, int); int EmitPreUnaryExpression(AstPreUnaryExpression *,int); void EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, int); void EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, int); void EmitPreUnaryIncrementExpressionArrayCode(int, int, int, int, int, int, int,int,int); void EmitPreUnaryIncrementExpressionField(int,AstPreUnaryExpression *expression, int); void EmitPreUnaryIncrementExpressionSimple(int,AstPreUnaryExpression *expression, int); void EmitThisInvocation(AstThisCall *); void EmitSuperInvocation(AstSuperCall *); AstExpression * UnParenthesize(AstExpression *); void ConcatenateString(AstBinaryExpression *); void EmitStringBuffer(); void EmitCallStringToString(); void AppendString(AstExpression *); void EmitStringAppendMethod(TypeSymbol *); void GenerateAccessMethod(MethodSymbol *); int GenerateFieldReference(VariableSymbol *); void ChangeStack (int); void ResolveAccess(AstExpression *, int); int GenerateClassAccess(AstFieldAccess *); void GenerateClassAccessMethod(MethodSymbol *); // Methods in bc_stmt.cpp void CompileClass(TypeSymbol *); //void SetConstructorParameter(VariableSymbol *); void CompileInterface(TypeSymbol *); void CompileConstructor(AstConstructorDeclaration *, Tuple<AstVariableDeclarator *> &); #define METHOD_KIND_ORDINARY 0 #define METHOD_KIND_CONSTRUCTOR 1 #define METHOD_KIND_GENERATED_CONSTRUCTOR 2 #define METHOD_KIND_INTERFACE 3 #define METHOD_KIND_ACCESS 4 #define METHOD_KIND_ACCESS_CLASS 5 int BeginMethod(int, MethodSymbol *); void EndMethod(int,int, MethodSymbol *); void DeclareField(VariableSymbol *); void InitializeClassVariable(AstVariableDeclarator *); void InitializeInstanceVariable(AstVariableDeclarator *); void InitializeArray(TypeSymbol *,AstArrayInitializer *); void DeclareLocalVariable(AstVariableDeclarator *); int EmitStatement(AstStatement *); void EmitReturnStatement(AstReturnStatement *); void EmitSynchronizedStatement(AstSynchronizedStatement *); int EmitBlockStatement(AstBlock *, int); void EmitStatementExpression(AstExpression * ast); void EmitSwitchStatement(AstSwitchStatement *); void UpdateBlockInfo(BlockSymbol *); void EmitTryStatement(AstTryStatement *); void EmitBranch(unsigned int opc, Label &); void EmitBranchIfExpression(AstExpression *, bool, Label &); void GenerateReturn(TypeSymbol * type); void CompleteCall(MethodSymbol *, int, int); #ifdef TEST void PrintCode(); #endif //void ProcessMethodDeclaration(AstMethodDeclaration *method); void FinishCode(TypeSymbol *); void Reset(){ constant_pool.Reset(); fields.Reset(); methods.Reset(); attributes.Reset(); this_class = super_class = 0; } public: ByteCode(TypeSymbol *); void PutOp(unsigned char opc); void PutNop(int); void PutI1(i1); void PutI2(i2); void PutU1(u1); void PutU2(u2); void PutU4(u4); }; #endif