⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dt_cg.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 4 页
字号:
			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);		if (dstsize < srcsize)			n = sizeof (uint64_t) * NBBY - dstsize * NBBY;		else			n = sizeof (uint64_t) * NBBY - srcsize * NBBY;		dt_cg_setx(dlp, reg, n);		instr = DIF_INSTR_FMT(DIF_OP_SLL,		    src->dn_reg, reg, dst->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?		    DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		dt_regset_free(drp, reg);	}}/* * Generate code to push the specified argument list on to the tuple stack. * We use this routine for handling subroutine calls and associative arrays. * We must first generate code for all subexpressions before loading the stack * because any subexpression could itself require the use of the tuple stack. * This holds a number of registers equal to the number of arguments, but this * is not a huge problem because the number of arguments can't exceed the * number of tuple register stack elements anyway.  At most one extra register * is required (either by dt_cg_typecast() or for dtdt_size, below).  This * implies that a DIF implementation should offer a number of general purpose * registers at least one greater than the number of tuple registers. */static voiddt_cg_arglist(dt_ident_t *idp, dt_node_t *args,    dt_irlist_t *dlp, dt_regset_t *drp){	const dt_idsig_t *isp = idp->di_data;	dt_node_t *dnp;	int i = 0;	for (dnp = args; dnp != NULL; dnp = dnp->dn_list)		dt_cg_node(dnp, dlp, drp);	dt_irlist_append(dlp,	    dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));	for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {		dtrace_diftype_t t;		dif_instr_t instr;		uint_t op;		int reg;		dt_node_diftype(dnp, &t);		isp->dis_args[i].dn_reg = dnp->dn_reg; /* re-use register */		dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);		isp->dis_args[i].dn_reg = -1;		if (t.dtdt_flags & DIF_TF_BYREF)			op = DIF_OP_PUSHTR;		else			op = DIF_OP_PUSHTV;		if (t.dtdt_size != 0) {			if ((reg = dt_regset_alloc(drp)) == -1)				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);			dt_cg_setx(dlp, reg, t.dtdt_size);		} else			reg = DIF_REG_R0;		instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		dt_regset_free(drp, dnp->dn_reg);		if (reg != DIF_REG_R0)			dt_regset_free(drp, reg);	}	if (i > yypcb->pcb_hdl->dt_conf.dtc_diftupregs)		longjmp(yypcb->pcb_jmpbuf, EDT_NOTUPREG);}static voiddt_cg_arithmetic_op(dt_node_t *dnp, dt_irlist_t *dlp,    dt_regset_t *drp, uint_t op){	int is_ptr_op = (dnp->dn_op == DT_TOK_ADD || dnp->dn_op == DT_TOK_SUB ||	    dnp->dn_op == DT_TOK_ADD_EQ || dnp->dn_op == DT_TOK_SUB_EQ);	int lp_is_ptr = dt_node_is_pointer(dnp->dn_left);	int rp_is_ptr = dt_node_is_pointer(dnp->dn_right);	dif_instr_t instr;	if (lp_is_ptr && rp_is_ptr) {		assert(dnp->dn_op == DT_TOK_SUB);		is_ptr_op = 0;	}	dt_cg_node(dnp->dn_left, dlp, drp);	if (is_ptr_op && rp_is_ptr)		dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_left->dn_reg);	dt_cg_node(dnp->dn_right, dlp, drp);	if (is_ptr_op && lp_is_ptr)		dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_right->dn_reg);	instr = DIF_INSTR_FMT(op, dnp->dn_left->dn_reg,	    dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, dnp->dn_right->dn_reg);	dnp->dn_reg = dnp->dn_left->dn_reg;	if (lp_is_ptr && rp_is_ptr)		dt_cg_ptrsize(dnp->dn_right,		    dlp, drp, DIF_OP_UDIV, dnp->dn_reg);}static uint_tdt_cg_stvar(const dt_ident_t *idp){	static const uint_t aops[] = { DIF_OP_STGAA, DIF_OP_STTAA, DIF_OP_NOP };	static const uint_t sops[] = { DIF_OP_STGS, DIF_OP_STTS, DIF_OP_STLS };	uint_t i = (((idp->di_flags & DT_IDFLG_LOCAL) != 0) << 1) |	    ((idp->di_flags & DT_IDFLG_TLS) != 0);	return (idp->di_kind == DT_IDENT_ARRAY ? aops[i] : sops[i]);}static voiddt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op){	ctf_file_t *ctfp = dnp->dn_ctfp;	dif_instr_t instr;	ctf_id_t type;	ssize_t size = 1;	int reg;	if (dt_node_is_pointer(dnp)) {		type = ctf_type_resolve(ctfp, dnp->dn_type);		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));	}	dt_cg_node(dnp->dn_child, dlp, drp);	dnp->dn_reg = dnp->dn_child->dn_reg;	if ((reg = dt_regset_alloc(drp)) == -1)		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);	dt_cg_setx(dlp, reg, size);	instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, reg);	/*	 * If we are modifying a variable, generate an stv instruction from	 * the variable specified by the identifier.  If we are storing to a	 * memory address, generate code again for the left-hand side using	 * DT_NF_REF to get the address, and then generate a store to it.	 * In both paths, we store the value in dnp->dn_reg (the new value).	 */	if (dnp->dn_child->dn_kind == DT_NODE_VAR) {		dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);		idp->di_flags |= DT_IDFLG_DIFW;		instr = DIF_INSTR_STV(dt_cg_stvar(idp),		    idp->di_id, dnp->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	} else {		uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;		assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);		assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);		dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */		dt_cg_node(dnp->dn_child, dlp, drp);		dt_cg_store(dnp, dlp, drp, dnp->dn_child);		dt_regset_free(drp, dnp->dn_child->dn_reg);		dnp->dn_left->dn_flags &= ~DT_NF_REF;		dnp->dn_left->dn_flags |= rbit;	}}static voiddt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,    dt_regset_t *drp, uint_t op){	ctf_file_t *ctfp = dnp->dn_ctfp;	dif_instr_t instr;	ctf_id_t type;	ssize_t size = 1;	int nreg;	if (dt_node_is_pointer(dnp)) {		type = ctf_type_resolve(ctfp, dnp->dn_type);		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));	}	dt_cg_node(dnp->dn_child, dlp, drp);	dnp->dn_reg = dnp->dn_child->dn_reg;	if ((nreg = dt_regset_alloc(drp)) == -1)		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);	dt_cg_setx(dlp, nreg, size);	instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	/*	 * If we are modifying a variable, generate an stv instruction from	 * the variable specified by the identifier.  If we are storing to a	 * memory address, generate code again for the left-hand side using	 * DT_NF_REF to get the address, and then generate a store to it.	 * In both paths, we store the value from 'nreg' (the new value).	 */	if (dnp->dn_child->dn_kind == DT_NODE_VAR) {		dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);		idp->di_flags |= DT_IDFLG_DIFW;		instr = DIF_INSTR_STV(dt_cg_stvar(idp), idp->di_id, nreg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	} else {		uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;		int oreg = dnp->dn_reg;		assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);		assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);		dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */		dt_cg_node(dnp->dn_child, dlp, drp);		dnp->dn_reg = nreg;		dt_cg_store(dnp, dlp, drp, dnp->dn_child);		dnp->dn_reg = oreg;		dt_regset_free(drp, dnp->dn_child->dn_reg);		dnp->dn_left->dn_flags &= ~DT_NF_REF;		dnp->dn_left->dn_flags |= rbit;	}	dt_regset_free(drp, nreg);}/* * Determine if we should perform signed or unsigned comparison for an OP2. * If both operands are of arithmetic type, perform the usual arithmetic * conversions to determine the common real type for comparison [ISOC 6.5.8.3]. */static intdt_cg_compare_signed(dt_node_t *dnp){	dt_node_t dn;	if (dt_node_is_string(dnp->dn_left) ||	    dt_node_is_string(dnp->dn_right))		return (1); /* strings always compare signed */	else if (!dt_node_is_arith(dnp->dn_left) ||	    !dt_node_is_arith(dnp->dn_right))		return (0); /* non-arithmetic types always compare unsigned */	bzero(&dn, sizeof (dn));	dt_node_promote(dnp->dn_left, dnp->dn_right, &dn);	return (dn.dn_flags & DT_NF_SIGNED);}static voiddt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op){	uint_t lbl_true = dt_irlist_label(dlp);	uint_t lbl_post = dt_irlist_label(dlp);	dif_instr_t instr;	uint_t opc;	dt_cg_node(dnp->dn_left, dlp, drp);	dt_cg_node(dnp->dn_right, dlp, drp);	if (dt_node_is_string(dnp->dn_left) || dt_node_is_string(dnp->dn_right))		opc = DIF_OP_SCMP;	else		opc = DIF_OP_CMP;	instr = DIF_INSTR_CMP(opc, dnp->dn_left->dn_reg, dnp->dn_right->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, dnp->dn_right->dn_reg);	dnp->dn_reg = dnp->dn_left->dn_reg;	instr = DIF_INSTR_BRANCH(op, lbl_true);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));}/* * Code generation for the ternary op requires some trickery with the assembler * in order to conserve registers.  We generate code for dn_expr and dn_left * and free their registers so they do not have be consumed across codegen for * dn_right.  We insert a dummy MOV at the end of dn_left into the destination * register, which is not yet known because we haven't done dn_right yet, and * save the pointer to this instruction node.  We then generate code for * dn_right and use its register as our output.  Finally, we reach back and * patch the instruction for dn_left to move its output into this register. */static voiddt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	uint_t lbl_false = dt_irlist_label(dlp);	uint_t lbl_post = dt_irlist_label(dlp);	dif_instr_t instr;	dt_irnode_t *dip;	dt_cg_node(dnp->dn_expr, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_expr->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, dnp->dn_expr->dn_reg);	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_node(dnp->dn_left, dlp, drp);	instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, DIF_REG_R0);	dip = dt_cg_node_alloc(DT_LBL_NONE, instr); /* save dip for below */	dt_irlist_append(dlp, dip);	dt_regset_free(drp, dnp->dn_left->dn_reg);	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, DIF_INSTR_NOP));	dt_cg_node(dnp->dn_right, dlp, drp);	dnp->dn_reg = dnp->dn_right->dn_reg;	/*	 * Now that dn_reg is assigned, reach back and patch the correct MOV	 * instruction into the tail of dn_left.  We know dn_reg was unused	 * at that point because otherwise dn_right couldn't have allocated it.	 */	dip->di_instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));}static voiddt_cg_logical_and(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	uint_t lbl_false = dt_irlist_label(dlp);	uint_t lbl_post = dt_irlist_label(dlp);	dif_instr_t instr;	dt_cg_node(dnp->dn_left, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, dnp->dn_left->dn_reg);	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_node(dnp->dn_right, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dnp->dn_reg = dnp->dn_right->dn_reg;	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_setx(dlp, dnp->dn_reg, 1);	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));}static voiddt_cg_logical_xor(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	uint_t lbl_next = dt_irlist_label(dlp);	uint_t lbl_tail = dt_irlist_label(dlp);	dif_instr_t instr;	dt_cg_node(dnp->dn_left, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_next);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_setx(dlp, dnp->dn_left->dn_reg, 1);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_next, DIF_INSTR_NOP));	dt_cg_node(dnp->dn_right, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_tail);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_setx(dlp, dnp->dn_right->dn_reg, 1);	instr = DIF_INSTR_FMT(DIF_OP_XOR, dnp->dn_left->dn_reg,	    dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_tail, instr));	dt_regset_free(drp, dnp->dn_right->dn_reg);	dnp->dn_reg = dnp->dn_left->dn_reg;}static voiddt_cg_logical_or(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	uint_t lbl_true = dt_irlist_label(dlp);	uint_t lbl_false = dt_irlist_label(dlp);	uint_t lbl_post = dt_irlist_label(dlp);	dif_instr_t instr;	dt_cg_node(dnp->dn_left, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, dnp->dn_left->dn_reg);	instr = DIF_INSTR_BRANCH(DIF_OP_BNE, lbl_true);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_node(dnp->dn_right, dlp, drp);	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dnp->dn_reg = dnp->dn_right->dn_reg;	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -