harec

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

qinstr.c (5115B)


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