1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
A few notes to myself...
----------------------------------------------------------------------
typedecl:
public, abstract, final and interface are meaningful.
protected is used as a scratch flag to tell whether the type has been
processed on this run through.
native is used to indicate that there aren't any non-overriding,
non-static methods in the type.
----------------------------------------------------------------------
Names in the C output file are of the form "Java<kind>_<id>", where
<kind> = ia* Instance structure tag (number of 'a's = level of array nesting)
<id> = <package>_<class>
= m Class jump-struct tag
<id> = <package>_<class>
= mia* Instantiation of class jump-struct
<id> = <package>_<class>
= sf Class field
<id> = <package>_<class>_<fieldname>
= coa* Prefabricated class object
<id> = <package>_<class>
= c Constructor
<id> = <package>_<class>__<argtypes>
= si Static initialiser
<id> = <package>_<class>
= (nothing) Class or instance method
<id> = <package>_<class>_<methodname>__<argtypes>
Arrays are supported by one of each of these shared between all arrays:
Javama Array jump-struct tag
Javamia Instantiation of array jump-struct
Javaa_clone Clone method for array classes
Actually, that isn't true; because the jump-struct contains a pointer
to the class object, we must instantiate the jump-struct once per array
type. All array types use Javam_java_lang_Object as the type of their
jump-struct, because they don't have any methods specific to themselves.
So, Javam_java_lang_Object is the jump-struct tag for all array types,
but the instantiations are Javamia_pkg_Class, Javamiabool, etc.
Also:
Java(m)i(a*)bool, Java(m)i(a*)byte, ...
Instance structure tag / jump-struct instantiation for
arrays with primitive element type
<argtypes> follows the form used in the .class file format, escaped as
per JNI.
----------------------------------------------------------------------
The 'this' argument to each instance method is of type java.lang.Object,
so as not to unnecessarily complicate the implementation of interfaces.
Narrowing reference conversions are just a struct member access:
struct typea { ... } *vara;
struct typeb { struct typea super; ... } *varb;
...
vara = &(varb->super)
Widening reference conversions involve some complex and nonstandard,
but hopefully fairly portable, pointer arithmetic. We assume that all
other type sizes and offsets can be represented in units of sizeof(char).
... check that the widening is valid ...
varb = (struct typeb *) (((char *) vara)
- ( ( (char *) &(((struct typeb *) 0)->super) )
- (char *) 0) );
In practice, this will be equivalent to a simple cast between pointer
types. If there's padding at the beginning of the struct, though,
the above code should correctly offset the new pointer to take this
into account.
When adding garbage collection, it will probably be necessary to revert
to using plain casts between pointer types, and adding code to the C
initialisation section to check that there is no padding at the start
of any struct.
[Additional: I recently discovered that the C standard prohibits a
compiler from placing padding at the start of a struct, or reordering
a struct's members. This means that it should be perfectly all right
to revert to using plain casts without any additional checks.]
----------------------------------------------------------------------
The parse tree undergoes a fair bit of processing. Here's some
documentation on the stmt and expr parts of the tree:
struct stmt contains:
tag: says what kind of statement this is
var: for variable declarations, the type, the names declared, and the
corresponding initialisers.
expr: an expression, or list of expressions
stmt[1234]: sub-statements
catch: for a try statement, a list of catchclauses
rest: the next statement in the block
The statements in a block are chained in the correct order through their
'rest' pointers. This is in contrast to all the other linked lists in the
tree, which are, as a rule, built in reverse order and not subsequently
fixed up.
Tags are:
Localvar: 'var' indicates what variables are defined
If: if 'expr' is true, execute 'stmt1', otherwise execute 'stmt2'
While: while 'expr' is true, execute 'stmt1'
For: execute 'stmt1' first, then, while 'expr' is true, execute the
block 'stmt3', then the update statement 'stmt2'. 'stmt1' and
'stmt2' are NO LONGER in reverse execution order!
Block: execute the block 'stmt1'
Empty: No-op
Exprstmt: evaluate 'expr'
Switch: evaluate 'expr', then jump to the appropriate Case in 'stmt1'
Case: 'expr' is the label
Default: no content
Do: execute 'stmt1' until 'expr' is false
Break, Cont: no content
Return: return from method. If 'expr' != null, return its value.
Throw: throws 'expr'
Try: execute block 'stmt1', handle exceptions using 'catch' clauses,
if any, then execute finaliser 'stmt2'.
struct expr contains:
tag: says what kind of expr this is
exp[123]: subexpressions of ths expression
type: this expression's type
name:
integ:
str:
rest: the next expression in a list
Tags are:
Prim: unused
NullString: the value of 'exp1', unless it is null, in which case "null".
Localacc: access local variable 'str'
This, Nulllit: no data
Intlit, Longlit, Boollit, Charlit: literal value 'integ'
Stringlit: literal value 'str', or string pool index 'integ'
Floatlit, Doublit: literal; value not currently stored.
New: create a new object of type 'type'. If it's an array, the
dimension exprs are 'exp1'. Otherwise, the constructor args are
'exp2'.
Primfield: access the field named by 'str' in expression 'exp1'
Meth: call method 'str' of 'exp1', with arguments 'exp2'. 'integ' is
0 for instance methods, 1 for static methods.
Super: call superclass method named 'str' with arguments 'exp2' if
'integ' is 0, otherwise access superclass field 'str'
Array: index by 'exp2' into array 'exp1'
Name: any ExpressionName is initially parsed to this type of expr,
the ExpressionName being placed in 'name'. A later stage of
processing turns most ExpressionNames into other kinds of exprs;
the only ones being left as Names are TypeNames.
Postinc, Postdec: 'exp1' ++ --
Plus, Minus, Preinc, Predec, Comp, Not: + - ++ -- ~ ! 'exp1'
Cast: convert 'exp1' to type 'type'
Mult, Div, Rem, Add, Sub, Lshift, Rshift, Urshift, Lt, Gt, Leq, Geq:
'exp1' * / % + - << >> >>> < > <= >= 'exp2'
Inst: 'exp1' instanceof 'type'. The name from 'type' is stashed in
'name' when the type decorator fills in 'type'.
Eq, Neq, And, Xor, Or, Condand, Condor: relational operators:
'exp1' == != & ^ | && || 'exp2'
Cond: exp1 ? exp2 : exp3
Assign: evaluate 'exp2' then assign the result to 'exp1'
Multass, Divass, Remass, Addass, Subass, Lshiftass, Rshiftass,
Urshiftass, Andass, Xorass, Orass: same, but combined with an operator
Arrayinit: create an array from the list of expressions 'exp1', whose
length is `integ'.
|