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

📄 dt_cg.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 4 页
字号:
static voiddt_cg_logical_neg(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	uint_t lbl_zero = dt_irlist_label(dlp);	uint_t lbl_post = dt_irlist_label(dlp);	dif_instr_t instr;	dt_cg_node(dnp->dn_child, dlp, drp);	dnp->dn_reg = dnp->dn_child->dn_reg;	instr = DIF_INSTR_TST(dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_zero);	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_zero, dnp->dn_reg, 1);	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));}static voiddt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	dif_instr_t instr;	/*	 * If we are performing a structure assignment of a translated type,	 * we must instantiate all members and create a snapshot of the object	 * in scratch space.  We allocs a chunk of memory, generate code for	 * each member, and then set dnp->dn_reg to the scratch object address.	 */	if (dt_node_is_dynamic(dnp->dn_right) &&	    dnp->dn_right->dn_ident->di_kind == DT_IDENT_XLSOU) {		ctf_membinfo_t ctm;		dt_xlator_t *dxp;		dt_node_t *mnp, dn, mn;		int r1, r2;		/*		 * Create two fake dt_node_t's representing operator "." and a		 * right-hand identifier child node.  These will be repeatedly		 * modified according to each instantiated member so that we		 * can pass them to dt_cg_store() and effect a member store.		 */		bzero(&dn, sizeof (dt_node_t));		dn.dn_kind = DT_NODE_OP2;		dn.dn_op = DT_TOK_DOT;		dn.dn_left = dnp;		dn.dn_right = &mn;		bzero(&mn, sizeof (dt_node_t));		mn.dn_kind = DT_NODE_IDENT;		mn.dn_op = DT_TOK_IDENT;		/*		 * Allocate a register for our scratch data pointer.  First we		 * set it to the size of our data structure, and then replace		 * it with the result of an allocs of the specified size.		 */		if ((r1 = dt_regset_alloc(drp)) == -1)			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);		dxp = dt_ident_resolve(dnp->dn_right->dn_ident)->di_data;		dt_cg_setx(dlp, r1,		    ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));		instr = DIF_INSTR_ALLOCS(r1, r1);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		/*		 * When dt_cg_asgn_op() is called, we have already generated		 * code for dnp->dn_right, which is the translator input.  We		 * now associate this register with the translator's input		 * identifier so it can be referenced during our member loop.		 */		dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;		dxp->dx_ident->di_id = dnp->dn_right->dn_reg;		for (mnp = dxp->dx_members; mnp != NULL; mnp = mnp->dn_list) {			/*			 * Generate code for the translator member expression,			 * and then cast the result to the member type.			 */			dt_cg_node(mnp->dn_membexpr, dlp, drp);			mnp->dn_reg = mnp->dn_membexpr->dn_reg;			dt_cg_typecast(mnp->dn_membexpr, mnp, dlp, drp);			/*			 * Ask CTF for the offset of the member so we can store			 * to the appropriate offset.  This call has already			 * been done once by the parser, so it should succeed.			 */			if (ctf_member_info(dxp->dx_dst_ctfp, dxp->dx_dst_base,			    mnp->dn_membname, &ctm) == CTF_ERR) {				yypcb->pcb_hdl->dt_ctferr =				    ctf_errno(dxp->dx_dst_ctfp);				longjmp(yypcb->pcb_jmpbuf, EDT_CTF);			}			/*			 * If the destination member is at offset 0, store the			 * result directly to r1 (the scratch buffer address).			 * Otherwise allocate another temporary for the offset			 * and add r1 to it before storing the result.			 */			if (ctm.ctm_offset != 0) {				if ((r2 = dt_regset_alloc(drp)) == -1)					longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);				/*				 * Add the member offset rounded down to the				 * nearest byte.  If the offset was not aligned				 * on a byte boundary, this member is a bit-				 * field and dt_cg_store() will handle masking.				 */				dt_cg_setx(dlp, r2, ctm.ctm_offset / NBBY);				instr = DIF_INSTR_FMT(DIF_OP_ADD, r1, r2, r2);				dt_irlist_append(dlp,				    dt_cg_node_alloc(DT_LBL_NONE, instr));				dt_node_type_propagate(mnp, &dn);				dn.dn_right->dn_string = mnp->dn_membname;				dn.dn_reg = r2;				dt_cg_store(mnp, dlp, drp, &dn);				dt_regset_free(drp, r2);			} else {				dt_node_type_propagate(mnp, &dn);				dn.dn_right->dn_string = mnp->dn_membname;				dn.dn_reg = r1;				dt_cg_store(mnp, dlp, drp, &dn);			}			dt_regset_free(drp, mnp->dn_reg);		}		dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;		dxp->dx_ident->di_id = 0;		assert(dnp->dn_reg == dnp->dn_right->dn_reg);		dt_regset_free(drp, dnp->dn_right->dn_reg);		dnp->dn_reg = r1;	}	/*	 * If we are storing to 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 assume dnp->dn_reg already has the new value.	 */	if (dnp->dn_left->dn_kind == DT_NODE_VAR) {		dt_ident_t *idp = dt_ident_resolve(dnp->dn_left->dn_ident);		if (idp->di_kind == DT_IDENT_ARRAY)			dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);		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_left->dn_flags & DT_NF_REF;		assert(dnp->dn_left->dn_flags & DT_NF_WRITABLE);		assert(dnp->dn_left->dn_flags & DT_NF_LVALUE);		dnp->dn_left->dn_flags |= DT_NF_REF; /* force pass-by-ref */		dt_cg_node(dnp->dn_left, dlp, drp);		dt_cg_store(dnp, dlp, drp, dnp->dn_left);		dt_regset_free(drp, dnp->dn_left->dn_reg);		dnp->dn_left->dn_flags &= ~DT_NF_REF;		dnp->dn_left->dn_flags |= rbit;	}}static voiddt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	dif_instr_t instr;	uint_t op;	assert(dnp->dn_kind == DT_NODE_VAR);	assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));	assert(dnp->dn_args != NULL);	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);	if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)		op = DIF_OP_LDTAA;	else		op = DIF_OP_LDGAA;	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));	/*	 * If the associative array is a pass-by-reference type, then we are	 * loading its value as a pointer to either load or store through it.	 * The array element in question may not have been faulted in yet, in	 * which case DIF_OP_LD*AA will return zero.  We append an epilogue	 * of instructions similar to the following:	 *	 *	  ld?aa	 id, %r1	! base ld?aa instruction above	 *	  tst	 %r1		! start of epilogue	 *   +--- bne	 label	 *   |    setx	 size, %r1	 *   |    allocs %r1, %r1	 *   |    st?aa	 id, %r1	 *   |    ld?aa	 id, %r1	 *   v	 * label: < rest of code >	 *	 * The idea is that we allocs a zero-filled chunk of scratch space and	 * do a DIF_OP_ST*AA to fault in and initialize the array element, and	 * then reload it to get the faulted-in address of the new variable	 * storage.  This isn't cheap, but pass-by-ref associative array values	 * are (thus far) uncommon and the allocs cost only occurs once.  If	 * this path becomes important to DTrace users, we can improve things	 * by adding a new DIF opcode to fault in associative array elements.	 */	if (dnp->dn_flags & DT_NF_REF) {		uint_t stvop = op == DIF_OP_LDTAA ? DIF_OP_STTAA : DIF_OP_STGAA;		uint_t label = dt_irlist_label(dlp);		instr = DIF_INSTR_TST(dnp->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		instr = DIF_INSTR_BRANCH(DIF_OP_BNE, label);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		dt_cg_setx(dlp, dnp->dn_reg, dt_node_type_size(dnp));		instr = DIF_INSTR_ALLOCS(dnp->dn_reg, dnp->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		dnp->dn_ident->di_flags |= DT_IDFLG_DIFW;		instr = DIF_INSTR_STV(stvop, dnp->dn_ident->di_id, dnp->dn_reg);		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));		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));		dt_irlist_append(dlp, dt_cg_node_alloc(label, DIF_INSTR_NOP));	}}static voiddt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	dif_instr_t instr;	uint_t op;	uintmax_t saved = dnp->dn_args->dn_value;	dt_arg_t *argp;	size_t size;	int reg, n;	assert(dnp->dn_kind == DT_NODE_VAR);	assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));	assert(dnp->dn_args != NULL);	assert(dnp->dn_args->dn_kind == DT_NODE_INT);	assert(dnp->dn_args->dn_list == NULL);	/*	 * If this is a reference in the args[] array, we're going to examine	 * our context to see if the value needs to be modified for the	 * purposes of remapping.	 */	if (dnp->dn_ident->di_id == DIF_VAR_ARGS) {		for (argp = yypcb->pcb_pargs; argp != NULL;		    argp = argp->da_next) {			if (argp->da_ndx == saved) {				dnp->dn_args->dn_value = argp->da_mapping;				break;			}		}	}	dt_cg_node(dnp->dn_args, dlp, drp);	dnp->dn_args->dn_value = saved;	dnp->dn_reg = dnp->dn_args->dn_reg;	if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)		op = DIF_OP_LDTA;	else		op = DIF_OP_LDGA;	dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;	instr = DIF_INSTR_LDA(op, dnp->dn_ident->di_id,	    dnp->dn_args->dn_reg, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	/*	 * If this is a reference to the args[] array, we need to take the	 * additional step of explicitly eliminating any bits larger than the	 * type size: the DIF interpreter in the kernel will always give us	 * the raw (64-bit) argument value, and any bits larger than the type	 * size may be junk.  As a practical matter, this arises only on	 * 64-bit architectures and only when the argument index is larger	 * than the number of arguments passed directly to DTrace:  if a 8-,	 * 16- or 32-bit argument must be retrieved from the stack, it is	 * possible (and it some cases, likely) that the upper bits will be	 * garbage.	 */	if (dnp->dn_ident->di_id != DIF_VAR_ARGS || !dt_node_is_scalar(dnp))		return;	if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))		return;	if ((reg = dt_regset_alloc(drp)) == -1)		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);	assert(size < sizeof (uint64_t));	n = sizeof (uint64_t) * NBBY - size * NBBY;	dt_cg_setx(dlp, reg, n);	instr = DIF_INSTR_FMT(DIF_OP_SLL, dnp->dn_reg, reg, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	instr = DIF_INSTR_FMT((dnp->dn_flags & DT_NF_SIGNED) ?	    DIF_OP_SRA : DIF_OP_SRL, dnp->dn_reg, reg, dnp->dn_reg);	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));	dt_regset_free(drp, reg);}static voiddt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp){	ctf_file_t *ctfp = dnp->dn_ctfp;	ctf_file_t *octfp;	ctf_membinfo_t m;	ctf_id_t type;	dif_instr_t instr;	ssize_t stroff;	uint_t op;	int reg;	switch (dnp->dn_op) {	case DT_TOK_COMMA:		dt_cg_node(dnp->dn_left, dlp, drp);		dt_regset_free(drp, dnp->dn_left->dn_reg);		dt_cg_node(dnp->dn_right, dlp, drp);		dnp->dn_reg = dnp->dn_right->dn_reg;		break;	case DT_TOK_ASGN:		dt_cg_node(dnp->dn_right, dlp, drp);		dnp->dn_reg = dnp->dn_right->dn_reg;		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_ADD_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_SUB_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_MUL_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_DIV_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp,		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_MOD_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp,		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_AND_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_XOR_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_OR_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_LSH_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_RSH_EQ:		dt_cg_arithmetic_op(dnp, dlp, drp,		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL);		dt_cg_asgn_op(dnp, dlp, drp);		break;	case DT_TOK_QUESTION:		dt_cg_ternary_op(dnp, dlp, drp);		break;	case DT_TOK_LOR:		dt_cg_logical_or(dnp, dlp, drp);		break;	case DT_TOK_LXOR:		dt_cg_logical_xor(dnp, dlp, drp);		break;	case DT_TOK_LAND:		dt_cg_logical_and(dnp, dlp, drp);		break;	case DT_TOK_BOR:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);		break;	case DT_TOK_XOR:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);		break;	case DT_TOK_BAND:		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);		break;	case DT_TOK_EQU:		dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BE);		break;	case DT_TOK_NEQ:		dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BNE);		break;	case DT_TOK_LT:

⌨️ 快捷键说明

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