📄 labels.c
字号:
/* snap-1.0. Copyright (C) 2000 by Jonathan T. Moore and Michael Hicks. * * labels.c : routines used by the assembler to keep track of labels * and fill in their values with offsets * * $Id: labels.c,v 1.2 2003/09/17 11:26:10 tmoerlan Exp $ */#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "../lib/io.h"#include "../lib/bytecode.h"#include "../lib/d_printf.h"#include "../lib/dyncheck.h"/******************* local functions and data *********************/typedef struct { char *name; void *where;} label_mapping_t;#define MAX_NUM_LABELS 100static label_mapping_t label_def_map[MAX_NUM_LABELS];static int label_def_map_idx = 0;static label_mapping_t label_use_map[MAX_NUM_LABELS];static int label_use_map_idx = 0;/* associates the label with the current pc */static void register_label(label_mapping_t map[], int idx, char *labname, void *where) { assert(where != NULL); assert(labname != NULL); if (idx >= MAX_NUM_LABELS) { fprintf(stderr,"Exceeded static size of label map (%d)!\n", MAX_NUM_LABELS); exit(1); } map[idx].name = labname; map[idx].where = where; d_printf(100,"registered label %s at addr %x in table %x\n", labname,(unsigned int)where,(unsigned int)map);}static char *find_label(label_mapping_t map[], int idx, void *where) { int i; for (i=0; i<idx; i++) { if (map[i].where == where) { return map[i].name; } } return NULL; /* not found */} static void *find_where(label_mapping_t map[], int idx, char *label) { int i; for (i=0; i<idx; i++) { if (!strcmp(map[i].name, label)) { return map[i].where; } } return NULL; /* not found */}/************************ exported functions *************************/void register_label_def(char *labname, void *where) { register_label(label_def_map,label_def_map_idx,labname,where); label_def_map_idx++;}void register_label_use(char *labname, void *where) { register_label(label_use_map,label_use_map_idx,labname,where); label_use_map_idx++;}static int calc_offs(char *label, instr_t *startpc) { instr_t *def_pc; assert(startpc != NULL); /* find the label's definition */ def_pc = (instr_t *)find_where(label_def_map, label_def_map_idx, label); if (def_pc == NULL) { fprintf(stderr,"label %s, is undefined\n", label); exit(1); } /* patch it */ return (int)(def_pc - startpc);}static void fill_value_label(value_t *v, char *label, instr_t *startpc) { int ofs; assert(v != NULL); assert(startpc != NULL); ofs = calc_offs(label,startpc); /* store in the argument for the instruction */ SET_INT(*v,GET_INT(*v) + ofs); d_printf(100,"patched label %s at addr %x; ofs = %d, val = %d\n", label,(unsigned int)v,ofs,GET_INT(*v)); assert(GET_INT(*v) >= 0);}static void fill_literal_label(instr_t *pc, char *label, instr_t *startpc) { int ofs; assert(pc != NULL); assert(startpc != NULL); GET_LIT(ofs,INTV,*pc); ofs += calc_offs(label,startpc); /* store in the argument for the instruction */ SET_LIT(*pc,INTV,ofs); d_printf(100,"patched label %s at pc %x; val = %d\n", label,(unsigned int)pc,ofs);}/* patch each instruction in the packet. It is assumed that the current pc of the packet is at the end of the code. */void patch_jumps(packet_t *p) { instr_t *cur_pc; value_t *cur_v; char *label; /* patch jumps in the code portion */ for (cur_pc = p->code_min; cur_pc < p->pc; cur_pc++) switch (GET_OP(*cur_pc)) { case JI: case BNE: case BEZ: case PUSH:#ifdef SMALL_INSTRS case PINT: case EQINT: case NQINT: case PADDR: case EQADR: case NQADR: case PTUP: case EQTUP: case NQTUP: case PEXC: case EQEXC: case NQEXC: case PSTR: case EQSTR: case NQSTR:#endif label = find_label(label_use_map,label_use_map_idx,cur_pc); if (label != NULL) fill_literal_label(cur_pc,label,p->code_min); break; default: assert(find_label(label_use_map,label_use_map_idx,cur_pc)==NULL); break; } /* now in the stack */ for (cur_v = p->stack_min; cur_v < p->sp; cur_v++) { label = find_label(label_use_map,label_use_map_idx,cur_v); if (label != NULL) fill_value_label(cur_v,label,p->code_min); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -