1 /* $OpenBSD: code.c,v 1.2 2007/11/22 15:06:43 stefan Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Michael Shalayeff 5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 # include "pass1.h" 33 34 NODE *funarg(NODE *, int *); 35 int argreg(TWORD, int *); 36 37 static const char *const loctbl[] = { "text", "data", "section .rodata" }; 38 39 /* 40 * Define everything needed to print out some data (or text). 41 * This means segment, alignment, visibility, etc. 42 */ 43 void 44 defloc(struct symtab *sp) 45 { 46 extern char *nextsect; 47 static int lastloc = -1; 48 TWORD t; 49 char *n; 50 int s; 51 52 if (sp == NULL) { 53 lastloc = -1; 54 return; 55 } 56 t = sp->stype; 57 s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; 58 if (nextsect) { 59 printf("\t.section %s\n", nextsect); 60 nextsect = NULL; 61 s = -1; 62 } else if (s != lastloc) 63 printf("\t.%s\n", loctbl[s]); 64 lastloc = s; 65 while (ISARY(t)) 66 t = DECREF(t); 67 s = ISFTN(t) ? ALINT : talign(t, sp->ssue); 68 if (s > ALCHAR) 69 printf("\t.align\t%d\n", s / ALCHAR); 70 n = sp->soname ? sp->soname : sp->sname; 71 if (sp->sclass == EXTDEF) 72 printf("\t.export %s, %s\n", n, 73 ISFTN(t)? "code" : "data"); 74 if (sp->slevel == 0) 75 printf("\t.type\t%s, @%s\n\t.label %s\n", 76 n, ISFTN(t)? "function" : "object", n); 77 else 78 printf("\t.type\t" LABFMT ", @%s\n\t.label\t" LABFMT "\n", 79 sp->soffset, ISFTN(t)? "function" : "object", sp->soffset); 80 } 81 82 /* 83 * code for the end of a function 84 * deals with struct return here 85 */ 86 void 87 efcode() 88 { 89 NODE *p, *q; 90 int sz; 91 92 if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) 93 return; 94 /* address of return struct is in %ret0 */ 95 /* create a call to memcpy() */ 96 /* will get the result in %ret0 */ 97 p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); 98 p->n_rval = RET0; 99 q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); 100 q->n_rval = FP; 101 q->n_lval = 8; /* return buffer offset */ 102 p = block(CM, q, p, INT, 0, MKSUE(INT)); 103 sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; 104 p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT)); 105 p->n_right->n_name = ""; 106 p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR)); 107 p->n_left->n_name = "memcpy"; 108 p = clocal(p); 109 send_passt(IP_NODE, p); 110 } 111 112 int 113 argreg(TWORD t, int *n) 114 { 115 switch (t) { 116 case FLOAT: 117 return FR7L - 2 * (*n)++; 118 case DOUBLE: 119 case LDOUBLE: 120 *n += 2; 121 return FR6 - *n - 2; 122 case LONGLONG: 123 case ULONGLONG: 124 *n += 2; 125 return AD1 - (*n - 2) / 2; 126 default: 127 return ARG0 - (*n)++; 128 } 129 } 130 131 /* 132 * code for the beginning of a function; 'a' is an array of 133 * indices in symtab for the arguments; n is the number 134 */ 135 void 136 bfcode(struct symtab **a, int cnt) 137 { 138 struct symtab *sp; 139 NODE *p, *q; 140 int i, n, sz; 141 142 if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { 143 /* Function returns struct, adjust arg offset */ 144 for (i = 0; i < n; i++) 145 a[i]->soffset += SZPOINT(LONG); 146 } 147 148 /* recalculate the arg offset and create TEMP moves */ 149 for (n = 0, i = 0; i < cnt; i++) { 150 sp = a[i]; 151 152 sz = szty(sp->stype); 153 if (n % sz) 154 n++; /* XXX LDOUBLE */ 155 156 if (n < 4) { 157 p = tempnode(0, sp->stype, sp->sdf, sp->ssue); 158 /* TODO p->n_left->n_lval = -(32 + n * 4); */ 159 q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue); 160 q->n_rval = argreg(sp->stype, &n); 161 p = buildtree(ASSIGN, p, q); 162 sp->soffset = regno(p->n_left); 163 sp->sflags |= STNODE; 164 ecomp(p); 165 } else { 166 sp->soffset += SZINT * n; 167 if (xtemps) { 168 /* put stack args in temps if optimizing */ 169 p = tempnode(0, sp->stype, sp->sdf, sp->ssue); 170 p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); 171 sp->soffset = regno(p->n_left); 172 sp->sflags |= STNODE; 173 ecomp(p); 174 } 175 } 176 } 177 } 178 179 180 /* 181 * by now, the automatics and register variables are allocated 182 */ 183 void 184 bccode() 185 { 186 SETOFF(autooff, SZINT); 187 } 188 189 /* called just before final exit */ 190 /* flag is 1 if errors, 0 if none */ 191 void 192 ejobcode(int errors) 193 { 194 if (errors) 195 return; 196 197 printf("\t.end\n"); 198 } 199 200 void 201 bjobcode(void) 202 { 203 printf("\t.level\t1.1\n" 204 "\t.import $global$, data\n" 205 "\t.import $$dyncall, millicode\n"); 206 } 207 208 /* 209 * return the alignment of field of type t 210 */ 211 int 212 fldal(unsigned int t) 213 { 214 uerror("illegal field type"); 215 return(ALINT); 216 } 217 218 /* fix up type of field p */ 219 void 220 fldty(struct symtab *p) 221 { 222 } 223 224 /* 225 * XXX - fix genswitch. 226 */ 227 int 228 mygenswitch(int num, TWORD type, struct swents **p, int n) 229 { 230 return 0; 231 } 232 233 NODE * 234 funarg(NODE *p, int *n) 235 { 236 NODE *r; 237 int sz; 238 239 if (p->n_op == CM) { 240 p->n_left = funarg(p->n_left, n); 241 p->n_right = funarg(p->n_right, n); 242 return p; 243 } 244 245 sz = szty(p->n_type); 246 if (*n % sz) 247 (*n)++; /* XXX LDOUBLE */ 248 249 if (*n >= 4) { 250 *n += sz; 251 r = block(OREG, NIL, NIL, p->n_type|PTR, 0, 252 MKSUE(p->n_type|PTR)); 253 r->n_rval = SP; 254 r->n_lval = -(32 + *n * 4); 255 } else { 256 r = block(REG, NIL, NIL, p->n_type, 0, 0); 257 r->n_lval = 0; 258 r->n_rval = argreg(p->n_type, n); 259 } 260 p = block(ASSIGN, r, p, p->n_type, 0, 0); 261 clocal(p); 262 263 return p; 264 } 265 266 /* 267 * Called with a function call with arguments as argument. 268 * This is done early in buildtree() and only done once. 269 */ 270 NODE * 271 funcode(NODE *p) 272 { 273 int n = 0; 274 275 p->n_right = funarg(p->n_right, &n); 276 return p; 277 } 278