1 /* src/vm/linker.c - class linker functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: linker.c 2279 2005-04-12 19:50:04Z twisti $
41 #include "mm/memory.h"
42 #include "native/native.h"
43 #include "vm/builtin.h"
45 #include "vm/classcache.h"
46 #include "vm/exceptions.h"
47 #include "vm/loader.h"
48 #include "vm/options.h"
49 #include "vm/resolve.h"
50 #include "vm/statistics.h"
51 #include "vm/jit/codegen.inc.h"
54 /* global variables ***********************************************************/
56 static s4 interfaceindex; /* sequential numbering of interfaces */
60 /* primitivetype_table *********************************************************
62 Structure for primitive classes: contains the class for wrapping
63 the primitive type, the primitive class, the name of the class for
64 wrapping, the one character type signature and the name of the
67 CAUTION: Don't change the order of the types. This table is indexed
68 by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
70 *******************************************************************************/
72 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
73 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
74 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
75 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
76 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
77 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
78 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
79 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
80 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
81 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
82 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
83 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
87 /* private functions **********************************************************/
89 static bool link_primitivetype_table(void);
90 static classinfo *link_class_intern(classinfo *c);
91 static arraydescriptor *link_array(classinfo *c);
92 static void linker_compute_class_values(classinfo *c);
93 static void linker_compute_subclasses(classinfo *c);
94 static void linker_addinterface(classinfo *c, classinfo *ic);
95 static s4 class_highestinterface(classinfo *c);
98 /* linker_init *****************************************************************
100 Initializes the linker subsystem.
102 *******************************************************************************/
104 bool linker_init(void)
106 /* reset interface index */
110 /* link important system classes */
112 if (!link_class(class_java_lang_Object))
115 if (!link_class(class_java_lang_String))
118 if (!link_class(class_java_lang_Cloneable))
121 if (!link_class(class_java_io_Serializable))
125 /* link classes for wrapping primitive types */
127 if (!link_class(class_java_lang_Void))
130 if (!link_class(class_java_lang_Boolean))
133 if (!link_class(class_java_lang_Byte))
136 if (!link_class(class_java_lang_Character))
139 if (!link_class(class_java_lang_Short))
142 if (!link_class(class_java_lang_Integer))
145 if (!link_class(class_java_lang_Long))
148 if (!link_class(class_java_lang_Float))
151 if (!link_class(class_java_lang_Double))
155 /* load some other important classes */
157 if (!link_class(class_java_lang_Class))
160 if (!link_class(class_java_lang_ClassLoader))
163 if (!link_class(class_java_lang_SecurityManager))
166 if (!link_class(class_java_lang_System))
170 if (!link_class(class_java_util_Vector))
174 /* create pseudo classes used by the typechecker */
176 /* pseudo class for Arraystubs (extends java.lang.Object) */
178 pseudo_class_Arraystub =
179 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
180 pseudo_class_Arraystub->loaded = true;
181 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
182 pseudo_class_Arraystub->interfacescount = 2;
183 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
184 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
185 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
186 if (!classcache_store(NULL, pseudo_class_Arraystub))
187 panic("could not cache pseudo_class_Arraystub");
189 if (!link_class(pseudo_class_Arraystub))
192 /* pseudo class representing the null type */
194 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
195 pseudo_class_Null->loaded = true;
196 pseudo_class_Null->super.cls = class_java_lang_Object;
197 if (!classcache_store(NULL, pseudo_class_Null))
198 panic("could not cache pseudo_class_Null");
200 if (!link_class(pseudo_class_Null))
203 /* pseudo class representing new uninitialized objects */
205 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
206 pseudo_class_New->loaded = true;
207 pseudo_class_New->linked = true; /* XXX is this allright? */
208 pseudo_class_New->super.cls = class_java_lang_Object;
209 if (!classcache_store(NULL,pseudo_class_New))
210 panic("could not cache pseudo_class_New");
212 /* create classes representing primitive types */
214 if (!link_primitivetype_table())
218 /* Correct vftbl-entries (retarded loading and linking of class */
219 /* java/lang/String). */
221 stringtable_update();
227 /* link_primitivetype_table ****************************************************
229 Create classes representing primitive types.
231 *******************************************************************************/
233 static bool link_primitivetype_table(void)
238 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
240 if (!primitivetype_table[i].name)
243 /* create primitive class */
244 c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
245 c->classUsed = NOTUSED; /* not used initially CO-RT */
248 /* prevent loader from loading primitive class */
250 if (!classcache_store(NULL,c)) {
251 log_text("Could not cache primitive class");
257 primitivetype_table[i].class_primitive = c;
259 /* create class for wrapping the primitive type */
260 if (!load_class_bootstrap(utf_new_char(primitivetype_table[i].wrapname),&c))
262 primitivetype_table[i].class_wrap = c;
263 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
264 primitivetype_table[i].class_wrap->impldBy = NULL;
266 /* create the primitive array class */
267 if (primitivetype_table[i].arrayname) {
268 c = class_create_classinfo(utf_new_char(primitivetype_table[i].arrayname));
269 if (!load_newly_created_array(c, NULL))
271 primitivetype_table[i].arrayclass = c;
276 primitivetype_table[i].arrayvftbl = c->vftbl;
284 /* link_class ******************************************************************
286 Wrapper function for link_class_intern to ease monitor enter/exit
287 and exception handling.
289 *******************************************************************************/
291 classinfo *link_class(classinfo *c)
296 *exceptionptr = new_nullpointerexception();
300 #if defined(USE_THREADS)
301 /* enter a monitor on the class */
303 builtin_monitorenter((java_objectheader *) c);
306 /* maybe the class is already linked */
308 #if defined(USE_THREADS)
309 builtin_monitorexit((java_objectheader *) c);
315 #if defined(STATISTICS)
318 if (getcompilingtime)
319 compilingtime_stop();
325 /* call the internal function */
326 r = link_class_intern(c);
328 /* if return value is NULL, we had a problem and the class is not linked */
332 #if defined(STATISTICS)
338 if (getcompilingtime)
339 compilingtime_start();
342 #if defined(USE_THREADS)
343 /* leave the monitor */
345 builtin_monitorexit((java_objectheader *) c);
352 /* link_class_intern ***********************************************************
354 Tries to link a class. The function calculates the length in bytes
355 that an instance of this class requires as well as the VTBL for
356 methods and interface methods.
358 *******************************************************************************/
360 static classinfo *link_class_intern(classinfo *c)
362 classinfo *super; /* super class */
363 classinfo *tc; /* temporary class variable */
364 s4 supervftbllength; /* vftbllegnth of super class */
365 s4 vftbllength; /* vftbllength of current class */
366 s4 interfacetablelength; /* interface table length */
367 vftbl_t *v; /* vftbl of current class */
368 s4 i,j; /* interface/method/field counter */
369 arraydescriptor *arraydesc; /* descriptor for array classes */
371 /* maybe the class is already linked */
376 log_message_class("Linking class: ", c);
378 /* the class must be loaded */
380 throw_cacao_exception_exit(string_java_lang_InternalError,
381 "Trying to link unloaded class");
383 /* ok, this class is somewhat linked */
388 /* check interfaces */
390 for (i = 0; i < c->interfacescount; i++) {
391 /* resolve this super interface */
392 if (!resolve_classref_or_classinfo(NULL,c->interfaces[i],resolveEager,false,&tc))
394 c->interfaces[i].cls = tc;
396 /* detect circularity */
400 new_exception_utfmessage(string_java_lang_ClassCircularityError,
407 if (!(tc->flags & ACC_INTERFACE)) {
409 new_exception_message(string_java_lang_IncompatibleClassChangeError,
410 "Implementing class");
419 /* check super class */
422 if (c->super.any == NULL) { /* class java.lang.Object */
424 c->classUsed = USED; /* Object class is always used CO-RT*/
426 c->instancesize = sizeof(java_objectheader);
428 vftbllength = supervftbllength = 0;
433 /* resolve super class */
434 if (!resolve_classref_or_classinfo(NULL,c->super,resolveEager,false,&super))
436 c->super.cls = super;
438 /* detect circularity */
441 new_exception_utfmessage(string_java_lang_ClassCircularityError,
446 assert(super->loaded);
448 if (super->flags & ACC_INTERFACE) {
449 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
450 panic("Interface specified as super class");
453 /* Don't allow extending final classes */
454 if (super->flags & ACC_FINAL) {
456 new_exception_message(string_java_lang_VerifyError,
457 "Cannot inherit from final class");
462 if (!link_class(super))
465 /* handle array classes */
466 if (c->name->text[0] == '[')
467 if (!(arraydesc = link_array(c)))
470 if (c->flags & ACC_INTERFACE)
471 c->index = interfaceindex++;
473 c->index = super->index + 1;
475 c->instancesize = super->instancesize;
477 vftbllength = supervftbllength = super->vftbl->vftbllength;
479 c->finalizer = super->finalizer;
483 /* compute vftbl length */
485 for (i = 0; i < c->methodscount; i++) {
486 methodinfo *m = &(c->methods[i]);
488 if (!(m->flags & ACC_STATIC)) { /* is instance method */
494 for (j = 0; j < tc->methodscount; j++) {
495 if (method_canoverwrite(m, &(tc->methods[j]))) {
496 if (tc->methods[j].flags & ACC_PRIVATE)
497 goto notfoundvftblindex;
499 if (tc->methods[j].flags & ACC_FINAL) {
500 /* class a overrides final method . */
502 new_exception(string_java_lang_VerifyError);
506 m->vftblindex = tc->methods[j].vftblindex;
507 goto foundvftblindex;
515 m->vftblindex = (vftbllength++);
522 /* check interfaces of ABSTRACT class for unimplemented methods */
524 if (c->flags & ACC_ABSTRACT) {
527 s4 abstractmethodscount;
531 abstractmethodscount = 0;
533 for (i = 0; i < c->interfacescount; i++) {
534 ic = c->interfaces[i].cls;
536 for (j = 0; j < ic->methodscount; j++) {
537 im = &(ic->methods[j]);
539 /* skip `<clinit>' and `<init>' */
541 if (im->name == utf_clinit || im->name == utf_init)
547 for (k = 0; k < tc->methodscount; k++) {
548 if (method_canoverwrite(im, &(tc->methods[k])))
549 goto noabstractmethod;
555 abstractmethodscount++;
562 if (abstractmethodscount > 0) {
565 /* reallocate methods memory */
567 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
568 c->methodscount + abstractmethodscount);
570 for (i = 0; i < c->interfacescount; i++) {
571 ic = c->interfaces[i].cls;
573 for (j = 0; j < ic->methodscount; j++) {
574 im = &(ic->methods[j]);
576 /* skip `<clinit>' and `<init>' */
578 if (im->name == utf_clinit || im->name == utf_init)
584 for (k = 0; k < tc->methodscount; k++) {
585 if (method_canoverwrite(im, &(tc->methods[k])))
586 goto noabstractmethod2;
592 am = &(c->methods[c->methodscount]);
595 MCOPY(am, im, methodinfo, 1);
597 am->vftblindex = (vftbllength++);
608 #if defined(STATISTICS)
611 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
614 /* compute interfacetable length */
616 interfacetablelength = 0;
619 for (i = 0; i < tc->interfacescount; i++) {
620 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
621 if (h > interfacetablelength)
622 interfacetablelength = h;
627 /* allocate virtual function table */
629 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
630 sizeof(methodptr) * (vftbllength - 1) +
631 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
632 v = (vftbl_t *) (((methodptr *) v) +
633 (interfacetablelength - 1) * (interfacetablelength > 1));
634 c->header.vftbl = c->vftbl = v;
636 v->vftbllength = vftbllength;
637 v->interfacetablelength = interfacetablelength;
638 v->arraydesc = arraydesc;
640 /* store interface index in vftbl */
642 if (c->flags & ACC_INTERFACE)
643 v->baseval = -(c->index);
645 /* copy virtual function table of super class */
647 for (i = 0; i < supervftbllength; i++)
648 v->table[i] = super->vftbl->table[i];
650 /* add method stubs into virtual function table */
652 for (i = 0; i < c->methodscount; i++) {
653 methodinfo *m = &(c->methods[i]);
655 /* Methods in ABSTRACT classes from interfaces maybe already have a */
658 if (!m->stubroutine) {
659 if (!(m->flags & ACC_NATIVE)) {
660 m->stubroutine = createcompilerstub(m);
663 functionptr f = native_findfunction(c->name,
666 (m->flags & ACC_STATIC));
667 #if defined(STATIC_CLASSPATH)
670 m->stubroutine = createnativestub(f, m);
674 if (!(m->flags & ACC_STATIC))
675 v->table[m->vftblindex] = m->stubroutine;
678 /* compute instance size and offset of each field */
680 for (i = 0; i < c->fieldscount; i++) {
682 fieldinfo *f = &(c->fields[i]);
684 if (!(f->flags & ACC_STATIC)) {
685 dsize = desc_typesize(f->descriptor);
686 c->instancesize = ALIGN(c->instancesize, dsize);
687 f->offset = c->instancesize;
688 c->instancesize += dsize;
692 /* initialize interfacetable and interfacevftbllength */
694 v->interfacevftbllength = MNEW(s4, interfacetablelength);
696 #if defined(STATISTICS)
698 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
701 for (i = 0; i < interfacetablelength; i++) {
702 v->interfacevftbllength[i] = 0;
703 v->interfacetable[-i] = NULL;
708 for (tc = c; tc != NULL; tc = tc->super.cls)
709 for (i = 0; i < tc->interfacescount; i++)
710 linker_addinterface(c, tc->interfaces[i].cls);
712 /* add finalizer method (not for java.lang.Object) */
717 fi = class_findmethod(c, utf_finalize, utf_void__void);
720 if (!(fi->flags & ACC_STATIC))
724 /* resolve exception class references */
726 for (i = 0; i < c->methodscount; i++) {
727 methodinfo *m = c->methods + i;
728 for (j=0; j<m->exceptiontablelength; ++j) {
729 if (!m->exceptiontable[j].catchtype.any)
731 if (!resolve_classref_or_classinfo(NULL,m->exceptiontable[j].catchtype,
732 resolveEager,false,&(m->exceptiontable[j].catchtype.cls)))
735 for (j=0; j<m->thrownexceptionscount; ++j)
736 if (!resolve_classref_or_classinfo(NULL,m->thrownexceptions[j],
737 resolveEager,false,&(m->thrownexceptions[j].cls)))
743 linker_compute_subclasses(c);
746 log_message_class("Linking done class: ", c);
748 /* just return c to show that we didn't had a problem */
754 /* link_array ******************************************************************
756 This function is called by link_class to create the arraydescriptor
759 This function returns NULL if the array cannot be linked because
760 the component type has not been linked yet.
762 *******************************************************************************/
764 static arraydescriptor *link_array(classinfo *c)
766 classinfo *comp = NULL;
767 s4 namelen = c->name->blength;
768 arraydescriptor *desc;
771 /* Check the component type */
772 switch (c->name->text[1]) {
774 /* c is an array of arrays. */
775 if (!load_class_from_classloader(utf_new_intern(c->name->text + 1, namelen - 1),
776 c->classloader,&comp))
781 /* c is an array of objects. */
782 if (!load_class_from_classloader(utf_new_intern(c->name->text + 2, namelen - 3),
783 c->classloader,&comp))
788 /* If the component type has not been linked, link it now */
789 assert(!comp || comp->loaded);
790 if (comp && !comp->linked) {
792 if (!link_class(comp))
796 /* Allocate the arraydescriptor */
797 desc = NEW(arraydescriptor);
800 /* c is an array of references */
801 desc->arraytype = ARRAYTYPE_OBJECT;
802 desc->componentsize = sizeof(void*);
803 desc->dataoffset = OFFSET(java_objectarray, data);
805 compvftbl = comp->vftbl;
807 panic("Component class has no vftbl");
808 desc->componentvftbl = compvftbl;
810 if (compvftbl->arraydesc) {
811 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
812 if (compvftbl->arraydesc->dimension >= 255)
813 panic("Creating array of dimension >255");
814 desc->dimension = compvftbl->arraydesc->dimension + 1;
815 desc->elementtype = compvftbl->arraydesc->elementtype;
818 desc->elementvftbl = compvftbl;
820 desc->elementtype = ARRAYTYPE_OBJECT;
824 /* c is an array of a primitive type */
825 switch (c->name->text[1]) {
827 desc->arraytype = ARRAYTYPE_BOOLEAN;
828 desc->dataoffset = OFFSET(java_booleanarray,data);
829 desc->componentsize = sizeof(u1);
833 desc->arraytype = ARRAYTYPE_BYTE;
834 desc->dataoffset = OFFSET(java_bytearray,data);
835 desc->componentsize = sizeof(u1);
839 desc->arraytype = ARRAYTYPE_CHAR;
840 desc->dataoffset = OFFSET(java_chararray,data);
841 desc->componentsize = sizeof(u2);
845 desc->arraytype = ARRAYTYPE_DOUBLE;
846 desc->dataoffset = OFFSET(java_doublearray,data);
847 desc->componentsize = sizeof(double);
851 desc->arraytype = ARRAYTYPE_FLOAT;
852 desc->dataoffset = OFFSET(java_floatarray,data);
853 desc->componentsize = sizeof(float);
857 desc->arraytype = ARRAYTYPE_INT;
858 desc->dataoffset = OFFSET(java_intarray,data);
859 desc->componentsize = sizeof(s4);
863 desc->arraytype = ARRAYTYPE_LONG;
864 desc->dataoffset = OFFSET(java_longarray,data);
865 desc->componentsize = sizeof(s8);
869 desc->arraytype = ARRAYTYPE_SHORT;
870 desc->dataoffset = OFFSET(java_shortarray,data);
871 desc->componentsize = sizeof(s2);
875 panic("Invalid array class name");
878 desc->componentvftbl = NULL;
879 desc->elementvftbl = NULL;
881 desc->elementtype = desc->arraytype;
888 /* linker_compute_subclasses ***************************************************
892 *******************************************************************************/
894 static void linker_compute_subclasses(classinfo *c)
896 #if defined(USE_THREADS)
897 #if defined(NATIVE_THREADS)
904 if (!(c->flags & ACC_INTERFACE)) {
909 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
910 c->nextsub = c->super.cls->sub;
911 c->super.cls->sub = c;
916 /* this is the java.lang.Object special case */
918 if (!class_java_lang_Object) {
919 linker_compute_class_values(c);
922 linker_compute_class_values(class_java_lang_Object);
925 #if defined(USE_THREADS)
926 #if defined(NATIVE_THREADS)
935 /* linker_compute_class_values *************************************************
939 *******************************************************************************/
941 static void linker_compute_class_values(classinfo *c)
945 c->vftbl->baseval = ++classvalue;
950 linker_compute_class_values(subs);
952 subs = subs->nextsub;
955 c->vftbl->diffval = classvalue - c->vftbl->baseval;
959 /* linker_addinterface *********************************************************
961 Is needed by link_class for adding a VTBL to a class. All
962 interfaces implemented by ic are added as well.
964 *******************************************************************************/
966 static void linker_addinterface(classinfo *c, classinfo *ic)
970 vftbl_t *v = c->vftbl;
972 if (i >= v->interfacetablelength)
973 panic ("Inernal error: interfacetable overflow");
975 if (v->interfacetable[-i])
978 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
979 v->interfacevftbllength[i] = 1;
980 v->interfacetable[-i] = MNEW(methodptr, 1);
981 v->interfacetable[-i][0] = NULL;
984 v->interfacevftbllength[i] = ic->methodscount;
985 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
987 #if defined(STATISTICS)
989 count_vftbl_len += sizeof(methodptr) *
990 (ic->methodscount + (ic->methodscount == 0));
993 for (j = 0; j < ic->methodscount; j++) {
997 for (m = 0; m < sc->methodscount; m++) {
998 methodinfo *mi = &(sc->methods[m]);
1000 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1001 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1012 for (j = 0; j < ic->interfacescount; j++)
1013 linker_addinterface(c, ic->interfaces[j].cls);
1017 /* class_highestinterface ******************************************************
1019 Used by the function link_class to determine the amount of memory
1020 needed for the interface table.
1022 *******************************************************************************/
1024 static s4 class_highestinterface(classinfo *c)
1030 /* check for ACC_INTERFACE bit already done in link_class_intern */
1034 for (i = 0; i < c->interfacescount; i++) {
1035 h2 = class_highestinterface(c->interfaces[i].cls);
1045 /***************** Function: print_arraydescriptor ****************************
1047 Debug helper for displaying an arraydescriptor
1049 *******************************************************************************/
1051 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
1054 fprintf(file, "<NULL>");
1059 if (desc->componentvftbl) {
1060 if (desc->componentvftbl->class)
1061 utf_fprint(file, desc->componentvftbl->class->name);
1063 fprintf(file, "<no classinfo>");
1069 if (desc->elementvftbl) {
1070 if (desc->elementvftbl->class)
1071 utf_fprint(file, desc->elementvftbl->class->name);
1073 fprintf(file, "<no classinfo>");
1077 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
1078 desc->dataoffset, desc->componentsize);
1083 * These are local overrides for various environment variables in Emacs.
1084 * Please do not remove this and leave it at the end of the file, where
1085 * Emacs will automagically detect them.
1086 * ---------------------------------------------------------------------
1089 * indent-tabs-mode: t