diff options
Diffstat (limited to 'src/buildvm.c')
-rw-r--r-- | src/buildvm.c | 97 |
1 files changed, 68 insertions, 29 deletions
diff --git a/src/buildvm.c b/src/buildvm.c index dd0cbcc6..1b4d6928 100644 --- a/src/buildvm.c +++ b/src/buildvm.c | |||
@@ -101,6 +101,33 @@ static void emit_raw(BuildCtx *ctx) | |||
101 | 101 | ||
102 | /* -- Build machine code -------------------------------------------------- */ | 102 | /* -- Build machine code -------------------------------------------------- */ |
103 | 103 | ||
104 | static const char *sym_decorate(BuildCtx *ctx, | ||
105 | const char *prefix, const char *suffix) | ||
106 | { | ||
107 | char name[256]; | ||
108 | char *p; | ||
109 | #if LJ_64 | ||
110 | const char *symprefix = ctx->mode == BUILD_machasm ? "_" : ""; | ||
111 | #else | ||
112 | const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : ""; | ||
113 | #endif | ||
114 | sprintf(name, "%s%s%s", symprefix, prefix, suffix); | ||
115 | p = strchr(name, '@'); | ||
116 | if (p) { | ||
117 | if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) | ||
118 | name[0] = '@'; | ||
119 | else | ||
120 | *p = '\0'; | ||
121 | } | ||
122 | p = (char *)malloc(strlen(name)+1); /* MSVC doesn't like strdup. */ | ||
123 | strcpy(p, name); | ||
124 | return p; | ||
125 | } | ||
126 | |||
127 | #define NRELOCSYM (sizeof(extnames)/sizeof(extnames[0])-1) | ||
128 | |||
129 | static int relocmap[NRELOCSYM]; | ||
130 | |||
104 | /* Collect external relocations. */ | 131 | /* Collect external relocations. */ |
105 | static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) | 132 | static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) |
106 | { | 133 | { |
@@ -108,32 +135,38 @@ static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) | |||
108 | fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n"); | 135 | fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n"); |
109 | exit(1); | 136 | exit(1); |
110 | } | 137 | } |
138 | if (relocmap[idx] < 0) { | ||
139 | relocmap[idx] = ctx->nrelocsym; | ||
140 | ctx->relocsym[ctx->nrelocsym] = sym_decorate(ctx, "", extnames[idx]); | ||
141 | ctx->nrelocsym++; | ||
142 | } | ||
111 | ctx->reloc[ctx->nreloc].ofs = (int32_t)(addr - ctx->code); | 143 | ctx->reloc[ctx->nreloc].ofs = (int32_t)(addr - ctx->code); |
112 | ctx->reloc[ctx->nreloc].sym = idx; | 144 | ctx->reloc[ctx->nreloc].sym = relocmap[idx]; |
113 | ctx->reloc[ctx->nreloc].type = type; | 145 | ctx->reloc[ctx->nreloc].type = type; |
114 | ctx->nreloc++; | 146 | ctx->nreloc++; |
115 | return 0; /* Encode symbol offset of 0. */ | 147 | return 0; /* Encode symbol offset of 0. */ |
116 | } | 148 | } |
117 | 149 | ||
118 | /* Naive insertion sort. Performance doesn't matter here. */ | 150 | /* Naive insertion sort. Performance doesn't matter here. */ |
119 | static void perm_insert(int *perm, int32_t *ofs, int i) | 151 | static void sym_insert(BuildCtx *ctx, int32_t ofs, |
152 | const char *prefix, const char *suffix) | ||
120 | { | 153 | { |
121 | perm[i] = i; | 154 | ptrdiff_t i = ctx->nsym++; |
122 | while (i > 0) { | 155 | while (i > 0) { |
123 | int a = perm[i-1]; | 156 | if (ctx->sym[i-1].ofs <= ofs) |
124 | int b = perm[i]; | 157 | break; |
125 | if (ofs[a] <= ofs[b]) break; | 158 | ctx->sym[i] = ctx->sym[i-1]; |
126 | perm[i] = a; | ||
127 | perm[i-1] = b; | ||
128 | i--; | 159 | i--; |
129 | } | 160 | } |
161 | ctx->sym[i].ofs = ofs; | ||
162 | ctx->sym[i].name = sym_decorate(ctx, prefix, suffix); | ||
130 | } | 163 | } |
131 | 164 | ||
132 | /* Build the machine code. */ | 165 | /* Build the machine code. */ |
133 | static int build_code(BuildCtx *ctx) | 166 | static int build_code(BuildCtx *ctx) |
134 | { | 167 | { |
135 | int status; | 168 | int status; |
136 | int i, j; | 169 | int i; |
137 | 170 | ||
138 | /* Initialize DynASM structures. */ | 171 | /* Initialize DynASM structures. */ |
139 | ctx->nglob = GLOB__MAX; | 172 | ctx->nglob = GLOB__MAX; |
@@ -141,8 +174,10 @@ static int build_code(BuildCtx *ctx) | |||
141 | memset(ctx->glob, 0, ctx->nglob*sizeof(void *)); | 174 | memset(ctx->glob, 0, ctx->nglob*sizeof(void *)); |
142 | ctx->nreloc = 0; | 175 | ctx->nreloc = 0; |
143 | 176 | ||
144 | ctx->extnames = extnames; | ||
145 | ctx->globnames = globnames; | 177 | ctx->globnames = globnames; |
178 | ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); | ||
179 | ctx->nrelocsym = 0; | ||
180 | for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; | ||
146 | 181 | ||
147 | ctx->dasm_ident = DASM_IDENT; | 182 | ctx->dasm_ident = DASM_IDENT; |
148 | ctx->dasm_arch = DASM_ARCH; | 183 | ctx->dasm_arch = DASM_ARCH; |
@@ -160,37 +195,41 @@ static int build_code(BuildCtx *ctx) | |||
160 | ctx->code = (uint8_t *)malloc(ctx->codesz); | 195 | ctx->code = (uint8_t *)malloc(ctx->codesz); |
161 | if ((status = dasm_encode(Dst, (void *)ctx->code))) return status; | 196 | if ((status = dasm_encode(Dst, (void *)ctx->code))) return status; |
162 | 197 | ||
163 | /* Allocate the symbol offset and permutation tables. */ | 198 | /* Allocate symbol table and bytecode offsets. */ |
164 | ctx->nsym = ctx->npc + ctx->nglob; | 199 | ctx->beginsym = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin"); |
165 | ctx->perm = (int *)malloc((ctx->nsym+1)*sizeof(int *)); | 200 | ctx->sym = (BuildSym *)malloc((ctx->npc+ctx->nglob+1)*sizeof(BuildSym)); |
166 | ctx->sym_ofs = (int32_t *)malloc((ctx->nsym+1)*sizeof(int32_t)); | 201 | ctx->nsym = 0; |
202 | ctx->bc_ofs = (int32_t *)malloc(ctx->npc*sizeof(int32_t)); | ||
167 | 203 | ||
168 | /* Collect the opcodes (PC labels). */ | 204 | /* Collect the opcodes (PC labels). */ |
169 | for (i = 0; i < ctx->npc; i++) { | 205 | for (i = 0; i < ctx->npc; i++) { |
170 | int32_t n = dasm_getpclabel(Dst, i); | 206 | int32_t ofs = dasm_getpclabel(Dst, i); |
171 | if (n < 0) return 0x22000000|i; | 207 | if (ofs < 0) return 0x22000000|i; |
172 | ctx->sym_ofs[i] = n; | 208 | ctx->bc_ofs[i] = ofs; |
173 | perm_insert(ctx->perm, ctx->sym_ofs, i); | 209 | #if !LJ_HASJIT |
210 | if (!(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP || | ||
211 | i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) | ||
212 | #endif | ||
213 | sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]); | ||
174 | } | 214 | } |
175 | 215 | ||
176 | /* Collect the globals (named labels). */ | 216 | /* Collect the globals (named labels). */ |
177 | for (j = 0; j < ctx->nglob; j++, i++) { | 217 | for (i = 0; i < ctx->nglob; i++) { |
178 | const char *gl = globnames[j]; | 218 | const char *gl = globnames[i]; |
179 | int len = (int)strlen(gl); | 219 | int len = (int)strlen(gl); |
180 | if (!ctx->glob[j]) { | 220 | if (!ctx->glob[i]) { |
181 | fprintf(stderr, "Error: undefined global %s\n", gl); | 221 | fprintf(stderr, "Error: undefined global %s\n", gl); |
182 | exit(2); | 222 | exit(2); |
183 | } | 223 | } |
184 | if (len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z') | 224 | /* Skip the _Z symbols. */ |
185 | ctx->sym_ofs[i] = -1; /* Skip the _Z symbols. */ | 225 | if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z')) |
186 | else | 226 | sym_insert(ctx, (int32_t)((uint8_t *)(ctx->glob[i]) - ctx->code), |
187 | ctx->sym_ofs[i] = (int32_t)((uint8_t *)(ctx->glob[j]) - ctx->code); | 227 | LABEL_PREFIX, globnames[i]); |
188 | perm_insert(ctx->perm, ctx->sym_ofs, i); | ||
189 | } | 228 | } |
190 | 229 | ||
191 | /* Close the address range. */ | 230 | /* Close the address range. */ |
192 | ctx->sym_ofs[i] = (int32_t)ctx->codesz; | 231 | sym_insert(ctx, (int32_t)ctx->codesz, "", ""); |
193 | perm_insert(ctx->perm, ctx->sym_ofs, i); | 232 | ctx->nsym--; |
194 | 233 | ||
195 | dasm_free(Dst); | 234 | dasm_free(Dst); |
196 | 235 | ||
@@ -260,7 +299,7 @@ static void emit_bcdef(BuildCtx *ctx) | |||
260 | for (i = 0; i < ctx->npc; i++) { | 299 | for (i = 0; i < ctx->npc; i++) { |
261 | if (i != 0) | 300 | if (i != 0) |
262 | fprintf(ctx->fp, ",\n"); | 301 | fprintf(ctx->fp, ",\n"); |
263 | fprintf(ctx->fp, "%d", ctx->sym_ofs[i]); | 302 | fprintf(ctx->fp, "%d", ctx->bc_ofs[i]); |
264 | } | 303 | } |
265 | } | 304 | } |
266 | 305 | ||