genutil.c (2450B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "gen.h" 5 #include "qbe.h" 6 #include "types.h" 7 #include "util.h" 8 9 struct qbe_value 10 mkqval(struct gen_context *ctx, struct gen_value *value) 11 { 12 struct qbe_value qval = {0}; 13 switch (value->kind) { 14 case GV_CONST: 15 qval.kind = QV_CONST; 16 qval.lval = value->lval; // XXX: Kind of hacky 17 break; 18 case GV_GLOBAL: 19 qval.kind = QV_GLOBAL; 20 qval.name = value->name; 21 qval.threadlocal = value->threadlocal; 22 break; 23 case GV_TEMP: 24 qval.kind = QV_TEMPORARY; 25 qval.name = value->name; 26 break; 27 } 28 qval.type = qtype_lookup(ctx, value->type, true); 29 return qval; 30 } 31 32 struct qbe_value 33 mklval(struct gen_context *ctx, struct gen_value *value) 34 { 35 struct qbe_value qval = mkqval(ctx, value); 36 qval.type = ctx->arch.ptr; 37 return qval; 38 } 39 40 struct qbe_value 41 mkcopy(struct gen_context *ctx, struct gen_value *value, const char *fmt) 42 { 43 struct qbe_value qval = mkqval(ctx, value); 44 struct qbe_value copy = mkqtmp(ctx, ctx->arch.ptr, fmt); 45 pushi(ctx->current, ©, Q_COPY, &qval, NULL); 46 return copy; 47 } 48 49 struct qbe_value 50 mkqtmp(struct gen_context *ctx, const struct qbe_type *qtype, const char *fmt) 51 { 52 return (struct qbe_value){ 53 .kind = QV_TEMPORARY, 54 .type = qtype, 55 .name = gen_name(&ctx->id, fmt), 56 }; 57 } 58 59 struct gen_value 60 mkgtemp(struct gen_context *ctx, const struct type *type, const char *fmt) 61 { 62 return (struct gen_value){ 63 .kind = GV_TEMP, 64 .type = type, 65 .name = gen_name(&ctx->id, fmt), 66 }; 67 } 68 69 struct qbe_value 70 mkrtfunc(struct gen_context *ctx, const char *name) 71 { 72 return (struct qbe_value){ 73 .kind = QV_GLOBAL, 74 .name = xstrdup(name), 75 .type = ctx->arch.ptr, 76 }; 77 } 78 79 struct qbe_value 80 mklabel(struct gen_context *ctx, struct qbe_statement *stmt, const char *fmt) 81 { 82 struct qbe_value val; 83 val.kind = QV_LABEL; 84 val.name = xstrdup(genl(stmt, &ctx->id, fmt)); 85 return val; 86 } 87 88 void 89 branch_copyresult(struct gen_context *ctx, 90 struct gen_value result, 91 struct gen_value merged, 92 struct gen_value *out) 93 { 94 // Branching expressions written in the _with style may need to 95 // consolodate each branch's result into a single temporary to return to 96 // the caller. This function facilitates that. 97 if (out 98 || type_dealias(merged.type)->storage == STORAGE_VOID 99 || type_dealias(result.type)->storage == STORAGE_VOID) { 100 return; 101 } 102 struct qbe_value qmerged = mkqval(ctx, &merged); 103 struct qbe_value qval = mkqval(ctx, &result); 104 pushi(ctx->current, &qmerged, Q_COPY, &qval, NULL); 105 }