예제 #1
0
static void transform_CEIL(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* Assuming:
	 *     ceil(x) = -floor(-x)
	 *
	 * After inlining floor:
	 *     ceil(x) = -(-x-frac(-x))
	 *
	 * After simplification:
	 *     ceil(x) = x+frac(-x)
	 */

	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, negate(inst->U.I.SrcReg[0]));
	emit2(c, inst->Prev, RC_OPCODE_ADD, inst->U.I.SaturateMode, inst->U.I.DstReg,
		inst->U.I.SrcReg[0], srcreg(RC_FILE_TEMPORARY, dst.Index));
	rc_remove_instruction(inst);
}
예제 #2
0
ssize_t process_unicorn_data( context_t *ctx, size_t ready )
{
	unicorn_config_t *cf = ctx->data;

	x_printf(ctx, "Entering process_unicorn_data()\n");
	if( ready >= cf->msgHdr.length ) {
		char *data_buffer = alloca( cf->msgHdr.length );
		u_ringbuf_read( &cf->input, data_buffer, cf->msgHdr.length );

		driver_data_t notification = { TYPE_DATA, ctx, {} };
		notification.event_data.bytes = cf->msgHdr.length;
		notification.event_data.data = data_buffer;
		emit2( ctx, EVENT_DATA_INCOMING, &notification );

		cf->flags &= ~(unsigned int)UNICORN_EXPECTING_DATA;
		return 0;
	}
	x_printf(ctx, "Leaving process_unicorn_data()\n");
	return -1;
}
예제 #3
0
/**
 * Approximate sin(x), where x is clamped to (-pi/2, pi/2).
 *
 * MUL tmp.xy, src, { 4/PI, -4/(PI^2) }
 * MAD tmp.x, tmp.y, |src|, tmp.x
 * MAD tmp.y, tmp.x, |tmp.x|, -tmp.x
 * MAD dest, tmp.y, weight, tmp.x
 */
