target/mcfunction.c
static void mcf_preprocess_code(Inst* code) {
  if (!code)
    return;

  typedef struct Block_ {
    int pc;
    Inst* code;
    int adj_pc;
    struct Block_* next;
  } Block;

  /* convert instruction list to list of blocks of instructions */
  int block_count = 1;
  Block* first_block = (Block*) malloc(sizeof(*first_block));
  first_block->pc = code->pc;
  first_block->code = code;
  first_block->adj_pc = -1;
  first_block->next = NULL;
  Block* last_block = first_block;

  Inst* prev_inst = NULL;
  for (Inst* inst = code; inst; inst = inst->next) {
    if (inst->pc != last_block->pc) {
      if (prev_inst)
        prev_inst->next = NULL;
      block_count++;
      Block* new_block = (Block*) malloc(sizeof(*new_block));
      new_block->pc = inst->pc;
      new_block->code = inst;
      new_block->adj_pc = -1;
      new_block->next = NULL;
      last_block->adj_pc = inst->pc;
      last_block->next = new_block;
      last_block = new_block;
    }
    prev_inst = inst;
  }

  /* Process the blocks */
  for (Block* block = first_block; block; block = block->next) {
    prev_inst = NULL;
    for (Inst* inst = block->code; inst; inst = inst->next) {
      /* there should be no instructions before getc (so it can schedule itself) */
      if (MCF_STDIN_WAIT && prev_inst && inst->op == GETC) {
        block_count++;
        Block* new_block = (Block*) malloc(sizeof(*new_block));
        new_block->pc = last_block->pc + 1;
        new_block->code = inst;
        new_block->adj_pc = block->adj_pc;
        new_block->next = NULL;
        last_block->next = new_block;
        last_block = new_block;
        block->adj_pc = new_block->pc;
        prev_inst->next = NULL;
        break;
      }

      /* there should be no instructions after getc or exit (they count as jump instructions for our purposes) */
      if (inst->next && ((MCF_STDIN_WAIT && inst->op == GETC) || inst->op == EXIT)) {
        block_count++;
        Block* new_block = (Block*) malloc(sizeof(*new_block));
        new_block->pc = last_block->pc + 1;
        new_block->code = inst->next;
        new_block->adj_pc = block->adj_pc;
        new_block->next = NULL;
        last_block->next = new_block;
        last_block = new_block;
        inst->next = NULL;
        inst->jmp.type = IMM;
        inst->jmp.imm = new_block->pc;
        break;
      }

      prev_inst = inst;
    }
  }

  /* Convert blocks back into instruction list */
  mcf.adj_pcs = (int*) malloc(block_count * sizeof(int));
  Inst* tail = NULL;
  for (Block* block = first_block; block; block = block->next) {
    for (Inst* inst = block->code; inst; inst = inst->next) {
      inst->pc = block->pc;
      if (tail)
        tail->next = inst;
      tail = inst;
    }
    mcf.adj_pcs[block->pc] = block->adj_pc;
  }

  /* free memory used by blocks */
  while (first_block) {
    Block* next = first_block->next;
    free(first_block);
    first_block = next;
  }
}
/*
 * Preprocess the code, rearranging the control flow graph for our special requirements.
 * Our main special requirement is that getc has to have a pc of its own.
 * This should only add blocks at the end, to avoid messing up with existing jump targets
 * in the code.
 */
