|
|
1.1 root 1: /* C compiler: VAX code generator */
2:
3: #include "c.h"
4:
5: dclproto(static void address,(Symbol, Symbol, int));
6: dclproto(static void defaddress,(Symbol));
7: dclproto(static void defconst,(int, Value));
8: dclproto(static void defstring,(int, char *));
9: dclproto(static void defsymbol,(Symbol));
10: dclproto(static void doarg,(Node));
11: dclproto(static void emitspecial,(Node));
12: dclproto(static void function,(Symbol, Symbol [], Symbol [], int));
13: dclproto(static void global,(Symbol));
14: dclproto(static void import,(Symbol));
15: dclproto(static void local,(Symbol));
16: dclproto(static void progbeg,(int, char **));
17: dclproto(static void segment,(int));
18: dclproto(static void space,(int));
19:
20: #ifdef vax
21: #ifdef V9
22: dclproto(static void stabblock,(int, int, Symbol*));
23: dclproto(static void stabend,(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *));
24: dclproto(static void stabfend,(Symbol, int));
25: dclproto(static void stabinit,(char *, int, char *[]));
26: dclproto(static void stabline,(Coordinate *));
27: dclproto(static void stabsym,(Symbol));
28: dclproto(static void stabtype,(Symbol));
29: #else
30: #include <stab.h>
31: #include "stabbsd.c"
32: #define stabend 0
33: #endif
34: #endif
35:
36: dclproto(static void initgen,(void));
37: dclproto(static void final,(Node));
38:
39: #ifdef GEN4
40: dclproto(static unsigned emit2,(Node,Node[],short[]));
41: dclproto(static void target,(Node));
42: #endif
43:
44: Interface vaxInterface = {
45: "vax",
46: 1, 1, 0, /* char */
47: 2, 2, 0, /* short */
48: 4, 4, 0, /* int */
49: 4, 4, 1, /* float */
50: 8, 4, 1, /* double */
51: 4, 4, 0, /* T * */
52: 0, 1, 0, /* struct */
53: 0, /* left_to_right */
54: 1, /* little_endian */
55: 0, /* jump_on_return */
56: 0, /* mulops_are_calls */
57: 1, /* compl_band */
58: 0, /* no_argb */
59: NODAG, /* no_dag */
60: address,
61: blockbeg,
62: blockend,
63: defaddress,
64: defconst,
65: defstring,
66: defsymbol,
67: 0,
68: export,
69: function,
70: gen,
71: global,
72: import,
73: local,
74: progbeg,
75: progend,
76: segment,
77: space,
78: #ifdef vax
79: stabblock, stabend, stabfend, stabinit, stabline, stabsym, stabtype,
80: #else
81: 0, 0, 0, 0, 0, 0, 0,
82: #endif
83: {".globl %s\n", 0, 0, {".text", ".data", ".data", ".text 1", ".data 2"},
84: doarg, docall, 0, 0, 0,
85: final, 0, emitspecial,
86: #ifdef GEN4
87: vax_kids, vax_ntname, vax_nts, vax_rule, vax_state, vax_string, vax_cost,
88: rules, emit2, target
89: #endif
90: }
91: };
92:
93: static Symbol d0, f0, r0, r1;
94:
95: /* address - initialize q for addressing expression p+n */
96: static void address(q, p, n) Symbol q, p; {
97: q->x.offset = p->x.offset + n;
98: if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
99: q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n);
100: else
101: q->x.name = stringd(q->x.offset);
102: }
103:
104: static void defaddress(p) Symbol p; {
105: print(".long %s\n", p->x.name);
106: }
107:
108: /* defconst - define a constant */
109: static void defconst(ty, v) Value v; {
110: switch (ty) {
111: case C: print(".byte %d\n", v.uc); break;
112: case S: print(".word %d\n", v.ss); break;
113: case I: print(".long %d\n", v.i ); break;
114: case U: print(".long 0x%x\n", v.u ); break;
115: case P: print(".long 0x%x\n", v.p ); break;
116: case F:
117: if (v.f == 0.0)
118: print(".long 0x0\n");
119: else {
120: struct real r;
121: r = decode(F, v.f);
122: r.exp = (r.exp + 129)&0xff;
123: r.msb &= ~0x1ff;
124: print(".long 0x%x\n", (r.msb<<7) | (r.sign<<15) | (r.exp<<7) | (r.msb>>25));
125: }
126: break;
127: case D:
128: if (v.d == 0.0)
129: print(".long 0x0,0x0\n");
130: else {
131: unsigned u;
132: struct real r;
133: r = decode(D, v.d);
134: r.exp = (r.exp + 129)&0xff;
135: u = r.msb&~0x1ff;
136: print(".long 0x%x,", (u<<7) | (r.sign<<15) | (r.exp<<7) | (u>>25));
137: u = (r.msb<<23) | (r.lsb>>9);
138: print("0x%x\n", (u<<16) | (u>>16));
139: }
140: break;
141: default:
142: assert(0);
143: }
144: }
145:
146: static void defstring(n, s) char *s; {
147: genascii(".ascii", ".byte", n, s);
148: }
149:
150: /* defsymbol - compute and store p's back-end name */
151: static void defsymbol(p) Symbol p; {
152: if (p->scope == CONSTANTS)
153: p->x.name = p->name;
154: else if (p->scope >= LOCAL && p->sclass == STATIC)
155: p->x.name = stringf("L%d", genlabel(1));
156: else if (p->generated)
157: p->x.name = stringf("L%s", p->name);
158: else
159: p->x.name = stringf("_%s", p->name);
160: }
161:
162: /* doarg - assign offset for next ARG node */
163: static void doarg(p) Node p; {
164: assert(p);
165: assert(p->syms[0]);
166: assert(p->syms[1]);
167: p->syms[2] = intconst(mkactual(p->syms[1]->u.c.v.i, p->syms[0]->u.c.v.i, 4));
168: }
169:
170: static void emitspecial(p) Node p; {}
171:
172: /* function - generate code for a function */
173: static void function(p, caller, callee, n) Symbol p, callee[], caller[]; {
174: int i;
175:
176: initfunc(n, 4, 0);
177: for (i = 0; callee[i]; i++) {
178: assert(caller[i]);
179: callee[i]->x.offset = caller[i]->x.offset = offset;
180: callee[i]->x.name = caller[i]->x.name = stringd(offset);
181: offset = roundup(offset + caller[i]->type->size, 4);
182: getregvar(callee[i], rmap[ttob(callee[i]->type)]);
183: }
184: assert(caller[i] == 0);
185: offset = 0;
186: gencode(caller, callee);
187: mvregvars();
188: savemask[0] = usedmask[0]&eemask[0];
189: savebase[0] = 20;
190: print(".align 1\n%s:.word 0x%x\n", p->x.name, savemask[0]);
191: if (maxoffset > 0)
192: print("subl2 $%d,sp\n", maxoffset);
193: if (isstruct(freturn(p->type)))
194: print("movl r1,-4(fp)\n");
195: if (pflag) {
196: int lab = genlabel(1);
197: print("movab L%d,r0\njsb mcount\n", lab);
198: print(".data\n.align 2\nL%d: .long 0\n.text\n", lab);
199: }
200: emitcode();
201: if (glevel > 1)
202: print("ret\n");
203: }
204:
205: /* global - global id */
206: static void global(p) Symbol p; {
207: assert(p->u.seg);
208: if (p->u.seg == BSS && (p->sclass == STATIC || Aflag >= 2))
209: print(".lcomm %s,", p->x.name);
210: else if (p->u.seg == BSS)
211: print(".comm %s,", p->x.name);
212: else {
213: if (p->type->align > 1)
214: print(".align %c; ", "..1.2...3"[p->type->align]);
215: print("%s:", p->x.name);
216: }
217: }
218:
219: static void import(p) Symbol p; {}
220:
221: /* local - local */
222: static void local(p) Symbol p; {
223: if (getregvar(p, rmap[ttob(p->type)]) == 0)
224: p->x.name = stringd(mkauto(p, 4));
225: }
226:
227: /* progbeg - beginning of program */
228: static void progbeg(argc, argv) char *argv[]; {
229: nregsets = 1;
230: eemask[0] = 0xfc0;
231: tmask[0] = 0x03f;
232: vmask[0] = 0xfc0;
233: parseflags(argc, argv);
234: initgen();
235: d0 = mkregs("%d", 0, 0, 2, 3, 0, D, 0);
236: r0 = mkregs("%d", 0, 0, 1, 1, 0, I, 0);
237: f0 = mkregs("%d", 0, 0, 1, 1, 0, F, 0);
238: r1 = mkregs("%d", 1, 1, 1, 1, 0, I, 0);
239: rmap[D] = mkregs("%d", 0, 10, 2, 3, 0, D, 0);
240: rmap[F] = mkregs("%d", 0, 11, 1, 1, 0, F, 0);
241: rmap[I] = mkregs("%d", 0, 11, 1, 1, 0, I, 0);
242: rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I];
243: }
244:
245: static void segment(n) {
246: setseg(n);
247: }
248:
249: static void space(n) {
250: spacen(n, ".space");
251: }
252:
253: #ifndef V9
254: #include <errno.h>
255: #ifndef errno
256: extern int errno;
257: #endif
258:
259: /* strtol - interpret str as a base b number; if ptr!=0, *ptr gets updated str */
260: long strtol(str, ptr, b) char *str, **ptr; {
261: long n = 0;
262: char *s, sign = '+';
263: int d, overflow = 0;
264:
265: if (ptr)
266: *ptr = str;
267: if (b < 0 || b == 1 || b > 36)
268: return 0;
269: while (*str==' '||*str=='\f'||*str=='\n'||*str=='\r'||*str=='\t'||*str=='\v')
270: str++;
271: if (*str == '-' || *str == '+')
272: sign = *str++;
273: if (b == 0)
274: if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
275: b = 16;
276: str += 2;
277: } else if (str[0] == '0')
278: b = 8;
279: else
280: b = 10;
281: for (s = str; *str; str++) {
282: if (*str >= '0' && *str <= '9')
283: d = *str - '0';
284: else if (*str >= 'a' && *str <= 'z' || *str >= 'A' && *str <= 'Z')
285: d = (*str&~040) - 'A' + 10;
286: else
287: break;
288: if (d >= b)
289: break;
290: if (n < (LONG_MIN + d)/b)
291: overflow = 1;
292: n = b*n - d;
293: }
294: if (s == str)
295: return 0;
296: if (ptr)
297: *ptr = str;
298: if (overflow || (sign == '+' && n == LONG_MIN)) {
299: errno = ERANGE;
300: return sign == '+' ? LONG_MAX : LONG_MIN;
301: }
302: return sign == '+' ? -n : n;
303: }
304: #endif
305:
306: #ifdef vax
307: #ifdef V9
308: #include <stab.h>
309: static char *currentfile; /* current file name */
310:
311: dclproto(static void emittype,(int desc, int s, Type ty, char *str));
312: dclproto(extern long time,(long *));
313:
314: /* emittype - emit p's type */
315: static void emittype(desc, s, ty, str) Type ty; char *str; {
316: ty = unqual(ty);
317: switch (ty->op) {
318: case CHAR: desc |= (ty == unsignedchar ? 12 : 2); break;
319: case SHORT: desc |= (ty == unsignedshort ? 13 : 3); break;
320: case INT: desc |= 4; break;
321: case UNSIGNED: desc |= 14; break;
322: case FLOAT: desc |= 6; break;
323: case DOUBLE: desc |= 7; break;
324: case STRUCT: case UNION: case ENUM:
325: if (ty->op == STRUCT)
326: desc |= 8;
327: else if (ty->op == UNION)
328: desc |= 9;
329: else
330: desc |= 10;
331: print("0x%x,%s\n", desc, str);
332: if (glevel > 1)
333: if (*ty->u.sym->name >= '0' && *ty->u.sym->name <= '9')
334: print(".stabs \"%s$%d.%s\",0x%x,0,0,0\n", ty->u.sym->src.file,
335: ty->u.sym->src.y, ty->u.sym->name, N_TYID);
336: else
337: print(".stabs \"%s\",0x%x,0,0,0\n", ty->u.sym->name, N_TYID);
338: return;
339: case ARRAY:
340: emittype(desc | (3<<s), s + 2, ty->type, str);
341: if (glevel > 1)
342: print(".stabn 0x%x,0,0,%d\n", N_DIM, ty->size/ty->type->size);
343: return;
344: case POINTER:
345: emittype(desc | (1<<s), s + 2, ty->type, str);
346: return;
347: case FUNCTION:
348: emittype(desc | (2<<s), s + 2, ty->type, str);
349: return;
350: case VOID: desc |= 16; break;
351: default: break;
352: }
353: print("0x%x,%s\n", desc, str);
354: }
355:
356: /* stabblock - output a stab entry for '{' or '}' at level lev */
357: static void stabblock(brace, lev, p) Symbol *p; {
358: if (brace == '}')
359: while (*p)
360: stabsym(*p++);
361: print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev);
362: }
363:
364: /* stabend - finalize stab output */
365: static void stabend(cp, p, cpp, sp, syms) Coordinate *cp; Symbol p, *sp, *syms; Coordinate **cpp; {
366: if (glevel && cp->file && *cp->file) {
367: segment(CODE);
368: print("Lend:.stabs \"%s\",0x%x,0,%d,Lend\n", cp->file, N_ESO, cp->y);
369: }
370: }
371:
372: /* stabfend - end of function p */
373: static void stabfend(p, line) Symbol p; {
374: int lab;
375:
376: if (glevel <= 1)
377: return;
378: lab = genlabel(1);
379: print(".stabn 0x%x,0,%d,L%d\n", N_RFUN, line, p->u.f.label);
380: print("L%d:.stabs \"%s\",0x%x,0,%d,L%d\n", lab,
381: p->name, N_EFUN, line, lab);
382: }
383:
384: /* stabinit - initialize stab output */
385: static void stabinit(file, argc, argv) char *file, *argv[]; {
386: if (file && *file) {
387: segment(CODE);
388: print("Ltext:.stabs \"%s\",0x%x,0,0,Ltext\n", file, N_SO);
389: print(".stabs \"rcc\",0x%x,0,17665,%d\n", N_VER, time(0));
390: currentfile = file;
391: }
392: }
393:
394: /* stabline - emit stab entry for source coordinate *cp */
395: static void stabline(cp) Coordinate *cp; {
396: if (glevel <= 1)
397: return;
398: if (cp->file && cp->file != currentfile) {
399: int lab = genlabel(1);
400: print("L%d: .stabs \"%s\",0x%x,0,%d,L%d\n", lab,
401: cp->file, N_SOL, line, lab);
402: currentfile = cp->file;
403: }
404: print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y);
405: }
406:
407: /* stabsym - output a stab entry for symbol p */
408: static void stabsym(p) Symbol p; {
409: char buf[100], *adr = p->x.name;
410:
411: if (p->generated || p->computed)
412: return;
413: print(".stabs \"%s\",", p->name);
414: if (isfunc(p->type)) {
415: print("0x%x,0,0x%x,_%s\n", N_FUN, p->u.f.pt[0].y, p->name);
416: print(".stabs \"%s\",0x%x,0,", p->name,
417: p->sclass == STATIC ? N_STFUN : N_GSYM);
418: adr = "0";
419: } else if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
420: print("0x%x,0,", N_GSYM);
421: adr = "0";
422: } else if (p->sclass == STATIC)
423: print("0x%x,0,", p->u.seg == BSS ? N_LCSYM : N_STSYM);
424: else if (p->scope == PARAM)
425: print("0x%x,0,", p->sclass == REGISTER ? N_RSYM : N_PSYM);
426: else if (p->scope >= LOCAL) {
427: print("0x%x,0,", p->sclass == REGISTER ? N_RSYM : N_LSYM);
428: if (p->sclass != REGISTER)
429: adr = p->x.name + 1; /* skip - sign */
430: } else
431: assert(0);
432: emittype(0, 5, p->type, adr);
433: }
434:
435: /* stabtype - output a stab entry for type name, ty */
436: static void stabtype(p) Symbol p; {
437: char *name = p->name;
438:
439: if (p->sclass || p->type == 0 || glevel <= 1)
440: return;
441: if (*p->name >= '0' && *p->name <= '9')
442: name = stringf("%s$%d.%s", p->src.file, p->src.y, p->name);
443: switch (p->type->op) {
444: case STRUCT: case UNION: {
445: Field q;
446: print(".stabs \"%s\",0x%x,0,%d,0\n", name, N_BSTR,
447: p->type->op == STRUCT ? 8 : 9);
448: for (q = fieldlist(p->type); q; q = q->link) {
449: print(".stabs \"%s\",", q->name ? q->name : "");
450: if (q->lsb)
451: print("0x%x,0,0x%x,%d\n", N_SFLD,
452: fieldsize(q)<<5|(q->type == inttype ? 4 : 14),
453: 8*q->offset + fieldright(q));
454: else {
455: print("0x%x,0,", N_SSYM);
456: emittype(0, 5, q->type, stringd(q->offset));
457: }
458: }
459: print(".stabs \"%s\",0x%x,0,%d,%d\n", name, N_ESTR,
460: p->type->op == STRUCT ? 8 : 9, p->type->size);
461: break;
462: }
463: case ENUM: {
464: Symbol *q;
465: print(".stabs \"%s\",0x%x,0,10,0\n", name, N_BSTR);
466: for (q = p->u.idlist; *q; q++)
467: print(".stabs \"%s\",0x%x,0,11,%d\n", (*q)->name,
468: N_SSYM, (*q)->u.value);
469: print(".stabs \"%s\",0x%x,0,10,%d\n", name, N_ESTR,
470: p->type->size);
471: break;
472: }
473: }
474: }
475: #endif
476: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.