initial
[prop.git] / prop-src / gcgen.pcc
blob397e2fbc2c990d55522b4da9553ea5a49b766b95
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 //  This file implements the garbage collection interface generation
4 //
5 ///////////////////////////////////////////////////////////////////////////////
7 #include "ir.ph"
8 #include "datatype.ph"
9 #include "type.h"
11 ///////////////////////////////////////////////////////////////////////////////
13 //  This method generates the interface method declarations
14 //  for the garbage collector.
16 ///////////////////////////////////////////////////////////////////////////////
17 void DatatypeClass::generate_gc_interface(CodeGen& C)
19    C.pr("%^%/"
20         "%^//"
21         "%^// Method for garbage collection tracing"
22         "%^//"
23         "%^%/"
24         "%-%^protected:%+"
25         "%^virtual void trace(GC *);"
26         "%-%^public:%+"
27        );
30 ///////////////////////////////////////////////////////////////////////////////
32 //  This method generates an implementation for the trace method
34 ///////////////////////////////////////////////////////////////////////////////
35 void DatatypeClass::generate_gc_implementation(CodeGen& C, Tys tys, DefKind k)
37    // Unit constructors do not need gc methods
38    if (root->arg_constructors == 0) return;
40    if (k == INTERFACE_DEFINITION)
41    {  C.pr("%^extern void %s%P::trace(GC *);", class_name, tys); 
42       return;
43    }
45    C.pr("%^void %s%P::trace(GC * gc__)"
46         "%^{%+", class_name, tys); 
48    // Invoke base class tracing methods
49    gen_super_class_tracing_methods(C,tys,k);
51    // Invoke tracing functions for each collectable fields.
52    if (cons != NOcons) 
53    {  Ty arg_ty = cons_arg_ty;
54       if (is_array) arg_ty = mkarrayty(arg_ty,IDexp("len_"));
55       gen_field_tracing_methods(C,DEREFexp(IDexp(#"this")),
56                                 arg_ty,tys,k,true);
57    } 
59    C.pr("%-%^}\n\n");
62 ///////////////////////////////////////////////////////////////////////////////
64 //  This method generates a tracing method for each base class 
65 //  that is collectable.
67 ///////////////////////////////////////////////////////////////////////////////
68 void DatatypeClass::gen_super_class_tracing_methods
69    (CodeGen& C, Tys tys, DefKind k)
71    // Generate a call to the superclass 
72    if (this != root) 
73    {
74       if (root->use_gc_base) 
75          C.pr("%^%s%P::trace(gc__);", root->class_name, tys);
76       else
77          C.pr("%^// call to method %s%P::trace() has been optimized out",
78               root->class_name, tys);
79    }
81    for_each(Inherit, inh, inherited_classes)
82    {  if((inh->qualifiers & QUALcollectable) || is_gc_ty(inh->super_class))
83       {  C.pr("%^%t::trace(gc__);", 
84               apply_ty(mkpolyty(inh->super_class,parameters),tys), "");
85          if (this == root) root->use_gc_base = true;
86       }
87    }
90 ///////////////////////////////////////////////////////////////////////////////
92 //  This method generates a tracing method for each field 
93 //  that is collectable.
95 ///////////////////////////////////////////////////////////////////////////////
96 void DatatypeClass::gen_field_tracing_methods
97    (CodeGen& C, Exp exp, Ty ty, Tys tys, DefKind k, Bool toplevel)
99    match (deref_all(ty))
100    {  TUPLEty types: 
101       {  int i = 1;
102          for_each(Ty, ty, types) 
103             gen_field_tracing_methods(C,DOTexp(exp,index_of(i++)),ty,tys,k);
104       }
105    |  EXTUPLEty types:
106       {  int i = 1;
107          for_each(Ty, ty, types) 
108             gen_field_tracing_methods(C,DOTexp(exp,index_of(i++)),ty,tys,k);
109       }
110    |  RECORDty (labels, _, types):
111       {  Ids ls; Tys ts;
112          for(ls = labels, ts = types; ls && ts; ls = ls->#2, ts = ts->#2)
113             gen_field_tracing_methods(C,DOTexp(exp,ls->#1),ts->#1,tys,k);
114       }
115    |  ARRAYty (ty,bound):
116       {  C.pr("%^{%+"
117               "%^for (int i__ = 0; i__ < %e; i__++)"
118               "%^{%+",
119               bound);
120          gen_field_tracing_methods(C,INDEXexp(exp,IDexp(#"i__")),ty,tys,k);
121          C.pr("%-%^}"
122               "%-%^}");
123       }
124    |  _:
125       {  if (is_gc_ty(ty))
126          {  if (toplevel) exp = DOTexp(exp,mangle(cons->name));
127             if (is_pointer_ty(ty))
128                C.pr("%^%e = (%t)gc__->trace(%e);",exp,ty,"",exp);
129             else
130                C.pr("%^gc__->trace(%e);",exp);
131             C.pr(" // %T", ty);
132          } else
133          {  C.pr("%^// omitted %T", ty); }
134       }
135    }