1 cananian 1.1.2.1  // StubCode.java, created Sat Oct 23 15:33:33 1999 by cananian
  2 cananian 1.1.2.1  // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1  package harpoon.Backend.Runtime1;
  5 cananian 1.1.2.1  
  6 cananian 1.1.2.1  import harpoon.Backend.Generic.Frame;
  7 cananian 1.1.2.1  import harpoon.Backend.Maps.NameMap;
  8 cananian 1.1.2.1  import harpoon.ClassFile.HClass;
  9 cananian 1.1.2.1  import harpoon.ClassFile.HCode;
 10 cananian 1.1.2.1  import harpoon.ClassFile.HCodeElement;
 11 cananian 1.1.2.1  import harpoon.ClassFile.HMethod;
 12 cananian 1.1.2.9  import harpoon.IR.Tree.DerivationGenerator;
 13 cananian 1.1.2.1  import harpoon.IR.Tree.Bop;
 14 cananian 1.1.2.1  import harpoon.IR.Tree.Exp;
 15 cananian 1.1.2.1  import harpoon.IR.Tree.ExpList;
 16 cananian 1.1.2.1  import harpoon.IR.Tree.Stm;
 17 cananian 1.1.2.1  import harpoon.IR.Tree.Tree;
 18 cananian 1.1.2.8  import harpoon.IR.Tree.TreeDerivation;
 19 cananian 1.1.2.1  import harpoon.IR.Tree.Type;
 20 cananian 1.1.2.1  import harpoon.IR.Tree.BINOP;
 21 cananian 1.1.2.1  import harpoon.IR.Tree.CJUMP;
 22 cananian 1.1.2.1  import harpoon.IR.Tree.CONST;
 23 cananian 1.1.2.1  import harpoon.IR.Tree.LABEL;
 24 cananian 1.1.2.1  import harpoon.IR.Tree.MEM;
 25 cananian 1.1.2.1  import harpoon.IR.Tree.METHOD;
 26 cananian 1.1.2.1  import harpoon.IR.Tree.MOVE;
 27 cananian 1.1.2.1  import harpoon.IR.Tree.NAME;
 28 cananian 1.1.2.1  import harpoon.IR.Tree.NATIVECALL;
 29 cananian 1.1.2.1  import harpoon.IR.Tree.RETURN;
 30 cananian 1.1.2.1  import harpoon.IR.Tree.SEGMENT;
 31 cananian 1.1.2.1  import harpoon.IR.Tree.TEMP;
 32 cananian 1.1.2.1  import harpoon.IR.Tree.THROW;
 33 cananian 1.1.2.1  import harpoon.Temp.Label;
 34 cananian 1.1.2.1  import harpoon.Temp.Temp;
 35 cananian 1.1.2.1  
 36 cananian 1.1.2.2  import java.lang.reflect.Modifier;
 37 cananian 1.1.2.2  
 38 cananian 1.1.2.1  import java.util.ArrayList;
 39 cananian 1.1.2.1  import java.util.List;
 40 cananian 1.1.2.1  /**
 41 cananian 1.1.2.1   * <code>StubCode</code> is used to generate non-canonical tree code
 42 cananian 1.1.2.1   * stubs for native methods.  That is, a <code>StubCode</code> is a
 43 cananian 1.1.2.1   * thunk from runtime-native methods to the JNI interface which
 44 cananian 1.1.2.1   * C-code "native methods" conform to.<p>
 45 cananian 1.1.2.1   * <code>StubCode</code> will generate a thunk for any old method you
 46 cananian 1.1.2.1   * give to its constructor.  It is the job of the
 47 cananian 1.1.2.1   * <code>nativeTreeCodeFactory()</code> in <code>Runtime1.Runtime</code>
 48 cananian 1.1.2.1   * to weed out native from non-native methods, give the proper ones
 49 cananian 1.1.2.1   * to <code>StubCode</code>, and do the right thing with the stubs that
 50 cananian 1.1.2.1   * <code>StubCode</code> makes.
 51 cananian 1.1.2.1   * 
 52 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 53 cananian 1.3       * @version $Id: StubCode.java,v 1.3 2003/10/21 02:11:02 cananian Exp $
 54 cananian 1.1.2.1   */
 55 cananian 1.1.2.1  public class StubCode extends harpoon.IR.Tree.TreeCode {
 56 cananian 1.1.2.1      final TreeBuilder m_tb;
 57 cananian 1.1.2.1      final NameMap m_nm;
 58 cananian 1.1.2.1      final int EXC_OFFSET;
 59 cananian 1.1.2.1      final int REF_OFFSET;
 60 cananian 1.1.2.9      final DerivationGenerator m_dg;
 61 cananian 1.1.2.1  
 62 cananian 1.1.2.13     /** Creates a <code>StubCode</code>.
 63 cananian 1.1.2.13      * @param method The method for which to generate code.
 64 cananian 1.1.2.13      * @param frame The frame for the generated code.
 65 cananian 1.1.2.16      */
 66 cananian 1.1.2.16     public StubCode(HMethod method, Frame frame) {
 67 cananian 1.1.2.9          super(method, null, frame, new DerivationGenerator());
 68 cananian 1.1.2.20         this.m_nm = frame.getRuntime().getNameMap();
 69 cananian 1.1.2.20         this.m_tb = (TreeBuilder) frame.getRuntime().getTreeBuilder();
 70 cananian 1.1.2.12         // keep this synchronized with struct FNI_Thread_State in
 71 cananian 1.1.2.12         // Runtime/include/jni-private.h and TreeBuilder._call_FNI_Monitor()
 72 cananian 1.1.2.1          this.EXC_OFFSET = 1 * m_tb.POINTER_SIZE;
 73 cananian 1.1.2.1          this.REF_OFFSET = 3 * m_tb.POINTER_SIZE;
 74 cananian 1.1.2.9          this.m_dg = (DerivationGenerator) getTreeDerivation();
 75 cananian 1.1.2.1          this.tree = buildStub(method);
 76 cananian 1.1.2.1      }
 77 cananian 1.1.2.1  
 78 cananian 1.1.2.9      // here is the real stub builder code.
 79 cananian 1.1.2.1      Tree buildStub(HMethod method) {
 80 cananian 1.1.2.9          final HClass HCcls = frame.getLinker().forName("java.lang.Class");
 81 cananian 1.1.2.9          final HClass HCthw = frame.getLinker().forName("java.lang.Throwable");
 82 cananian 1.1.2.9  
 83 cananian 1.1.2.1          List stmlist = new ArrayList();
 84 cananian 1.1.2.1          // segment change
 85 cananian 1.1.2.1          stmlist.add(new SEGMENT(tf, null, SEGMENT.CODE));
 86 cananian 1.1.2.1          // add method header.
 87 cananian 1.1.2.1          // (remember that first method parameter in tree form is the
 88 cananian 1.1.2.1          //  'return exception address')
 89 cananian 1.1.2.1          HClass[] paramTypes = method.getParameterTypes();
 90 cananian 1.1.2.5          if (!method.isStatic()) {// add 'this' parameter for non-static methods
 91 cananian 1.1.2.5              HClass[] nparamTypes = new HClass[paramTypes.length+1];
 92 cananian 1.1.2.5              nparamTypes[0] = method.getDeclaringClass();
 93 cananian 1.1.2.5              System.arraycopy(paramTypes,0,nparamTypes,1,paramTypes.length);
 94 cananian 1.1.2.5              paramTypes = nparamTypes;
 95 cananian 1.1.2.5          }
 96 cananian 1.1.2.1          Temp[] paramTemps = new Temp[paramTypes.length+1];
 97 cananian 1.1.2.1          TEMP[] paramTEMPs = new TEMP[paramTypes.length+1];
 98 cananian 1.1.2.1          paramTemps[0] = new Temp(tf.tempFactory(), "rexaddr");
 99 cananian 1.1.2.9          paramTEMPs[0] = _TEMP(tf, null, HClass.Void, paramTemps[0]);
100 cananian 1.1.2.1          for (int i=0; i<paramTypes.length; i++) {
101 cananian 1.1.2.1              paramTemps[i+1] = new Temp(tf.tempFactory(), "param"+i);
102 cananian 1.1.2.9              paramTEMPs[i+1] = _TEMP(tf, null, paramTypes[i], paramTemps[i+1]);
103 cananian 1.1.2.1          }
104 cananian 1.1.2.15         int rtype = (method.getReturnType()==HClass.Void) ? -1 :
105 cananian 1.1.2.15             class2type(method.getReturnType());
106 cananian 1.1.2.15         stmlist.add(new METHOD(tf,null,m_nm.label(method), rtype, paramTEMPs));
107 cananian 1.1.2.11         // get JNIEnv * (which is thread-local)
108 cananian 1.1.2.1          Temp envT = new Temp(tf.tempFactory(), "env");
109 cananian 1.1.2.11         stmlist.add(new NATIVECALL
110 cananian 1.1.2.11                     (tf, null,
111 cananian 1.1.2.11                      _TEMP(tf, null, HClass.Void, envT) /*retval*/,
112 cananian 1.1.2.11                      _NAME(tf, null, HClass.Void,
113 cananian 1.1.2.11                            new Label(m_nm.c_function_name("FNI_GetJNIEnv"))),
114 cananian 1.1.2.11                      null/* no args*/));
115 cananian 1.1.2.11 
116 cananian 1.1.2.1          // reset the exception field in the thread state.
117 cananian 1.1.2.12         /* CSA: i don't think we need to do this -- we clear the exception
118 cananian 1.1.2.12          * when we return. [mar-26-2000]
119 cananian 1.1.2.1          stmlist.add(new MOVE(tf, null,
120 cananian 1.1.2.9                               _MEM(tf, null, HClass.Void,
121 cananian 1.1.2.1                                       new BINOP(tf, null, Type.POINTER, Bop.ADD,
122 cananian 1.1.2.9                                                 _TEMP(tf, null, HClass.Void,
123 cananian 1.1.2.1                                                          envT),
124 cananian 1.1.2.1                                                 new CONST(tf, null, EXC_OFFSET)
125 cananian 1.1.2.1                                                 )),
126 cananian 1.1.2.1                               new CONST(tf, null))); // set to null.
127 cananian 1.1.2.12         */
128 cananian 1.1.2.1          // save the top of the local ref stack (so we can restore it later)
129 cananian 1.1.2.1          Temp refT = new Temp(tf.tempFactory(), "lref");
130 cananian 1.1.2.1          stmlist.add(new MOVE(tf, null,
131 cananian 1.1.2.9                               _TEMP(tf, null, HClass.Void, refT),
132 cananian 1.1.2.9                               _MEM(tf, null, HClass.Void,
133 cananian 1.1.2.1                                       new BINOP(tf, null, Type.POINTER, Bop.ADD,
134 cananian 1.1.2.9                                                 _TEMP(tf, null, HClass.Void,
135 cananian 1.1.2.1                                                          envT),
136 cananian 1.1.2.1                                                 new CONST(tf, null, REF_OFFSET)
137 cananian 1.1.2.1                                                 ))));
138 cananian 1.1.2.1          // wrap objects in parameter list
139 cananian 1.1.2.1          for (int i=0; i<paramTypes.length; i++)
140 cananian 1.1.2.19             if (!paramTypes[i].isPrimitive()) {
141 cananian 1.1.2.19                 Temp wrapped = new Temp(paramTemps[i+1]);
142 cananian 1.1.2.1                  stmlist.add(new NATIVECALL
143 cananian 1.1.2.1                              (tf, null,
144 cananian 1.1.2.9                               _TEMP
145 cananian 1.1.2.19                              (tf, null, HClass.Void, wrapped),
146 cananian 1.1.2.9                               _NAME
147 cananian 1.1.2.9                               (tf, null, HClass.Void,
148 cananian 1.1.2.10                               new Label(m_nm.c_function_name
149 cananian 1.1.2.10                                         ("FNI_NewLocalRef"))),
150 cananian 1.1.2.9                               new ExpList
151 cananian 1.1.2.9                                (_TEMP(tf, null, HClass.Void, envT),
152 cananian 1.1.2.1                                 new ExpList
153 cananian 1.1.2.9                                 (_TEMP(tf, null, paramTypes[i],paramTemps[i+1]),
154 cananian 1.1.2.1                                  null))));
155 cananian 1.1.2.19                 // after this point, use wrapped temp
156 cananian 1.1.2.19                 paramTypes[i] = HClass.Void;
157 cananian 1.1.2.19                 paramTemps[i+1] = wrapped;
158 cananian 1.1.2.19             }
159 cananian 1.1.2.1          // wrap a class object pointer for static methods.
160 cananian 1.1.2.1          Temp classT = null;
161 cananian 1.1.2.1          if (method.isStatic()) {
162 cananian 1.1.2.1              classT = new Temp(tf.tempFactory(), "jclass");
163 cananian 1.1.2.1              stmlist.add(new NATIVECALL
164 cananian 1.1.2.1                          (tf, null,
165 cananian 1.1.2.9                           _TEMP
166 cananian 1.1.2.9                           (tf,null,HClass.Void, classT),
167 cananian 1.1.2.9                           _NAME
168 cananian 1.1.2.10                          (tf,null,HClass.Void, new Label(m_nm.c_function_name
169 cananian 1.1.2.10                                                          ("FNI_NewLocalRef"))),
170 cananian 1.1.2.1                           new ExpList
171 cananian 1.1.2.9                           (_TEMP(tf, null, HClass.Void, envT),
172 cananian 1.1.2.1                            new ExpList
173 cananian 1.1.2.9                            (_NAME(tf, null, HCcls,
174 cananian 1.1.2.1                                      m_nm.label(method.getDeclaringClass(),
175 cananian 1.1.2.1                                                 "classobj")),
176 cananian 1.1.2.1                             null))));
177 cananian 1.1.2.1          }
178 cananian 1.1.2.14         // if this method is synchronized, lock the object.
179 cananian 1.1.2.14         Temp lockT = (classT != null) ? classT : paramTemps[1];
180 cananian 1.1.2.17         emitMonitorLockUnlock(stmlist, envT, lockT, true/*lock*/);
181 cananian 1.1.2.1          // make the native call's parameters, in reverse order
182 cananian 1.1.2.1          ExpList jniParams = null;
183 cananian 1.1.2.1          for (int i=paramTypes.length-1; i>=0; i--)
184 cananian 1.1.2.1              jniParams = new ExpList
185 cananian 1.1.2.9                  (_TEMP(tf, null, paramTypes[i], paramTemps[i+1]),
186 cananian 1.1.2.1                   jniParams);
187 cananian 1.1.2.1          // second parameter is either a jclass for a static method
188 cananian 1.1.2.5          // or an (already added) 'this' object
189 cananian 1.1.2.1          if (classT != null)
190 cananian 1.1.2.9              jniParams = new ExpList(_TEMP(tf, null, HCcls, classT),
191 cananian 1.1.2.1                                      jniParams);
192 cananian 1.1.2.1          // first parameter is the JNIEnv *
193 cananian 1.1.2.9          jniParams = new ExpList(_TEMP(tf, null, HClass.Void, envT),
194 cananian 1.1.2.1                                  jniParams);
195 cananian 1.1.2.1          // Do the call.
196 cananian 1.1.2.1          Temp retT = null;
197 cananian 1.1.2.19         HClass rettype = method.getReturnType();
198 cananian 1.1.2.19         if (rettype!=HClass.Void) {
199 cananian 1.1.2.1              retT = new Temp(tf.tempFactory(), "retval");
200 cananian 1.1.2.19             if (!rettype.isPrimitive()) rettype=HClass.Void;//retval is wrapped
201 cananian 1.1.2.19         }
202 cananian 1.1.2.1          stmlist.add(new NATIVECALL(tf, null,
203 cananian 1.1.2.1                                     (retT==null) ? null :
204 cananian 1.1.2.19                                    _TEMP(tf, null, rettype, retT),
205 cananian 1.1.2.9                                     _NAME(tf, null, HClass.Void,
206 cananian 1.1.2.10                                          new Label(m_nm.c_function_name
207 cananian 1.1.2.10                                                    (jniMangle(method)))),
208 cananian 1.1.2.1                                     jniParams));
209 cananian 1.1.2.1          // now clean up afterward: check for exceptions, etc.
210 cananian 1.1.2.1          Temp excT = new Temp(tf.tempFactory(), "excval");
211 cananian 1.1.2.1          stmlist.add(new MOVE(tf, null,
212 cananian 1.1.2.9                               _TEMP(tf, null, HClass.Void, excT),
213 cananian 1.1.2.9                               _MEM(tf, null, HClass.Void,
214 cananian 1.1.2.1                                       new BINOP(tf, null, Type.POINTER, Bop.ADD,
215 cananian 1.1.2.9                                                 _TEMP(tf, null, HClass.Void,
216 cananian 1.1.2.1                                                          envT),
217 cananian 1.1.2.1                                                 new CONST(tf, null, EXC_OFFSET)
218 cananian 1.1.2.1                                                 ))));
219 cananian 1.1.2.1          Label no_exceptions = new Label();
220 cananian 1.1.2.1          Label yes_exceptions = new Label();
221 cananian 1.1.2.1          stmlist.add(new CJUMP(tf, null,
222 cananian 1.1.2.1                                new BINOP(tf, null, Type.POINTER, Bop.CMPEQ,
223 cananian 1.1.2.9                                          _TEMP(tf, null, HClass.Void, excT),
224 cananian 1.1.2.1                                          new CONST(tf, null)/*null pointer*/),
225 cananian 1.1.2.1                                no_exceptions, yes_exceptions));
226 cananian 1.1.2.1          // no exceptions occurred.  unwrap return value and return from stub.
227 cananian 1.1.2.1          stmlist.add(new LABEL(tf, null, no_exceptions, false));
228 cananian 1.1.2.19         emitMonitorLockUnlock(stmlist, envT, lockT, false/*unlock*/);
229 cananian 1.1.2.1          Exp retexp;
230 cananian 1.1.2.1          if (retT==null)
231 cananian 1.1.2.1              retexp = new CONST(tf, null);
232 cananian 1.1.2.1          else {
233 cananian 1.1.2.19             rettype = method.getReturnType();//reset to unwrapped type.
234 cananian 1.1.2.19             if (!rettype.isPrimitive()) {
235 cananian 1.1.2.19                 Temp unwrapped = new Temp(retT);
236 cananian 1.1.2.1                  stmlist.add(new NATIVECALL(tf, null,
237 cananian 1.1.2.19                                            _TEMP(tf, null, rettype, unwrapped),
238 cananian 1.1.2.9                                             _NAME(tf, null, HClass.Void,
239 cananian 1.1.2.10                                                  new Label(m_nm.c_function_name
240 cananian 1.1.2.10                                                            ("FNI_Unwrap"))),
241 cananian 1.1.2.1                                             new ExpList
242 cananian 1.1.2.9                                             (_TEMP(tf, null, HClass.Void, retT),
243 cananian 1.1.2.9                                              null)
244 cananian 1.1.2.1                                             ));
245 cananian 1.1.2.19                 retT = unwrapped; // after this point, use unwrapped temp
246 cananian 1.1.2.19             }
247 cananian 1.1.2.9              retexp = _TEMP(tf, null, rettype, retT);
248 cananian 1.1.2.1          }
249 cananian 1.1.2.1          emitFreeLocals(stmlist, envT, refT);
250 cananian 1.1.2.1          stmlist.add(new RETURN(tf, null, retexp));
251 cananian 1.1.2.1          // an exception occurred.  unwrap exception value and throw it.
252 cananian 1.1.2.6          // (don't forget to clear the exception before we invoke any more
253 cananian 1.1.2.6          //  jni functions!)
254 cananian 1.1.2.1          stmlist.add(new LABEL(tf, null, yes_exceptions, false));
255 cananian 1.1.2.6          stmlist.add(new NATIVECALL(tf, null, null,
256 cananian 1.1.2.9                                     _NAME(tf, null, HClass.Void,
257 cananian 1.1.2.10                                             new Label(m_nm.c_function_name
258 cananian 1.1.2.10                                                       ("FNI_ExceptionClear"))),
259 cananian 1.1.2.6                                     new ExpList
260 cananian 1.1.2.9                                     (_TEMP(tf, null, HClass.Void, envT),
261 cananian 1.1.2.6                                      null)
262 cananian 1.1.2.6                                     ));
263 cananian 1.1.2.19         emitMonitorLockUnlock(stmlist, envT, lockT, false/*unlock*/);
264 cananian 1.1.2.19         Temp unwrapped = new Temp(excT);
265 cananian 1.1.2.1          stmlist.add(new NATIVECALL(tf, null,
266 cananian 1.1.2.19                                    _TEMP(tf, null, HCthw, unwrapped),
267 cananian 1.1.2.9                                     _NAME(tf, null, HClass.Void,
268 cananian 1.1.2.10                                             new Label(m_nm.c_function_name
269 cananian 1.1.2.10                                                       ("FNI_Unwrap"))),
270 cananian 1.1.2.1                                     new ExpList
271 cananian 1.1.2.9                                     (_TEMP(tf, null, HClass.Void, excT),
272 cananian 1.1.2.1                                      null)
273 cananian 1.1.2.1                                     ));
274 cananian 1.1.2.19         excT = unwrapped; // after this point, use unwrapped temp
275 cananian 1.1.2.1          emitFreeLocals(stmlist, envT, refT);
276 cananian 1.1.2.1          stmlist.add(new THROW(tf, null,
277 cananian 1.1.2.9                                _TEMP(tf, null, HCthw, excT),
278 cananian 1.1.2.9                                _TEMP(tf, null, HClass.Void, paramTemps[0])
279 cananian 1.1.2.1                                ));
280 cananian 1.1.2.1          return Stm.toStm(stmlist);
281 cananian 1.1.2.14     }
282 cananian 1.1.2.14     private void emitMonitorLockUnlock(List stmlist, Temp envT,
283 cananian 1.1.2.17                                        Temp lockT, boolean isLock) {
284 cananian 1.1.2.14         // if this method is not synchronized, skip this.
285 cananian 1.1.2.14         if (!Modifier.isSynchronized(getMethod().getModifiers())) return;
286 cananian 1.1.2.14         // okay, emit native call to FNI_MonitorEnter/Exit().
287 cananian 1.1.2.14         Temp discardT = new Temp(tf.tempFactory(), "discard");
288 cananian 1.1.2.14         stmlist.add(new NATIVECALL
289 cananian 1.1.2.14                     (tf, null,
290 cananian 1.1.2.14                      _TEMP(tf, null, HClass.Int, discardT)/* retval*/,
291 cananian 1.1.2.14                      _NAME(tf, null, HClass.Void,
292 cananian 1.1.2.14                            new Label(m_nm.c_function_name
293 cananian 1.1.2.14                                      (isLock ?
294 cananian 1.1.2.14                                       "FNI_MonitorEnter":"FNI_MonitorExit"))),
295 cananian 1.1.2.14                      new ExpList(_TEMP(tf, null, HClass.Void, envT),
296 cananian 1.1.2.17                                  // note type of lockT is HClass.Void because
297 cananian 1.1.2.17                                  // it has been wrapped.
298 cananian 1.1.2.17                                  new ExpList(_TEMP(tf, null, HClass.Void,
299 cananian 1.1.2.17                                                    lockT),  null))));
300 cananian 1.1.2.1      }
301 cananian 1.1.2.1      private void emitFreeLocals(List stmlist, Temp envT, Temp refT) {
302 cananian 1.1.2.1          stmlist.add(new NATIVECALL
303 cananian 1.1.2.1                      (tf, null, null, // free local references
304 cananian 1.1.2.9                       _NAME(tf, null, HClass.Void,
305 cananian 1.1.2.10                               new Label(m_nm.c_function_name
306 cananian 1.1.2.10                                         ("FNI_DeleteLocalRefsUpTo"))),
307 cananian 1.1.2.9                       new ExpList(_TEMP(tf, null, HClass.Void, envT),
308 cananian 1.1.2.9                       new ExpList(_TEMP(tf, null, HClass.Void, refT),
309 cananian 1.1.2.4                                   null))));
310 cananian 1.1.2.1      }
311 cananian 1.1.2.1  
312 cananian 1.1.2.9      private TEMP _TEMP(TreeFactory tf, HCodeElement src,
313 cananian 1.1.2.9                         HClass type, Temp temp) {
314 cananian 1.1.2.9          TEMP result = new TEMP(tf, src, class2type(type), temp);
315 cananian 1.1.2.9          m_dg.putTypeAndTemp(result, type, temp);
316 cananian 1.1.2.9          return result;
317 cananian 1.1.2.9      }
318 cananian 1.1.2.9      private MEM _MEM(TreeFactory tf, HCodeElement src,
319 cananian 1.1.2.9                       HClass type, Exp exp) {
320 cananian 1.1.2.9          MEM result = new MEM(tf, src, class2type(type), exp);
321 cananian 1.1.2.9          m_dg.putType(result, type);
322 cananian 1.1.2.9          return result;
323 cananian 1.1.2.9      }
324 cananian 1.1.2.9      private NAME _NAME(TreeFactory tf, HCodeElement src,
325 cananian 1.1.2.9                         HClass type, Label label) {
326 cananian 1.1.2.9          NAME result = new NAME(tf, src, label);
327 cananian 1.1.2.9          m_dg.putType(result, type);
328 cananian 1.1.2.9          return result;
329 cananian 1.1.2.9      }
330 cananian 1.1.2.9      
331 cananian 1.1.2.1      private static int class2type(HClass hc) {
332 cananian 1.1.2.1          if (!hc.isPrimitive()) return Type.POINTER;
333 cananian 1.1.2.9          if (hc==HClass.Void) return Type.POINTER;
334 cananian 1.1.2.1          if (hc==HClass.Boolean || hc==HClass.Byte || hc==HClass.Char ||
335 cananian 1.1.2.1              hc==HClass.Int || hc==HClass.Short) return Type.INT;
336 cananian 1.1.2.1          if (hc==HClass.Double) return Type.DOUBLE;
337 cananian 1.1.2.1          if (hc==HClass.Float) return Type.FLOAT;
338 cananian 1.1.2.1          if (hc==HClass.Long) return Type.LONG;
339 cananian 1.1.2.1          throw new Error("Unknown primitive type: "+hc);
340 cananian 1.1.2.1      }
341 cananian 1.1.2.1  
342 cananian 1.1.2.1      private static String jniMangle(HMethod m) {
343 cananian 1.1.2.2          // jni sez use short name unless two native methods would use the
344 cananian 1.1.2.2          // same short name.  So, let's check that, shall we?
345 cananian 1.1.2.2          boolean useShort = true;
346 cananian 1.1.2.2          HMethod[] allm = m.getDeclaringClass().getMethods();
347 cananian 1.1.2.2          for (int i=0; i<allm.length; i++)
348 cananian 1.1.2.2              if (Modifier.isNative(allm[i].getModifiers()) &&
349 cananian 1.1.2.2                  allm[i].getName().equals(m.getName()) &&
350 cananian 1.1.2.2                  !allm[i].equals(m))
351 cananian 1.1.2.2                  useShort = false;
352 cananian 1.1.2.10         String mangled = "Java_" +
353 cananian 1.1.2.2              encode(m.getDeclaringClass().getName()) +
354 cananian 1.1.2.2              "_" +
355 cananian 1.1.2.2              encode(m.getName());
356 cananian 1.1.2.2          if (!useShort) {
357 cananian 1.1.2.2              String desc = m.getDescriptor();
358 cananian 1.1.2.2              mangled += "__" +
359 cananian 1.1.2.2                  encode(desc.substring(1, desc.lastIndexOf(')')));
360 cananian 1.1.2.2          }
361 cananian 1.1.2.2          return mangled;
362 cananian 1.1.2.2      }
363 cananian 1.1.2.2  
364 cananian 1.1.2.2      //-------- CODE BELOW THIS LINE WAS COPIED FROM DefaultNameMap.java ----
365 cananian 1.1.2.2      // (so if you find a bug here, fix it there, too!)
366 cananian 1.1.2.2  
367 cananian 1.1.2.2      /** Apply the JNI-standard unicode-to-C encoding. */
368 cananian 1.1.2.2      private static String encode(String s) {
369 cananian 1.1.2.2          StringBuffer sb = new StringBuffer();
370 cananian 1.1.2.2          for(int i=0; i<s.length(); i++) {
371 cananian 1.1.2.2              switch(s.charAt(i)) {
372 cananian 1.1.2.2              case '.':
373 cananian 1.1.2.2              case '/':
374 cananian 1.1.2.2                  sb.append("_");
375 cananian 1.1.2.2                  break;
376 cananian 1.1.2.2              case '_':
377 cananian 1.1.2.2                  sb.append("_1");
378 cananian 1.1.2.2                  break;
379 cananian 1.1.2.2              case ';':
380 cananian 1.1.2.2                  sb.append("_2");
381 cananian 1.1.2.2                  break;
382 cananian 1.1.2.2              case '[':
383 cananian 1.1.2.2                  sb.append("_3");
384 cananian 1.1.2.2                  break;
385 cananian 1.1.2.2              default:
386 cananian 1.1.2.2                  if ((s.charAt(i) >= 'a' &&
387 cananian 1.1.2.2                       s.charAt(i) <= 'z') ||
388 cananian 1.1.2.2                      (s.charAt(i) >= 'A' &&
389 cananian 1.1.2.2                       s.charAt(i) <= 'Z') ||
390 cananian 1.1.2.2                      (s.charAt(i) >= '0' &&
391 cananian 1.1.2.2                       s.charAt(i) <= '9')) {
392 cananian 1.1.2.2                      sb.append(s.charAt(i));
393 cananian 1.1.2.2                  } else {
394 cananian 1.1.2.2                      sb.append("_0" + toHex(s.charAt(i), 4));
395 cananian 1.1.2.2                  }
396 cananian 1.1.2.2                  break;
397 cananian 1.1.2.2              }
398 cananian 1.1.2.2          }
399 cananian 1.1.2.2          return sb.toString();
400 cananian 1.1.2.2      }
401 cananian 1.1.2.2      /** Convert the integer <code>value</code> into a hexadecimal 
402 cananian 1.1.2.2       *  string with at least <code>num_digits</code> digits. */
403 cananian 1.1.2.2      private static String toHex(int value, int num_digits) {
404 cananian 1.1.2.2          String hexval= // javah puts all hex vals in lowercase.
405 cananian 1.1.2.2              Integer.toHexString(value).toLowerCase();
406 cananian 1.1.2.2          while(hexval.length()<num_digits) hexval="0"+hexval;
407 cananian 1.1.2.2          return hexval;
408 cananian 1.1.2.1      }
409 cananian 1.2      }