Preprocess the code, rearranging the control flow graph for our special requirements.
Our main special requirement is that getc has to have a pc of its own.
This should only add blocks at the end, to avoid messing up with existing jump targets
in the code.
Preprocess the code rearranging the control flow graph for our special requirements . Our main special requirement is that getc has to have a pc of its own . This should only add blocks at the end to avoid messing up with existing jump targets in the code .
static void mcf_preprocess_code(Inst* code) {
  if (!code)
    return;
  typedef struct Block_ {
    int pc;
    Inst* code;
    int adj_pc;
    struct Block_* next;
  } Block;
  int block_count = 1;
  Block* first_block = (Block*) malloc(sizeof(*first_block));
  first_block->pc = code->pc;
  first_block->code = code;
  first_block->adj_pc = -1;
  first_block->next = NULL;
  Block* last_block = first_block;
  Inst* prev_inst = NULL;
  for (Inst* inst = code; inst; inst = inst->next) {
    if (inst->pc != last_block->pc) {
      if (prev_inst)
        prev_inst->next = NULL;
      block_count++;
      Block* new_block = (Block*) malloc(sizeof(*new_block));
      new_block->pc = inst->pc;
      new_block->code = inst;
      new_block->adj_pc = -1;
      new_block->next = NULL;
      last_block->adj_pc = inst->pc;
      last_block->next = new_block;
      last_block = new_block;
    }
    prev_inst = inst;
  }
  for (Block* block = first_block; block; block = block->next) {
    prev_inst = NULL;
    for (Inst* inst = block->code; inst; inst = inst->next) {
      if (MCF_STDIN_WAIT && prev_inst && inst->op == GETC) {
        block_count++;
        Block* new_block = (Block*) malloc(sizeof(*new_block));
        new_block->pc = last_block->pc + 1;
        new_block->code = inst;
        new_block->adj_pc = block->adj_pc;
        new_block->next = NULL;
        last_block->next = new_block;
        last_block = new_block;
        block->adj_pc = new_block->pc;
        prev_inst->next = NULL;
        break;
      }
      if (inst->next && ((MCF_STDIN_WAIT && inst->op == GETC) || inst->op == EXIT)) {
        block_count++;
        Block* new_block = (Block*) malloc(sizeof(*new_block));
        new_block->pc = last_block->pc + 1;
        new_block->code = inst->next;
        new_block->adj_pc = block->adj_pc;
        new_block->next = NULL;
        last_block->next = new_block;
        last_block = new_block;
        inst->next = NULL;
        inst->jmp.type = IMM;
        inst->jmp.imm = new_block->pc;
        break;
      }
      prev_inst = inst;
    }
  }
  mcf.adj_pcs = (int*) malloc(block_count * sizeof(int));
  Inst* tail = NULL;
  for (Block* block = first_block; block; block = block->next) {
    for (Inst* inst = block->code; inst; inst = inst->next) {
      inst->pc = block->pc;
      if (tail)
        tail->next = inst;
      tail = inst;
    }
    mcf.adj_pcs[block->pc] = block->adj_pc;
  }
  while (first_block) {
    Block* next = first_block->next;
    free(first_block);
    first_block = next;
  }
}
static void mcf_preprocess_code ( Inst * code ) { if ( ! code ) return ; typedef struct Block_ { int pc ; Inst * code ; int adj_pc ; struct Block_ * next ; } Block ; int block_count = 1 ; Block * first_block = ( Block * ) malloc ( sizeof ( * first_block ) ) ; first_block -> pc = code -> pc ; first_block -> code = code ; first_block -> adj_pc = -1 ; first_block -> next = NULL ; Block * last_block = first_block ; Inst * prev_inst = NULL ; for ( Inst * inst = code ; inst ; inst = inst -> next ) { if ( inst -> pc != last_block -> pc ) { if ( prev_inst ) prev_inst -> next = NULL ; block_count ++ ; Block * new_block = ( Block * ) malloc ( sizeof ( * new_block ) ) ; new_block -> pc = inst -> pc ; new_block -> code = inst ; new_block -> adj_pc = -1 ; new_block -> next = NULL ; last_block -> adj_pc = inst -> pc ; last_block -> next = new_block ; last_block = new_block ; } prev_inst = inst ; } for ( Block * block = first_block ; block ; block = block -> next ) { prev_inst = NULL ; for ( Inst * inst = block -> code ; inst ; inst = inst -> next ) { if ( MCF_STDIN_WAIT && prev_inst && inst -> op == GETC ) { block_count ++ ; Block * new_block = ( Block * ) malloc ( sizeof ( * new_block ) ) ; new_block -> pc = last_block -> pc + 1 ; new_block -> code = inst ; new_block -> adj_pc = block -> adj_pc ; new_block -> next = NULL ; last_block -> next = new_block ; last_block = new_block ; block -> adj_pc = new_block -> pc ; prev_inst -> next = NULL ; break ; } if ( inst -> next && ( ( MCF_STDIN_WAIT && inst -> op == GETC ) || inst -> op == EXIT ) ) { block_count ++ ; Block * new_block = ( Block * ) malloc ( sizeof ( * new_block ) ) ; new_block -> pc = last_block -> pc + 1 ; new_block -> code = inst -> next ; new_block -> adj_pc = block -> adj_pc ; new_block -> next = NULL ; last_block -> next = new_block ; last_block = new_block ; inst -> next = NULL ; inst -> jmp . type = IMM ; inst -> jmp . imm = new_block -> pc ; break ; } prev_inst = inst ; } } mcf . adj_pcs = ( int * ) malloc ( block_count * sizeof ( int ) ) ; Inst * tail = NULL ; for ( Block * block = first_block ; block ; block = block -> next ) { for ( Inst * inst = block -> code ; inst ; inst = inst -> next ) { inst -> pc = block -> pc ; if ( tail ) tail -> next = inst ; tail = inst ; } mcf . adj_pcs [ block -> pc ] = block -> adj_pc ; } while ( first_block ) { Block * next = first_block -> next ; free ( first_block ) ; first_block = next ; } }
Preprocess the code, rearranging the control flow graph for our special requirements.
Preprocess the code rearranging the control flow graph for our special requirements .
/* convert instruction list to list of blocks of instructions */ /* Process the blocks */ /* there should be no instructions before getc (so it can schedule itself) */ /* there should be no instructions after getc or exit (they count as jump instructions for our purposes) */ /* Convert blocks back into instruction list */ /* free memory used by blocks */