Commit | Line | Data |
---|---|---|
3be3d0a4 KM |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
ca67e7b4 | 8 | static char sccsid[] = "@(#)stab.c 5.3 (Berkeley) 1/3/88"; |
3be3d0a4 KM |
9 | #endif not lint |
10 | ||
11 | /* | |
12 | * stab.c | |
13 | * | |
14 | * Symbolic debugging info interface for the f77 compiler. | |
15 | * | |
16 | * Here we generate pseudo-ops that cause the assembler to put | |
17 | * symbolic debugging information into the object file. | |
18 | * | |
19 | * University of Utah CS Dept modification history: | |
20 | * | |
21 | * $Log: stab.c,v $ | |
6f672207 DS |
22 | * Revision 5.3 86/01/10 17:12:58 donn |
23 | * Add junk to handle PARAMETER variables. | |
24 | * | |
25 | * Revision 5.2 86/01/10 13:51:31 donn | |
26 | * Changes to produce correct stab information for logical and logical*2 types | |
27 | * (from Jerry Berkman) plus changes for dummy procedures. | |
28 | * | |
29 | * Revision 5.1 85/08/10 03:50:06 donn | |
30 | * 4.3 alpha | |
31 | * | |
3be3d0a4 KM |
32 | * Revision 1.2 85/02/02 01:30:09 donn |
33 | * Don't put the 'program' name into the file; it only confuses dbx, sigh. | |
34 | * | |
35 | */ | |
36 | ||
37 | #include "defs.h" | |
38 | ||
39 | #include <sys/types.h> | |
40 | #include <a.out.h> | |
41 | #include <stab.h> | |
42 | ||
43 | #define public | |
44 | #define private static | |
45 | #define and && | |
46 | #define or || | |
47 | #define not ! | |
48 | #define div / | |
49 | #define mod % | |
50 | #define nil 0 | |
51 | ||
52 | typedef enum { false, true } Boolean; | |
53 | ||
54 | static char asmline[128]; | |
55 | int len; | |
56 | extern char *malloc(); | |
57 | ||
58 | prstab(s, code, type, loc) | |
59 | char *s, *loc; | |
60 | int code, type; | |
61 | { | |
62 | char *locout; | |
63 | ||
64 | if (sdbflag) { | |
65 | locout = (loc == nil) ? "0" : loc; | |
66 | if (s == nil) { | |
67 | sprintf(asmline, "\t.stabn\t0x%x,0,0x%x,%s\n", code, type, locout); | |
68 | } else { | |
69 | sprintf(asmline, "\t.stabs\t\"%s\",0x%x,0,0x%x,%s\n", s, code, type, | |
70 | locout); | |
71 | } | |
72 | p2pass( asmline ); | |
73 | } | |
74 | } | |
75 | ||
76 | filenamestab(s) | |
77 | char *s; | |
78 | { | |
79 | sprintf(asmline,"\t.stabs\t\"%s\",0x%x,0,0,0\n", s, N_SO); | |
80 | p2pass( asmline ); | |
81 | } | |
82 | ||
83 | linenostab(lineno) | |
84 | int lineno; | |
85 | { | |
86 | sprintf(asmline,"\t.stabd\t0x%x,0,%d\n", N_SLINE, lineno); | |
87 | p2pass( asmline ); | |
88 | } | |
89 | ||
90 | /* | |
91 | * Generate information for an entry point | |
92 | */ | |
93 | ||
94 | public entrystab(p,class) | |
95 | register struct Entrypoint *p; | |
96 | int class; | |
97 | { | |
98 | int et; | |
99 | Namep q; | |
100 | ||
101 | switch(class) { | |
102 | case CLMAIN: | |
103 | et=writestabtype(TYSUBR); | |
104 | sprintf(asmline, "\t.stabs\t\"MAIN:F%2d\",0x%x,0,0,L%d\n", | |
105 | et,N_FUN,p->entrylabel); | |
106 | p2pass(asmline); | |
107 | break; | |
108 | ||
109 | case CLBLOCK: /* May need to something with block data LATER */ | |
110 | break; | |
111 | ||
112 | default : | |
113 | if( (q=p->enamep) == nil) fatal("entrystab has no nameblock"); | |
114 | sprintf(asmline, "\t.stabs\t\"%s:F", varstr(VL,q->varname)); | |
115 | len = strlen(asmline); | |
116 | /* when insufficient information is around assume TYSUBR; enddcl | |
117 | will fill this in*/ | |
118 | if(q->vtype == TYUNKNOWN || (q->vtype == TYCHAR && q->vleng == nil) ){ | |
119 | sprintf(asmline+len, "%2d", writestabtype(TYSUBR)); | |
120 | } | |
121 | else addtypeinfo(q); | |
122 | len += strlen(asmline+len); | |
123 | sprintf(asmline+len, "\",0x%x,0,0,L%d\n",N_FUN,p->entrylabel); | |
124 | p2pass(asmline); | |
125 | break; | |
126 | } | |
127 | } | |
128 | ||
129 | /* | |
130 | * Generate information for a symbol table (name block ) entry. | |
131 | */ | |
132 | ||
133 | public namestab(sym) | |
134 | Namep sym; | |
135 | { | |
136 | register Namep p; | |
137 | char *varname, *classname; | |
6f672207 DS |
138 | expptr ep; |
139 | char buf[100]; | |
3be3d0a4 KM |
140 | Boolean ignore; |
141 | int vartype; | |
142 | ||
143 | ignore = false; | |
144 | p = sym; | |
145 | if(!p->vdcldone) return; | |
146 | vartype = p->vtype; | |
147 | varname = varstr(VL, p->varname); | |
148 | switch (p->vclass) { | |
149 | case CLPARAM: /* parameter (constant) */ | |
6f672207 DS |
150 | classname = buf; |
151 | if ((ep = ((struct Paramblock *) p)->paramval) && | |
152 | ep->tag == TCONST) { | |
153 | switch(ep->constblock.vtype) { | |
154 | case TYLONG: | |
155 | case TYSHORT: | |
156 | case TYLOGICAL: | |
157 | case TYADDR: | |
9868d2fe | 158 | sprintf(buf, "c=i%d", ep->constblock.constant.ci); |
6f672207 DS |
159 | break; |
160 | case TYREAL: | |
161 | case TYDREAL: | |
9868d2fe | 162 | sprintf(buf, "c=r%f", ep->constblock.constant.cd[0]); |
6f672207 DS |
163 | break; |
164 | default: | |
165 | /* punt */ | |
166 | ignore = true; | |
167 | break; | |
168 | } | |
169 | } else { | |
170 | ignore = true; | |
171 | } | |
3be3d0a4 KM |
172 | break; |
173 | ||
174 | case CLVAR: /* variable */ | |
175 | case CLUNKNOWN: | |
176 | if(p->vstg == STGARG) classname = "v"; | |
177 | else classname = "V"; | |
178 | break; | |
179 | ||
6f672207 DS |
180 | case CLPROC: /* external or function or subroutine */ |
181 | if(p->vstg == STGARG) { | |
182 | classname = "v"; | |
183 | break; | |
184 | } | |
185 | /* FALL THROUGH */ | |
3be3d0a4 KM |
186 | case CLMAIN: /* main program */ |
187 | case CLENTRY: /* secondary entry point */ | |
188 | case CLBLOCK: /* block data name*/ | |
3be3d0a4 KM |
189 | ignore = true; /* these are put out by entrystab */ |
190 | break; | |
191 | ||
192 | ||
193 | } | |
194 | if (not ignore) { | |
195 | sprintf(asmline, "\t.stabs\t\"%s:%s", varname, classname); | |
196 | len = strlen(asmline); | |
197 | addtypeinfo(p); | |
198 | len += strlen(asmline+len); | |
199 | switch(p->vstg) { | |
200 | ||
201 | case STGUNKNOWN : | |
202 | case STGCONST : | |
203 | case STGEXT : | |
204 | case STGINTR : | |
205 | case STGSTFUNCT : | |
206 | case STGLENG : | |
207 | case STGNULL : | |
208 | case STGREG : | |
209 | case STGINIT : | |
6f672207 DS |
210 | if (p->vclass == CLPARAM) { |
211 | /* these have zero storage class for some reason */ | |
212 | sprintf(asmline+len, "\",0x%x,0,0,0\n", N_LSYM); | |
213 | break; | |
214 | } | |
3be3d0a4 KM |
215 | sprintf(asmline+len, |
216 | "\",0x%x,0,0,0 /* don't know how to calc loc for stg %d*/ \n", | |
217 | N_LSYM,p->vstg); | |
218 | break; | |
219 | ||
220 | case STGARG : | |
221 | sprintf(asmline+len,"\",0x%x,0,0,%d \n", | |
222 | N_PSYM,p->vardesc.varno + ARGOFFSET ); | |
223 | break; | |
224 | ||
225 | case STGCOMMON : | |
226 | sprintf(asmline+len, "\",0x%x,0,0,%d\n", | |
227 | N_GSYM, p->voffset); | |
228 | break; | |
229 | ||
230 | case STGBSS : | |
231 | sprintf(asmline+len, "\",0x%x,0,0,v.%d\n", | |
232 | (p->inlcomm ? N_LCSYM : N_STSYM), | |
233 | p->vardesc.varno); | |
234 | break; | |
235 | ||
236 | case STGEQUIV : | |
237 | sprintf(asmline+len, "\",0x%x,0,0,%s + %d \n", | |
238 | (p->inlcomm ? N_LCSYM : N_STSYM) , | |
239 | memname(STGEQUIV,p->vardesc.varno),(p->voffset)) ; | |
240 | break; | |
241 | ||
242 | case STGAUTO : | |
243 | sprintf(asmline+len, "\",0x%x,0,0,-%d \n", | |
244 | N_LSYM, p->voffset); | |
245 | ||
246 | } | |
247 | p2pass(asmline); | |
248 | } | |
249 | } | |
250 | ||
6f672207 | 251 | static typenum[NTYPES+1]; /* has the given type already been defined ?*/ |
3be3d0a4 KM |
252 | |
253 | private writestabtype(type) | |
254 | int type; | |
255 | { | |
256 | char asmline[130]; | |
6f672207 DS |
257 | static char *typename[NTYPES+1] = { |
258 | "unknown", "addr", "integer*2", "integer", "real", "double precision", | |
259 | "complex", "double complex", "logical", "char", "void", "error", "logical*2" }; | |
3be3d0a4 | 260 | |
6f672207 | 261 | static int typerange[NTYPES+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; |
3be3d0a4 KM |
262 | |
263 | /* compare with typesize[] in init.c */ | |
6f672207 | 264 | static int typebounds[2] [NTYPES+1] ={ |
3be3d0a4 KM |
265 | /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ |
266 | { 0 , 0 , -32768, -2147483648, 4, 8, | |
6f672207 DS |
267 | /* "complex", "d-complex", "logical", "char", "void", "error", "logical*2" */ |
268 | 8, 16, 4, 0, 0, 0, 2 }, | |
3be3d0a4 | 269 | /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ |
6f672207 DS |
270 | { 0 , -1, 32767, 2147483647, 0, 0, |
271 | /* "complex", "d-complex", "logical", "char", "void", "error", "logical*2" */ | |
272 | 0, 0, 0, 127, 0, 0, 0 } | |
3be3d0a4 KM |
273 | }; |
274 | ||
275 | ||
6f672207 DS |
276 | if (type < 0 || type > NTYPES) |
277 | badtype("writestabtype",type); | |
278 | ||
279 | /* substitute "logical*2" for "logical" when "-i2" compiler flag used */ | |
280 | if (type == TYLOGICAL && tylogical == TYSHORT) | |
281 | type = NTYPES; | |
3be3d0a4 KM |
282 | |
283 | if (typenum[type]) return(typenum[type]); | |
284 | typenum[type] = type; | |
285 | sprintf(asmline, "\t.stabs\t\"%s:t%d=r%d;%ld;%ld;\",0x%x,0,0,0 \n", | |
286 | typename[type], type, typerange[type], typebounds[0][type], | |
287 | typebounds[1][type], N_GSYM) ; | |
288 | p2pass(asmline); | |
289 | return(typenum[type]); | |
290 | } | |
291 | ||
292 | ||
293 | private getbasenum(p) | |
294 | Namep p; | |
295 | { | |
296 | ||
297 | int t; | |
3be3d0a4 | 298 | |
6f672207 DS |
299 | if (p->vclass == CLPROC && p->vstg == STGARG) |
300 | t = TYADDR; | |
301 | else | |
302 | t = p->vtype; | |
303 | ||
304 | if (t < TYADDR || t > TYSUBR) | |
305 | dclerr("can't get dbx basetype information",p); | |
306 | ||
307 | if (p->vtype == TYCHAR || p->vdim != nil) | |
308 | writestabtype(TYINT); | |
3be3d0a4 KM |
309 | return(writestabtype(t)); |
310 | } | |
311 | ||
312 | /* | |
313 | * Generate debugging information for the given type of the given symbol. | |
314 | */ | |
315 | ||
316 | private addtypeinfo(sym) | |
317 | Namep sym; | |
318 | { | |
319 | Namep p; | |
320 | int i,tnum; | |
321 | char lb[20],ub[20]; | |
322 | ||
323 | p = sym; | |
324 | if (p->tag != TNAME) badtag("addtypeinfo",p->tag); | |
6f672207 DS |
325 | if (p->vclass == CLPARAM) |
326 | return; | |
3be3d0a4 KM |
327 | |
328 | tnum = getbasenum(p); | |
329 | if(p->vdim != (struct Dimblock *) ENULL) { | |
330 | ||
331 | for (i = p->vdim->ndim-1; i >=0 ; --i) { | |
332 | if(p->vdim->dims[i].lbaddr == ENULL) { | |
9868d2fe | 333 | sprintf(lb,"%d", p->vdim->dims[i].lb->constblock.constant.ci); |
3be3d0a4 KM |
334 | } |
335 | else { | |
9868d2fe | 336 | sprintf(lb,"T%d", p->vdim->dims[i].lbaddr->addrblock.memoffset->constblock.constant.ci); |
3be3d0a4 KM |
337 | } |
338 | if(p->vdim->dims[i].ubaddr == ENULL) { | |
9868d2fe | 339 | sprintf(ub,"%d",p->vdim->dims[i].ub->constblock.constant.ci); |
3be3d0a4 KM |
340 | } |
341 | else { | |
9868d2fe | 342 | sprintf(ub,"T%d",p->vdim->dims[i].ubaddr->addrblock.memoffset->constblock.constant.ci); |
3be3d0a4 KM |
343 | } |
344 | sprintf(asmline+len, "ar%d;%s;%s;", TYINT, lb, ub); | |
345 | len += strlen(asmline+len); | |
346 | } | |
347 | } | |
348 | if (p->vtype == TYCHAR) { | |
349 | /* character type always an array(1:?) */ | |
350 | if( ! (p->vleng ) ) | |
351 | fatalstr("missing length in addtypeinfo for character variable %s", varstr(p->varname)); | |
352 | ||
9868d2fe | 353 | if (ISCONST(p->vleng)) sprintf(ub,"%d",p->vleng->constblock.constant.ci); |
3be3d0a4 KM |
354 | else sprintf(ub,"A%d",p->vleng->addrblock.memno + ARGOFFSET); |
355 | ||
356 | sprintf(asmline+len,"ar%d;1;%s;", TYINT, ub); | |
357 | len += strlen(asmline+len); | |
358 | } | |
359 | sprintf(asmline+len, "%d",tnum); | |
360 | } |