qinstr.c (5157B)
1 #include <assert.h> 2 #include <stdlib.h> 3 #include "gen.h" 4 #include "qbe.h" 5 #include "types.h" 6 #include "type_store.h" 7 8 enum qbe_instr 9 alloc_for_align(size_t align) 10 { 11 switch (align) { 12 case 1: 13 case 2: 14 case 4: 15 return Q_ALLOC4; 16 case 8: 17 return Q_ALLOC8; 18 case 16: 19 return Q_ALLOC16; 20 default: 21 abort(); 22 } 23 } 24 25 enum qbe_instr 26 store_for_type(struct gen_context *ctx, const struct type *type) 27 { 28 switch (type->storage) { 29 case STORAGE_CHAR: 30 case STORAGE_I8: 31 case STORAGE_U8: 32 case STORAGE_BOOL: 33 return Q_STOREB; 34 case STORAGE_I16: 35 case STORAGE_U16: 36 return Q_STOREH; 37 case STORAGE_I32: 38 case STORAGE_U32: 39 case STORAGE_INT: 40 case STORAGE_UINT: 41 case STORAGE_RCONST: 42 case STORAGE_RUNE: 43 return Q_STOREW; 44 case STORAGE_I64: 45 case STORAGE_U64: 46 return Q_STOREL; 47 case STORAGE_F32: 48 return Q_STORES; 49 case STORAGE_F64: 50 return Q_STORED; 51 case STORAGE_SIZE: 52 switch (ctx->arch.sz->stype) { 53 case Q_LONG: 54 return Q_STOREL; 55 default: 56 assert(0); 57 } 58 break; 59 case STORAGE_POINTER: 60 case STORAGE_UINTPTR: 61 switch (ctx->arch.ptr->stype) { 62 case Q_LONG: 63 return Q_STOREL; 64 default: 65 assert(0); 66 } 67 break; 68 case STORAGE_ENUM: 69 case STORAGE_ALIAS: 70 return store_for_type(ctx, type->alias.type); 71 case STORAGE_ARRAY: 72 case STORAGE_ERROR: 73 case STORAGE_FCONST: 74 case STORAGE_FUNCTION: 75 case STORAGE_ICONST: 76 case STORAGE_NULL: 77 case STORAGE_SLICE: 78 case STORAGE_STRING: 79 case STORAGE_STRUCT: 80 case STORAGE_TAGGED: 81 case STORAGE_TUPLE: 82 case STORAGE_UNION: 83 case STORAGE_VALIST: 84 case STORAGE_VOID: 85 abort(); // Invariant 86 } 87 abort(); // Unreachable 88 } 89 90 enum qbe_instr 91 load_for_type(struct gen_context *ctx, const struct type *type) 92 { 93 switch (type->storage) { 94 case STORAGE_I8: 95 return Q_LOADSB; 96 case STORAGE_CHAR: 97 case STORAGE_U8: 98 case STORAGE_BOOL: 99 return Q_LOADUB; 100 case STORAGE_I16: 101 return Q_LOADSH; 102 case STORAGE_U16: 103 return Q_LOADUH; 104 case STORAGE_U32: 105 case STORAGE_UINT: 106 case STORAGE_RCONST: 107 case STORAGE_RUNE: 108 return Q_LOADUW; 109 case STORAGE_I32: 110 case STORAGE_INT: 111 return Q_LOADSW; 112 case STORAGE_I64: 113 case STORAGE_U64: 114 return Q_LOADL; 115 case STORAGE_F32: 116 return Q_LOADS; 117 case STORAGE_F64: 118 return Q_LOADD; 119 case STORAGE_SIZE: 120 switch (ctx->arch.sz->stype) { 121 case Q_LONG: 122 return Q_LOADL; 123 default: 124 assert(0); 125 } 126 break; 127 case STORAGE_POINTER: 128 case STORAGE_UINTPTR: 129 switch (ctx->arch.ptr->stype) { 130 case Q_LONG: 131 return Q_LOADL; 132 default: 133 assert(0); 134 } 135 break; 136 case STORAGE_ENUM: 137 case STORAGE_ALIAS: 138 return load_for_type(ctx, type->alias.type); 139 case STORAGE_ARRAY: 140 case STORAGE_ERROR: 141 case STORAGE_FCONST: 142 case STORAGE_FUNCTION: 143 case STORAGE_ICONST: 144 case STORAGE_NULL: 145 case STORAGE_SLICE: 146 case STORAGE_STRING: 147 case STORAGE_STRUCT: 148 case STORAGE_TAGGED: 149 case STORAGE_TUPLE: 150 case STORAGE_UNION: 151 case STORAGE_VALIST: 152 case STORAGE_VOID: 153 abort(); // Invariant 154 } 155 abort(); // Unreachable 156 } 157 158 enum qbe_instr 159 binarithm_for_op(struct gen_context *ctx, 160 enum binarithm_operator op, 161 const struct type *type) 162 { 163 // TODO: NaN, udiv et al 164 bool is_signed = type_is_signed(type); 165 enum qbe_stype stype = qtype_lookup(ctx, type, false)->stype; 166 assert(stype != Q__AGGREGATE && stype != Q__VOID); 167 switch (op) { 168 case BIN_PLUS: 169 return Q_ADD; 170 case BIN_BAND: 171 return Q_AND; 172 case BIN_DIV: 173 return is_signed ? Q_DIV : Q_UDIV; 174 case BIN_MINUS: 175 return Q_SUB; 176 case BIN_TIMES: 177 return Q_MUL; 178 case BIN_MODULO: 179 return is_signed ? Q_REM : Q_UREM; 180 case BIN_BOR: 181 return Q_OR; 182 case BIN_BXOR: 183 return Q_XOR; 184 case BIN_LSHIFT: 185 return Q_SHL; 186 case BIN_RSHIFT: 187 return is_signed ? Q_SAR : Q_SHR; 188 case BIN_LEQUAL: 189 switch (stype) { 190 case Q_WORD: 191 return Q_CEQW; 192 case Q_LONG: 193 return Q_CEQL; 194 case Q_SINGLE: 195 return Q_CEQS; 196 case Q_DOUBLE: 197 return Q_CEQD; 198 default: 199 assert(0); 200 } 201 break; 202 case BIN_NEQUAL: 203 case BIN_LXOR: 204 switch (stype) { 205 case Q_WORD: 206 return Q_CNEW; 207 case Q_LONG: 208 return Q_CNEL; 209 case Q_SINGLE: 210 return Q_CNES; 211 case Q_DOUBLE: 212 return Q_CNED; 213 default: 214 assert(0); 215 } 216 break; 217 case BIN_GREATER: 218 switch (stype) { 219 case Q_WORD: 220 return is_signed ? Q_CSGTW : Q_CUGTW; 221 case Q_LONG: 222 return is_signed ? Q_CSGTL : Q_CUGTL; 223 case Q_SINGLE: 224 return Q_CGTS; 225 case Q_DOUBLE: 226 return Q_CGTD; 227 default: 228 assert(0); 229 } 230 case BIN_GREATEREQ: 231 switch (stype) { 232 case Q_WORD: 233 return is_signed ? Q_CSGEW : Q_CUGEW; 234 case Q_LONG: 235 return is_signed ? Q_CSGEL : Q_CUGEL; 236 case Q_SINGLE: 237 return Q_CGES; 238 case Q_DOUBLE: 239 return Q_CGED; 240 default: 241 assert(0); 242 } 243 break; 244 case BIN_LESS: 245 switch (stype) { 246 case Q_WORD: 247 return is_signed ? Q_CSLTW : Q_CULTW; 248 case Q_LONG: 249 return is_signed ? Q_CSLTL : Q_CULTL; 250 case Q_SINGLE: 251 return Q_CLTS; 252 case Q_DOUBLE: 253 return Q_CLTD; 254 default: 255 assert(0); 256 } 257 break; 258 case BIN_LESSEQ: 259 switch (stype) { 260 case Q_WORD: 261 return is_signed ? Q_CSLEW : Q_CULEW; 262 case Q_LONG: 263 return is_signed ? Q_CSLEL : Q_CULEL; 264 case Q_SINGLE: 265 return Q_CLES; 266 case Q_DOUBLE: 267 return Q_CLED; 268 default: 269 assert(0); 270 } 271 break; 272 case BIN_LAND: 273 case BIN_LOR: 274 assert(0); // Handled elsewhere to address short circuiting 275 } 276 assert(0); // Unreachable 277 }