static void sin_approx(
	struct radeon_compiler* c, struct rc_instruction * inst,
	struct rc_dst_register dst, struct rc_src_register src, const unsigned int* constants)
{
	unsigned int tempreg = rc_find_free_temporary(c);

	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, dstregtmpmask(tempreg, RC_MASK_XY),
		swizzle_xxxx(src),
		srcreg(RC_FILE_CONSTANT, constants[0]));
	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_X),
		swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
		absolute(swizzle_xxxx(src)),
		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)));
	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_Y),
		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)),
		absolute(swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg))),
		negate(swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg))));
	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dst,
		swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
		swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[0])),
		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)));
}
예제 #4
0
static void transform_r300_vertex_fix_LIT(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	unsigned constant_swizzle;
	int constant = rc_constants_add_immediate_scalar(&c->Program.Constants,
							 0.0000000000000000001,
							 &constant_swizzle);

	/* MOV dst, src */
	dst.WriteMask = RC_MASK_XYZW;
	emit1(c, inst->Prev, RC_OPCODE_MOV, 0,
		dst,
		inst->U.I.SrcReg[0]);

	/* MAX dst.y, src, 0.00...001 */
	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
		dstregtmpmask(dst.Index, RC_MASK_Y),
		srcreg(RC_FILE_TEMPORARY, dst.Index),
		srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle));

	inst->U.I.SrcReg[0] = srcreg(RC_FILE_TEMPORARY, dst.Index);
}
예제 #5
0
static void transform_SSG(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* result = sign(x)
	 *
	 *   CMP tmp0, -x, 1, 0
	 *   CMP tmp1, x, 1, 0
	 *   ADD result, tmp0, -tmp1;
	 */
	struct rc_dst_register dst0;
	unsigned tmp1;

	/* 0 < x */
	dst0 = try_to_reuse_dst(c, inst);
	emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
	      dst0,
	      negate(inst->U.I.SrcReg[0]),
	      builtin_one,
	      builtin_zero);

	/* x < 0 */
	tmp1 = rc_find_free_temporary(c);
	emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
	      dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
	      inst->U.I.SrcReg[0],
	      builtin_one,
	      builtin_zero);

	/* Either both are zero, or one of them is one and the other is zero. */
	/* result = tmp0 - tmp1 */
	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
	      inst->U.I.DstReg,
	      srcreg(RC_FILE_TEMPORARY, dst0.Index),
	      negate(srcreg(RC_FILE_TEMPORARY, tmp1)));

	rc_remove_instruction(inst);
}
예제 #6
0
ssize_t unicorn_handler(context_t *ctx, event_t event, driver_data_t *event_data)
{
	event_data_t   *data = 0L;
	event_child_t *child = 0L;

	unicorn_config_t *cf = (unicorn_config_t *) ctx->data;

	//x_printf(ctx, "<%s> Event = \"%s\" (%d)\n", ctx->name, event_map[event], event);

	if (event_data->type == TYPE_DATA)
		data = &event_data->event_data;
	else if( event_data->type == TYPE_CHILD )
		child = & event_data->event_child;

	switch (event) {
		case EVENT_INIT:
			{
				x_printf(ctx,"calling event add SIGQUIT\n");
				event_add( ctx, SIGQUIT, EH_SIGNAL );
				x_printf(ctx,"calling event add SIGTERM\n");
				event_add( ctx, SIGTERM, EH_SIGNAL );
				x_printf(ctx,"calling event 1000 EH_WANT_TICK\n");
				event_add( ctx, 1000, EH_WANT_TICK );

				cf->driver = config_get_item( ctx->config, "endpoint" );

				if( ! config_get_timeval( ctx->config, "retry", &cf->retry_time ) )
					cf->retry_time = 120*1000;

				if( cf->driver )
					start_service( &cf->modem, cf->driver, ctx->config, ctx, 0L );

				if( !cf->modem ) {
					logger( ctx, "Unable to launch modem driver. Exiting\n" );
					cf->state = UNICORN_STATE_ERROR;
					context_terminate( ctx );
					return -1;
				}

				cf->state = UNICORN_STATE_IDLE;
			}
			break;

		case EVENT_TERMINATE:
			{
				cf->pending_action_timeout = rel_time(0L);

				cf->flags |= UNICORN_TERMINATING; // In process of terminating the modem driver
				cf->state  = UNICORN_STATE_STOPPING; // In process of terminating self

				// Ensure 'exec' driver known not to restart when the modem driver terminates.
				// If the modem driver is something other than 'exec', this should be ignored.
				uint8_t flag = 0;
				driver_data_t notification = { TYPE_CUSTOM, ctx, {} };
				notification.event_custom = &flag;
				emit(cf->modem, EXEC_SET_RESPAWN, &notification);

				if( cf->driver_state == CMD_ST_ONLINE ) {
					x_printf(ctx,"Driver is online - sending disconnect\n");
					send_unicorn_command( ctx, CMD_DISCONNECT, CMD_ST_OFFLINE, 0, 0L );
				} else {
					x_printf(ctx,"Driver is offline - sending shutdown\n");
					send_unicorn_command( ctx, CMD_STATE, CMD_ST_OFFLINE, 0, 0L );
				}
			}
			break;

		case EVENT_RESTART:
			// This event is used to signal that the modem driver needs to resync.
			// set the 'reconnecting' flag and send a disconnect
			x_printf(ctx,"EVENT_RESTART: - sending disconnect to modem\n");
			//logger(ctx, "Sending disconnect command to modem driver");
			if( event_data->source == ctx->owner ) {
				cf->pending_action_timeout = rel_time(0L);
				cf->flags |= UNICORN_WAITING_FOR_CONNECT;
				if( cf->modem ) {
					x_printf(ctx, "Sending CMD_DISCONNECT to modem driver (%s)\n",cf->modem->name);
					if( (event_data->type == TYPE_CUSTOM) && event_data->event_custom ) {
						logger(ctx, "Sending abort command to modem driver due to unexpected disconnect");
						send_unicorn_command( ctx, CMD_ABORT, CMD_ST_OFFLINE, 0, 0L );
					} else {
						logger(ctx, "Sending disconnect command to modem driver");
						send_unicorn_command( ctx, CMD_DISCONNECT, CMD_ST_OFFLINE, 0, 0L );
					}
				} else {
					x_printf(ctx, "Modem driver not running.. doing nothing.\n");
				}
			} else {
				x_printf(ctx,"Forwarding EVENT_RESTART to owner (%s)\n",ctx->name);
				emit2( ctx, EVENT_RESTART, event_data);
			}
			break;

		case EVENT_CHILD:
			x_printf(ctx,"Got a message from a child (%s:%d).. probably starting\n", child->ctx->name, child->action);
			if ( child->ctx == cf->modem ) {
				if( child->action == CHILD_STARTING ) {
					cf->state = UNICORN_STATE_RUNNING;
					cf->flags &= ~(unsigned int) UNICORN_RESTARTING;
					// Assume ensure the first time the modem driver starts it skips the connection delay
					cf->flags |= UNICORN_FIRST_START;
				}

				if ( child->action == CHILD_STOPPED ) {
					x_printf(ctx,"Modem driver terminated - restart or terminate\n");
					// modem driver terminated.  Restart or exit.
					cf->state = UNICORN_STATE_IDLE;
					if ( cf->flags & UNICORN_TERMINATING ) {
						x_printf(ctx,"Terminating immediately\n");
						context_terminate( ctx );
					} else {
						x_printf(ctx,"Need to restart modem driver\n");
						cf->flags |= UNICORN_RESTARTING;
						cf->pending_action_timeout = rel_time(0L);
						// Reset the driver state, and notify the parent that we are offline
						cf->driver_state = CMD_ST_UNKNOWN;
						context_owner_notify( ctx, CHILD_EVENT, UNICORN_MODE_OFFLINE );
					}
				}
			}
			break;

		case EVENT_DATA_INCOMING:
		case EVENT_DATA_OUTGOING:
			if( event_data->source == cf->modem ) {

				size_t bytes = data->bytes;
				size_t offset = 0;

				while( bytes ) {

					size_t to_read = u_ringbuf_avail( &cf->input );
					if( to_read > bytes )
						to_read = bytes;

					u_ringbuf_write( &cf->input, &((char *)data->data)[offset], to_read );

					bytes -= to_read;
					offset += to_read;

					while(process_unicorn_packet(ctx) >= 0);
				}

				return (ssize_t) offset;
			} else {
				send_unicorn_command( ctx, CMD_DATA, CMD_ST_ONLINE, data->bytes,data->data);
				return (ssize_t) data->bytes;
			}

			break;

		case EVENT_READ:
			break;

		case EVENT_EXCEPTION:
			break;

		case EVENT_SIGNAL:
			x_printf(ctx,"Woa! Got a sign from the gods... %d\n", event_data->event_signal);
			if( event_data->event_signal == SIGQUIT || event_data->event_signal == SIGTERM )
				emit( ctx, EVENT_TERMINATE, 0L );
			break;

		case EVENT_TICK:
			{
				time_t now = rel_time(0L);

				// Handle case where a massive time shift due to NTP resync causes all timeouts to fire simultaneously
				// This is technically deprecated due to the use of rel_time()
				if( (now - cf->last_message) > MAXIMUM_SAFE_TIMEDELTA ) {
					logger(ctx, "WARNING: Resetting timeout due to RTC time change");
					cf->last_message = now;
				}

				if( ((now - cf->last_message) > UNICORN_KEEPALIVE_TIMEOUT ) && ( cf->driver_state != CMD_ST_UNKNOWN )) {

					if( ~ cf->flags & UNICORN_LAGGED ) {
						// Its been a couple of minutes since the last keepalive, reset the driver_state
						// to unknown and prompt for one.
						logger(ctx,"Forcing connection state request due to communications timeout.\n");
						cf->flags |= UNICORN_LAGGED;
						cf->retry_count = UNICORN_KEEPALIVE_RETRY_MAX;
					}

					if( cf->retry_count ) {
						send_unicorn_command( ctx, CMD_STATE, CMD_ST_OFFLINE, 0, 0L );
						cf->retry_count --;
					} else {
						// Its been a long time since the last message, despite prompting for one
						// restart the modem driver

						logger(ctx, "Communications timeout. Restarting modem driver.");
						uint8_t sig = SIGHUP;
						driver_data_t notification = { TYPE_CUSTOM, ctx, {} };
						notification.event_custom = &sig;

						emit( cf->modem, EVENT_RESTART, &notification );
					}
					cf->last_message = now;
				}

				if( (cf->flags & UNICORN_RESTARTING) && ((now - cf->pending_action_timeout) > UNICORN_RESTART_DELAY )) {
					x_printf(ctx,"Restart delay expired - restarting modem driver\n");
					cf->pending_action_timeout = rel_time(0L);
					if( cf->driver )
						start_service( &cf->modem, cf->driver, ctx->config, ctx, 0L );
				} else if( (cf->flags & UNICORN_RECONNECTING) && ((now - cf->pending_action_timeout) > cf->retry_time )) {
					x_printf(ctx,"Reconnect delay expired - attempting reconnect\n");
					cf->pending_action_timeout = rel_time(0L);
					cf->flags &= ~(unsigned int)UNICORN_RECONNECTING;
					if( cf->modem )
						send_unicorn_command(ctx, CMD_CONNECT, CMD_ST_ONLINE, 0, 0 );
				} else if( (cf->flags & UNICORN_WAITING_FOR_CONNECT) && ((now - cf->pending_action_timeout) > UNICORN_CONNECT_TIMEOUT )) {
					x_printf(ctx,"Timeout during connect - terminating modem driver\n");
					cf->flags &= ~(unsigned int) UNICORN_WAITING_FOR_CONNECT;
					cf->state = UNICORN_STATE_IDLE;
					if( cf->modem )
						emit( cf->modem, EVENT_TERMINATE, 0L );
				}

				if( (cf->flags & UNICORN_TERMINATING) && ((now - cf->pending_action_timeout) > UNICORN_PROCESS_TERMINATION_TIMEOUT)) {
					x_printf(ctx,"termination timeout - killing the modem driver with prejudice\n");
					cf->state = UNICORN_STATE_IDLE;
					if( cf->modem )
						context_terminate( cf->modem );
					context_terminate( ctx );
				}

				// Special case.. If I am expecting a data frame, and it takes too long to arrive,
				// reset state.
				if( (cf->flags & UNICORN_EXPECTING_DATA) && ((now - cf->last_message) > FRAME_TIMEOUT)) {
					x_printf(ctx,"FRAME TIMEOUT - resetting input buffer\n");
					u_ringbuf_init( &cf->input );
					cf->flags &= ~(unsigned int)UNICORN_EXPECTING_DATA;
				}

#ifndef NDEBUG
				size_t bytes = u_ringbuf_ready( &cf->input );
				if( bytes )
					x_printf(ctx,"Un-processed data in ring buffer... %d bytes\n",(int)bytes);
#endif
			}
			break;

		default:
			x_printf(ctx,"\n *\n *\n * Emitted some kind of event \"%s\" (%d)\n *\n *\n", event_map[event], event);
	}
	return 0;
}
예제 #7
0
/**
 * Definition of LIT (from ARB_fragment_program):
 *
 *  tmp = VectorLoad(op0);
 *  if (tmp.x < 0) tmp.x = 0;
 *  if (tmp.y < 0) tmp.y = 0;
 *  if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
 *  else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
 *  result.x = 1.0;
 *  result.y = tmp.x;
 *  result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
 *  result.w = 1.0;
 *
 * The longest path of computation is the one leading to result.z,
 * consisting of 5 operations. This implementation of LIT takes
 * 5 slots, if the subsequent optimization passes are clever enough
 * to pair instructions correctly.
 */
static void transform_LIT(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	unsigned int constant;
	unsigned int constant_swizzle;
	unsigned int temp;
	struct rc_src_register srctemp;

	constant = rc_constants_add_immediate_scalar(&c->Program.Constants, -127.999999, &constant_swizzle);

	if (inst->U.I.DstReg.WriteMask != RC_MASK_XYZW || inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
		struct rc_instruction * inst_mov;

		inst_mov = emit1(c, inst,
			RC_OPCODE_MOV, 0, inst->U.I.DstReg,
			srcreg(RC_FILE_TEMPORARY, rc_find_free_temporary(c)));

		inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
		inst->U.I.DstReg.Index = inst_mov->U.I.SrcReg[0].Index;
		inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
	}

	temp = inst->U.I.DstReg.Index;
	srctemp = srcreg(RC_FILE_TEMPORARY, temp);

	/* tmp.x = max(0.0, Src.x); */
	/* tmp.y = max(0.0, Src.y); */
	/* tmp.w = clamp(Src.z, -128+eps, 128-eps); */
	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
		dstregtmpmask(temp, RC_MASK_XYW),
		inst->U.I.SrcReg[0],
		swizzle(srcreg(RC_FILE_CONSTANT, constant),
			RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, constant_swizzle&3));
	emit2(c, inst->Prev, RC_OPCODE_MIN, 0,
		dstregtmpmask(temp, RC_MASK_Z),
		swizzle_wwww(srctemp),
		negate(srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle)));

	/* tmp.w = Pow(tmp.y, tmp.w) */
	emit1(c, inst->Prev, RC_OPCODE_LG2, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_yyyy(srctemp));
	emit2(c, inst->Prev, RC_OPCODE_MUL, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_wwww(srctemp),
		swizzle_zzzz(srctemp));
	emit1(c, inst->Prev, RC_OPCODE_EX2, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_wwww(srctemp));

	/* tmp.z = (tmp.x > 0) ? tmp.w : 0.0 */
	emit3(c, inst->Prev, RC_OPCODE_CMP, inst->U.I.SaturateMode,
		dstregtmpmask(temp, RC_MASK_Z),
		negate(swizzle_xxxx(srctemp)),
		swizzle_wwww(srctemp),
		builtin_zero);

	/* tmp.x, tmp.y, tmp.w = 1.0, tmp.x, 1.0 */
	emit1(c, inst->Prev, RC_OPCODE_MOV, inst->U.I.SaturateMode,
		dstregtmpmask(temp, RC_MASK_XYW),
		swizzle(srctemp, RC_SWIZZLE_ONE, RC_SWIZZLE_X, RC_SWIZZLE_ONE, RC_SWIZZLE_ONE));

	rc_remove_instruction(inst);
}
예제 #8
0
파일: ucode.c 프로젝트: wan2land/mini-c
void processOperator(SymbolTable *table, Node *ptr)
{
    int stIndex;

    switch(ptr->token.tokenNumber) {
        case ASSIGN_OP: {
            Node *lhs = ptr->son, *rhs = ptr->son->next;

            if (lhs->noderep == NONTERM) {
                lvalue = 1;
                processOperator(table, lhs);
                lvalue = 0;
            }

            if (rhs->noderep == NONTERM) {
                processOperator(table, rhs);
            } else {
                rv_emit(table, rhs);
            }

            if (lhs->noderep == TERMINAL)     {
                stIndex = lookup(table, lhs->token.tokenValue);
                if (stIndex == -1) {
                    fprintf(stderr, "undefined variable: %s\n", lhs->token.tokenValue);
                    return;
                }
                emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset);
            } else                             {
                emit0("sti");
            }
            break;
        }

        case ADD_ASSIGN: case SUB_ASSIGN: case MUL_ASSIGN:
        case DIV_ASSIGN: case MOD_ASSIGN: {
            Node *lhs = ptr->son, *rhs = ptr->son->next;
            int nodeNumber = ptr->token.tokenNumber;

            ptr->token.tokenNumber = ASSIGN_OP;

            if (lhs->noderep == NONTERM) {
                lvalue = 1;
                processOperator(table, lhs);
                lvalue = 0;
            }

            ptr->token.tokenNumber = nodeNumber;

            if (lhs->noderep == NONTERM) {
                processOperator(table, lhs);
            } else {
                rv_emit(table, lhs);
            }

            if (rhs->noderep == NONTERM) {
                processOperator(table, rhs);
            } else {
                rv_emit(table, rhs);
            }

            switch(ptr->token.tokenNumber) {
                case ADD_ASSIGN: emit0("add"); break;
                case SUB_ASSIGN: emit0("sub"); break;
                case MUL_ASSIGN: emit0("mult"); break;
                case DIV_ASSIGN: emit0("div"); break;
                case MOD_ASSIGN: emit0("mod"); break;
            }

            if (lhs->noderep == TERMINAL) {
                stIndex = lookup(table, lhs->token.tokenValue);
                if (stIndex == -1) {
                    fprintf(file, "undefined variable: %s\n", lhs->son->token.tokenValue);
                    return;
                }
                emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset);
            } else {
                emit0("sti");
            }
            break;
        }

        case ADD: case SUB: case MUL:  case DIV:  case MOD:
        case EQ:  case NE:  case GT:   case LT:   case GE:    case LE:
        case LOGICAL_AND:   case LOGICAL_OR: {
            Node *lhs = ptr->son, *rhs = ptr->son->next;

            if (lhs->noderep == NONTERM)  {
                processOperator(table, lhs);
            } else {
                rv_emit(table, lhs);
            }

            if (rhs->noderep == NONTERM)  {
                processOperator(table, rhs);
            } else {
                rv_emit(table, rhs);
            }

            switch(ptr->token.tokenNumber) {
                case ADD:         emit0("add");       break;
                case SUB:         emit0("sub");       break;
                case MUL:         emit0("mult");      break;
                case DIV:         emit0("div");       break;
                case MOD:         emit0("mod");       break;
                case EQ:          emit0("eq");        break;
                case NE:          emit0("ne");        break;
                case GT:          emit0("gt");        break;
                case LT:          emit0("lt");        break;
                case GE:          emit0("ge");        break;
                case LE:          emit0("le");        break;
                case LOGICAL_AND: emit0("and");       break;
                case LOGICAL_OR:  emit0("or");        break;
            }
            break;
        }
        case UNARY_MINUS:    case LOGICAL_NOT: {
            Node *p = ptr->son;

            if (p->noderep == NONTERM) {
                processOperator(table, p);
            } else {
                rv_emit(table, p);
            }

            switch(ptr->token.tokenNumber) {
                case UNARY_MINUS:    emit0("neg");        break;
                case LOGICAL_NOT:    emit0("not");        break;
            }
            break;
        }
        case INDEX: {
            Node *indexExp = ptr->son->next;

            if (indexExp->noderep == NONTERM) processOperator(table, indexExp); else rv_emit(table, indexExp);

            stIndex = lookup(table, ptr->son->token.tokenValue);
            if (stIndex == -1) {
                fprintf(file, "undefined variable: %s\n", ptr->son->token.tokenValue);
                return;
            }
            emit2("lda", table->rows[stIndex].base, table->rows[stIndex].offset);
            emit0("add");
            if (!lvalue)             {
                emit0("ldi");
            }
            break;
        }
        case PRE_INC:    case PRE_DEC:    case POST_INC:    case POST_DEC: {
            Node *p = ptr->son;
            Node *q;
            int stIndex;
            int amount = 1;

            if (p->noderep == NONTERM) {
                processOperator(table, p);
            } else {
                rv_emit(table, p);
            }

            q = p;
            while (q->noderep != TERMINAL)  {
                q = q->son;
            }

            if (!q || (q->token.tokenNumber != IDENT)) {
                fprintf(file, "increment/decrement operators can not be applied in expression\n");
                return;
            }
            stIndex = lookup(table, q->token.tokenValue);
            if (stIndex == -1) {
                return;
            }

            switch(ptr->token.tokenNumber) {
                case PRE_INC:    emit0("inc");    break;
                case PRE_DEC:    emit0("dec");    break;
                case POST_INC:   emit0("inc");    break;
                case POST_DEC:   emit0("dec");    break;
            }

            if (p->noderep == TERMINAL) {
                stIndex = lookup(table, p->token.tokenValue);
                if (stIndex == -1)  {
                    return;
                }

                emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset);
            } else if (p->token.tokenNumber == INDEX) {
                lvalue = 1;
                processOperator(table, p);
                lvalue = 0;
                emit0("swp");
                emit0("sti");
            } else fprintf(file, "error in increment/decrement operators\n");
            break;
        }
        case CALL: {
            Node *p = ptr->son;
            char *functionName;
            int stIndex;
            int noArguments;

            if (checkPredefined(table, p)) {
                break;
            }

            functionName = p->token.tokenValue;

            stIndex = lookup(rootTable, functionName);
      
            if (stIndex == -1) {
                fprintf(file, "%s: undefined function\n", functionName);
                break;
            }
            noArguments = rootTable->rows[stIndex].width;
      
            emit0("ldp");
            p = p->next->son;
            while (p)             {
                if (p->noderep == NONTERM) {
                    processOperator(table, p);
                } else {
                    rv_emit(table, p);
                }
                noArguments--;
                p = p->next;
            }

            if (noArguments > 0) {
                fprintf(file, "%s: too few actual arguments\n", functionName);
            }

            if (noArguments < 0) {
                fprintf(file, "%s: too many actual arguments\n", functionName);
            }

            emitJump("call", ptr->son->token.tokenValue);
            break;
        }
    }
}
예제 #9
0
파일: ucode.c 프로젝트: wan2land/mini-c
int checkPredefined(SymbolTable *table, Node *ptr)
{
    Node *p=ptr;
    char *functionName;
    int noArguments;
    int stIndex;

    functionName = p->token.tokenValue;
    if (strcmp(functionName, "read") == 0) {
        noArguments = 1;

        emit0("ldp");
        p = p->next->son;
        while (p) {
            if (p->noderep == NONTERM) {
                processOperator(table, p);
            } else {
                stIndex = lookup(table, p->token.tokenValue);
                if (stIndex == -1) {
                    return 0;
                }
                emit2("lda", table->rows[stIndex].base, table->rows[stIndex].offset);
            }
            noArguments--;
            p = p->next;
        }

        if (noArguments > 0) {
            fprintf(file, "%s: too few actual arguments\n", functionName);
        }

        if (noArguments < 0) {
            fprintf(file, "%s: too many actual arguments\n", functionName);
        }

        emitJump("call", functionName);
        return 1;
    } else if (strcmp(functionName, "write") == 0) {
        noArguments = 1;

        emit0("ldp");
        p = p->next->son;
        while (p) {
            if (p->noderep == NONTERM) {
                processOperator(table, p);
            } else {
                stIndex = lookup(table, p->token.tokenValue);
                if (stIndex == -1) return 0;
                emit2("lod", table->rows[stIndex].base, table->rows[stIndex].offset);
            }
            noArguments--;
            p=p->next;
        }

        if (noArguments > 0) {
            fprintf(file, "%s: too few actual arguments\n", functionName);
        }

        if (noArguments < 0) {
            fprintf(file, "%s: too many actual arguments\n", functionName);
        }

        emitJump("call", functionName);
        return 1;
    } else if (strcmp(functionName, "lf") == 0) {
        emitJump("call", functionName);
        return 1;
    }

    return 0;
}
예제 #10
0
static int compile_operator(compiletime c)
{
	int operand_count = 0;

	const char *op = pop_operator(c, &operand_count);

	if (!strcmp(op, "*"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, multiply_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "**"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, power_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "/"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, divide_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "%"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, modulo_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "="))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, assign_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, ";"))
	{
	}
	else if (!strcmp(op, "if"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, if_tc, val1);
		DEBUG printf("emit '%s' %s\n", val1, op);
		c->level++;
	}
	else if (!strcmp(op, "else"))
	{
		c->level--;
		emit1(c, else_tc);
		c->level++;
		DEBUG printf("emit %s\n", op);
	}
	else if (!strcmp(op, "fi"))
	{
		c->level--;
		emit1(c, fi_tc);
		DEBUG printf("emit %s\n", op);
	}
	else if (!strcmp(op, "!"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, not_tc, val1);
		DEBUG printf("emit '%s' %s\n", val1, op);
	}
	else if (!strcmp(op, "+"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, add_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "-"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, subtract_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, ">"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, gt_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, ">="))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, geq_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "<="))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, leq_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "<"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, lt_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "&&"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, and_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "||"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, or_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "^^"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, xor_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "&"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, bit_and_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "|"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, bit_or_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "^"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, bit_xor_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "~"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, bit_negate_tc, val1);
		DEBUG printf("emit %s %s\n", val1, op);
	}
	else if (!strcmp(op, "<<"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, shift_left_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, ">>"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, shift_right_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, ">>>"))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, logical_shift_right_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "=="))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, eq_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "!="))
	{
		const char *val2 = pop_operand(c);
		const char *val1 = pop_operand(c);
		emit3(c, neq_tc, val1, val2);
		DEBUG printf("emit %s %s %s\n", val1, op, val2);
	}
	else if (!strcmp(op, "fold-case"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_fold_case_tc, val1);
		DEBUG printf("emit %s %s\n", op, val1);
	}
	else if (!strcmp(op, "size"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_size_tc, val1);
		DEBUG printf("emit %s %s\n", op, val1);
	}
	else if (!strcmp(op, "print"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_print_tc, val1);
		DEBUG printf("emit %s %s\n", op, val1);
	}
	else if (!strcmp(op, "jday"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_jday_tc, val1);
		DEBUG printf("emit %s %s\n", op, val1);
	}
	else if (!strcmp(op, "dow"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_dow_tc, val1);
		DEBUG printf("emit %s %s\n", op, val1);
	}
	else if (!strcmp(op, "equals"))
	{
		emit_code(c, func_eq_tc, operand_count);

		while (operand_count--)
		{
			const char *val1 = pop_operand(c);
			emit_value(c, val1);
			DEBUG printf("emit %s '%s'\n", op, val1);
		}
	}
	else if (!strcmp(op, "contains"))
	{
		emit_code(c, func_contains_tc, operand_count);

		while (operand_count--)
		{
			const char *val1 = pop_operand(c);
			emit_value(c, val1);
			DEBUG printf("emit %s '%s'\n", op, val1);
		}
	}
	else if (!strcmp(op, "begins-with"))
	{
		emit_code(c, func_begins_with_tc, operand_count);

		while (operand_count--)
		{
			const char *val1 = pop_operand(c);
			emit_value(c, val1);
			DEBUG printf("emit %s '%s'\n", op, val1);
		}
	}
	else if (!strcmp(op, "ends-with"))
	{
		emit_code(c, func_ends_with_tc, operand_count);

		while (operand_count--)
		{
			const char *val1 = pop_operand(c);
			emit_value(c, val1);
			DEBUG printf("emit %s '%s'\n", op, val1);
		}
	}
	else if (!strcmp(op, "int"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_is_int_tc, val1);
		DEBUG printf("emit %s '%s'\n", op, val1);
	}
	else if (!strcmp(op, "real"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_is_real_tc, val1);
		DEBUG printf("emit %s '%s'\n", op, val1);
	}
	else if (!strcmp(op, "nan"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_is_nan_tc, val1);
		DEBUG printf("emit %s '%s'\n", op, val1);
	}
	else if (!strcmp(op, "string"))
	{
		const char *val1 = pop_operand(c);
		emit2(c, func_is_string_tc, val1);
		DEBUG printf("emit %s '%s'\n", op, val1);
	}
	else if (!strcmp(op, "("))
	{
		return 1;
	}
	else if (!strcmp(op, ")"))
	{
		return 1;
	}
	else
	{
		DEBUG printf("bad operator '%s'\n", op);
		return 0;
	}

	push_operand(c, "_STACK");
	return 1;
}