target/whirl.c
static WhirlCodeSegment *generate_jump_for_table(WhirlCodeSegment *last_segment, RingState state, int jump_amount, unsigned length) {
    RingState start_state = state;
    WhirlCodeSegment *segment = NULL;

    // We may not end up being able to create a jump aligned how we would like inside the
    // length given to us, so we do a loop here to try out different lengths, and then pad
    // them out to match the length we're trying for
    for (int i = 0; i < 200; i++) {
        size_t actual_len = length - i;
        int actual_jump = jump_amount - i;
        state = start_state;

        segment = new_segment(NULL, last_segment);
        set_mem(segment, &state, -actual_jump);
        generate_op_command(segment, &state, OP_LOAD);
        set_math_ring_clockwise(segment, &state);

        if (state.op_dir != CLOCKWISE) {
            emit_zero(segment, &state);
            emit_one(segment, &state);
        }

        while (segment->len < actual_len &&
            (actual_len - segment->len + state.cur_op_pos - 2) % NUM_CMDS_PER_RING != OP_IF)
        {
            emit_zero(segment, &state);
            emit_one(segment, &state);
            emit_one(segment, &state);
            emit_zero(segment, &state);
            emit_one(segment, &state);
        }

        // We've exceeded the length without aligning with the OP_IF command,
        // so we give up on this length and try again
        if (segment->len >= actual_len) {
            free_segments(segment);
            segment = NULL;
            continue;
        }

        while (segment->len < actual_len - 2) {
            emit_one(segment, &state);
        }

        emit_zero(segment, &state);
        emit_zero(segment, &state);

        for (int j = 0; j < i; j++) {
            emit_zero(segment, &state);
        }

        return segment;
    }

    return segment;
}
// Generates a jump instruction for the end of program jump table. Given the length that
// the jump segment must be, and the amount backwards it has to jump at the end, it will
// return a segment that will perform that jump, or a null pointer if it was unable to
// create a segment in the given size
Generates a jump instruction for the end of program jump table. Given the length that
the jump segment must be, and the amount backwards it has to jump at the end, it will
return a segment that will perform that jump, or a null pointer if it was unable to
create a segment in the given size
Generates a jump instruction for the end of program jump table . Given the length that the jump segment must be and the amount backwards it has to jump at the end it will return a segment that will perform that jump or a null pointer if it was unable to create a segment in the given size
static WhirlCodeSegment *generate_jump_for_table(WhirlCodeSegment *last_segment, RingState state, int jump_amount, unsigned length) {
    RingState start_state = state;
    WhirlCodeSegment *segment = NULL;
    for (int i = 0; i < 200; i++) {
        size_t actual_len = length - i;
        int actual_jump = jump_amount - i;
        state = start_state;
        segment = new_segment(NULL, last_segment);
        set_mem(segment, &state, -actual_jump);
        generate_op_command(segment, &state, OP_LOAD);
        set_math_ring_clockwise(segment, &state);
        if (state.op_dir != CLOCKWISE) {
            emit_zero(segment, &state);
            emit_one(segment, &state);
        }
        while (segment->len < actual_len &&
            (actual_len - segment->len + state.cur_op_pos - 2) % NUM_CMDS_PER_RING != OP_IF)
        {
            emit_zero(segment, &state);
            emit_one(segment, &state);
            emit_one(segment, &state);
            emit_zero(segment, &state);
            emit_one(segment, &state);
        }
        if (segment->len >= actual_len) {
            free_segments(segment);
            segment = NULL;
            continue;
        }
        while (segment->len < actual_len - 2) {
            emit_one(segment, &state);
        }
        emit_zero(segment, &state);
        emit_zero(segment, &state);
        for (int j = 0; j < i; j++) {
            emit_zero(segment, &state);
        }
        return segment;
    }
    return segment;
}
static WhirlCodeSegment * generate_jump_for_table ( WhirlCodeSegment * last_segment , RingState state , int jump_amount , unsigned length ) { RingState start_state = state ; WhirlCodeSegment * segment = NULL ; for ( int i = 0 ; i < 200 ; i ++ ) { size_t actual_len = length - i ; int actual_jump = jump_amount - i ; state = start_state ; segment = new_segment ( NULL , last_segment ) ; set_mem ( segment , & state , - actual_jump ) ; generate_op_command ( segment , & state , OP_LOAD ) ; set_math_ring_clockwise ( segment , & state ) ; if ( state . op_dir != CLOCKWISE ) { emit_zero ( segment , & state ) ; emit_one ( segment , & state ) ; } while ( segment -> len < actual_len && ( actual_len - segment -> len + state . cur_op_pos - 2 ) % NUM_CMDS_PER_RING != OP_IF ) { emit_zero ( segment , & state ) ; emit_one ( segment , & state ) ; emit_one ( segment , & state ) ; emit_zero ( segment , & state ) ; emit_one ( segment , & state ) ; } if ( segment -> len >= actual_len ) { free_segments ( segment ) ; segment = NULL ; continue ; } while ( segment -> len < actual_len - 2 ) { emit_one ( segment , & state ) ; } emit_zero ( segment , & state ) ; emit_zero ( segment , & state ) ; for ( int j = 0 ; j < i ; j ++ ) { emit_zero ( segment , & state ) ; } return segment ; } return segment ; }
Generates a jump instruction for the end of program jump table.
Generates a jump instruction for the end of program jump table .
// We may not end up being able to create a jump aligned how we would like inside the // length given to us, so we do a loop here to try out different lengths, and then pad // them out to match the length we're trying for // We've exceeded the length without aligning with the OP_IF command, // so we give up on this length and try again