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