📄 dt_cg.c
字号:
dt_cg_compare_op(dnp, dlp, drp, dt_cg_compare_signed(dnp) ? DIF_OP_BL : DIF_OP_BLU); break; case DT_TOK_LE: dt_cg_compare_op(dnp, dlp, drp, dt_cg_compare_signed(dnp) ? DIF_OP_BLE : DIF_OP_BLEU); break; case DT_TOK_GT: dt_cg_compare_op(dnp, dlp, drp, dt_cg_compare_signed(dnp) ? DIF_OP_BG : DIF_OP_BGU); break; case DT_TOK_GE: dt_cg_compare_op(dnp, dlp, drp, dt_cg_compare_signed(dnp) ? DIF_OP_BGE : DIF_OP_BGEU); break; case DT_TOK_LSH: dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL); break; case DT_TOK_RSH: dt_cg_arithmetic_op(dnp, dlp, drp, (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL); break; case DT_TOK_ADD: dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD); break; case DT_TOK_SUB: dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB); break; case DT_TOK_MUL: dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL); break; case DT_TOK_DIV: dt_cg_arithmetic_op(dnp, dlp, drp, (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV); break; case DT_TOK_MOD: dt_cg_arithmetic_op(dnp, dlp, drp, (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM); break; case DT_TOK_LNEG: dt_cg_logical_neg(dnp, dlp, drp); break; case DT_TOK_BNEG: dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; instr = DIF_INSTR_NOT(dnp->dn_reg, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; case DT_TOK_PREINC: dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_ADD); break; case DT_TOK_POSTINC: dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_ADD); break; case DT_TOK_PREDEC: dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_SUB); break; case DT_TOK_POSTDEC: dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_SUB); break; case DT_TOK_IPOS: dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; break; case DT_TOK_INEG: dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; instr = DIF_INSTR_FMT(DIF_OP_SUB, DIF_REG_R0, dnp->dn_reg, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; case DT_TOK_DEREF: dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; if (!(dnp->dn_flags & DT_NF_REF)) { uint_t ubit = dnp->dn_flags & DT_NF_USERLAND; /* * Save and restore DT_NF_USERLAND across dt_cg_load(): * we need the sign bit from dnp and the user bit from * dnp->dn_child in order to get the proper opcode. */ dnp->dn_flags |= (dnp->dn_child->dn_flags & DT_NF_USERLAND); instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp, dnp->dn_type), dnp->dn_reg, dnp->dn_reg); dnp->dn_flags &= ~DT_NF_USERLAND; dnp->dn_flags |= ubit; dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); } break; case DT_TOK_ADDROF: { uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF; dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */ dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; dnp->dn_child->dn_flags &= ~DT_NF_REF; dnp->dn_child->dn_flags |= rbit; break; } case DT_TOK_SIZEOF: { size_t size = dt_node_sizeof(dnp->dn_child); if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); assert(size != 0); dt_cg_setx(dlp, dnp->dn_reg, size); break; } case DT_TOK_STRINGOF: dt_cg_node(dnp->dn_child, dlp, drp); dnp->dn_reg = dnp->dn_child->dn_reg; break; case DT_TOK_XLATE: dt_cg_node(dnp->dn_right, dlp, drp); dnp->dn_reg = dnp->dn_right->dn_reg; break; case DT_TOK_LPAR: dt_cg_node(dnp->dn_right, dlp, drp); dnp->dn_reg = dnp->dn_right->dn_reg; dt_cg_typecast(dnp->dn_right, dnp, dlp, drp); break; case DT_TOK_PTR: case DT_TOK_DOT: assert(dnp->dn_right->dn_kind == DT_NODE_IDENT); dt_cg_node(dnp->dn_left, dlp, drp); /* * If the left-hand side of PTR or DOT is a dynamic variable, * we expect it to be the output of a D translator. In this * case, we look up the parse tree corresponding to the member * that is being accessed and run the code generator over it. * We then cast the result as if by the assignment operator. */ if (dt_node_is_dynamic(dnp->dn_left)) { dt_ident_t *idp; dt_xlator_t *dxp; dt_node_t *mnp; idp = dt_ident_resolve(dnp->dn_left->dn_ident); assert(idp->di_kind == DT_IDENT_XLSOU || idp->di_kind == DT_IDENT_XLPTR); dxp = idp->di_data; mnp = dt_xlator_member(dxp, dnp->dn_right->dn_string); assert(mnp != NULL); dxp->dx_ident->di_flags |= DT_IDFLG_CGREG; dxp->dx_ident->di_id = dnp->dn_left->dn_reg; dt_cg_node(mnp->dn_membexpr, dlp, drp); dnp->dn_reg = mnp->dn_membexpr->dn_reg; dt_cg_typecast(mnp->dn_membexpr, dnp, dlp, drp); dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG; dxp->dx_ident->di_id = 0; dt_regset_free(drp, dnp->dn_left->dn_reg); break; } ctfp = dnp->dn_left->dn_ctfp; type = ctf_type_resolve(ctfp, dnp->dn_left->dn_type); if (dnp->dn_op == DT_TOK_PTR) { type = ctf_type_reference(ctfp, type); type = ctf_type_resolve(ctfp, type); } if ((ctfp = dt_cg_membinfo(octfp = ctfp, type, dnp->dn_right->dn_string, &m)) == NULL) { yypcb->pcb_hdl->dt_ctferr = ctf_errno(octfp); longjmp(yypcb->pcb_jmpbuf, EDT_CTF); } if (m.ctm_offset != 0) { if ((reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); /* * If the offset is not aligned on a byte boundary, it * is a bit-field member and we will extract the value * bits below after we generate the appropriate load. */ dt_cg_setx(dlp, reg, m.ctm_offset / NBBY); instr = DIF_INSTR_FMT(DIF_OP_ADD, dnp->dn_left->dn_reg, reg, dnp->dn_left->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); dt_regset_free(drp, reg); } if (!(dnp->dn_flags & DT_NF_REF)) { uint_t ubit = dnp->dn_flags & DT_NF_USERLAND; /* * Save and restore DT_NF_USERLAND across dt_cg_load(): * we need the sign bit from dnp and the user bit from * dnp->dn_left in order to get the proper opcode. */ dnp->dn_flags |= (dnp->dn_left->dn_flags & DT_NF_USERLAND); instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp, m.ctm_type), dnp->dn_left->dn_reg, dnp->dn_left->dn_reg); dnp->dn_flags &= ~DT_NF_USERLAND; dnp->dn_flags |= ubit; dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); if (dnp->dn_flags & DT_NF_BITFIELD) dt_cg_field_get(dnp, dlp, drp, ctfp, &m); } dnp->dn_reg = dnp->dn_left->dn_reg; break; case DT_TOK_STRING: if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); assert(dnp->dn_kind == DT_NODE_STRING); stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string); if (stroff == -1L) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (stroff > DIF_STROFF_MAX) longjmp(yypcb->pcb_jmpbuf, EDT_STR2BIG); instr = DIF_INSTR_SETS((ulong_t)stroff, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; case DT_TOK_IDENT: /* * If the specified identifier is a variable on which we have * set the code generator register flag, then this variable * has already had code generated for it and saved in di_id. * Allocate a new register and copy the existing value to it. */ if (dnp->dn_kind == DT_NODE_VAR && (dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) { if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); instr = DIF_INSTR_MOV(dnp->dn_ident->di_id, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; } /* * Identifiers can represent function calls, variable refs, or * symbols. First we check for inlined variables, and handle * them by generating code for the inline parse tree, and then * casting the result to the inline's output type. */ if (dnp->dn_kind == DT_NODE_VAR && (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) { dt_idnode_t *inp = dnp->dn_ident->di_data; dt_cg_node(inp->din_root, dlp, drp); dnp->dn_reg = inp->din_root->dn_reg; dt_cg_typecast(inp->din_root, dnp, dlp, drp); break; } switch (dnp->dn_kind) { case DT_NODE_FUNC: { dt_ident_t *idp = dnp->dn_ident; if (idp->di_kind != DT_IDENT_FUNC) { yylineno = dnp->dn_line; xyerror(D_CG_EXPR, "%s %s( ) may not be " "called from a D expression (D program " "context required)\n", dt_idkind_name(idp->di_kind), idp->di_name); } dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp); if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); instr = DIF_INSTR_CALL( dnp->dn_ident->di_id, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; } case DT_NODE_VAR: if (dnp->dn_ident->di_kind == DT_IDENT_XLSOU || dnp->dn_ident->di_kind == DT_IDENT_XLPTR) { /* * This can only happen if we have translated * args[]. */ assert(dnp->dn_ident->di_id == DIF_VAR_ARGS); dt_cg_array_op(dnp, dlp, drp); break; } if (dnp->dn_ident->di_kind == DT_IDENT_ARRAY) { if (dnp->dn_ident->di_id > DIF_VAR_ARRAY_MAX) dt_cg_assoc_op(dnp, dlp, drp); else dt_cg_array_op(dnp, dlp, drp); break; } if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) op = DIF_OP_LDLS; else if (dnp->dn_ident->di_flags & DT_IDFLG_TLS) op = DIF_OP_LDTS; else op = DIF_OP_LDGS; dnp->dn_ident->di_flags |= DT_IDFLG_DIFR; instr = DIF_INSTR_LDV(op, dnp->dn_ident->di_id, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); break; case DT_NODE_SYM: { dtrace_hdl_t *dtp = yypcb->pcb_hdl; dtrace_syminfo_t *sip = dnp->dn_ident->di_data; GElf_Sym sym; if (dtrace_lookup_by_name(dtp, sip->dts_object, sip->dts_name, &sym, NULL) == -1) { xyerror(D_UNKNOWN, "cg failed for symbol %s`%s:" " %s\n", sip->dts_object, sip->dts_name, dtrace_errmsg(dtp, dtrace_errno(dtp))); } if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); dt_cg_xsetx(dlp, dnp->dn_ident, DT_LBL_NONE, dnp->dn_reg, sym.st_value); if (!(dnp->dn_flags & DT_NF_REF)) { instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp, dnp->dn_type), dnp->dn_reg, dnp->dn_reg); dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr)); } break; } default: xyerror(D_UNKNOWN, "internal error -- node type %u is " "not valid for an identifier\n", dnp->dn_kind); } break; case DT_TOK_INT: if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value); break; default: xyerror(D_UNKNOWN, "internal error -- token type %u is not a " "valid D compilation token\n", dnp->dn_op); }}voiddt_cg(dt_pcb_t *pcb, dt_node_t *dnp){ dif_instr_t instr; if (pcb->pcb_regs == NULL && (pcb->pcb_regs = dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); dt_regset_reset(pcb->pcb_regs); (void) dt_regset_alloc(pcb->pcb_regs); /* allocate %r0 */ if (pcb->pcb_inttab != NULL) dt_inttab_destroy(pcb->pcb_inttab); if ((pcb->pcb_inttab = dt_inttab_create(yypcb->pcb_hdl)) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); if (pcb->pcb_strtab != NULL) dt_strtab_destroy(pcb->pcb_strtab); if ((pcb->pcb_strtab = dt_strtab_create(BUFSIZ)) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); dt_irlist_destroy(&pcb->pcb_ir); dt_irlist_create(&pcb->pcb_ir); assert(pcb->pcb_dret == NULL); pcb->pcb_dret = dnp; if (dt_node_is_dynamic(dnp)) { dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result " "of dynamic type\n"); } dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs); instr = DIF_INSTR_RET(dnp->dn_reg); dt_regset_free(pcb->pcb_regs, dnp->dn_reg); dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -