harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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 }