annotate keiko/xmain.c @ 1:b5139af1a420 tip basis

Fixed permissions on compile scripts
author Mike Spivey <mike@cs.ox.ac.uk>
date Fri, 13 Oct 2017 17:27:58 +0100
parents bfdcc3820b32
children
rev   line source
mike@0 1 /*
mike@0 2 * xmain.c
mike@0 3 *
mike@0 4 * This file is part of the Oxford Oberon-2 compiler
mike@0 5 * Copyright (c) 2006--2016 J. M. Spivey
mike@0 6 * All rights reserved
mike@0 7 *
mike@0 8 * Redistribution and use in source and binary forms, with or without
mike@0 9 * modification, are permitted provided that the following conditions are met:
mike@0 10 *
mike@0 11 * 1. Redistributions of source code must retain the above copyright notice,
mike@0 12 * this list of conditions and the following disclaimer.
mike@0 13 * 2. Redistributions in binary form must reproduce the above copyright notice,
mike@0 14 * this list of conditions and the following disclaimer in the documentation
mike@0 15 * and/or other materials provided with the distribution.
mike@0 16 * 3. The name of the author may not be used to endorse or promote products
mike@0 17 * derived from this software without specific prior written permission.
mike@0 18 *
mike@0 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
mike@0 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
mike@0 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
mike@0 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
mike@0 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
mike@0 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
mike@0 25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
mike@0 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
mike@0 27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
mike@0 28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mike@0 29 */
mike@0 30
mike@0 31 #define EXTERN
mike@0 32 #include "obx.h"
mike@0 33 #include "keiko.h"
mike@0 34 #include "exec.h"
mike@0 35
mike@0 36 #ifdef JIT
mike@0 37 #include "vm.h"
mike@0 38 #ifdef DEBUG
mike@0 39 #define JTEST 1
mike@0 40 #endif
mike@0 41 #endif
mike@0 42
mike@0 43 #ifdef PROFILE
mike@0 44 #define MYNAME "profiler"
mike@0 45 #else
mike@0 46 #ifdef OBXDEB
mike@0 47 #define MYNAME "debugging monitor"
mike@0 48 #else
mike@0 49 #define MYNAME "runtime system"
mike@0 50 #endif
mike@0 51 #endif
mike@0 52
mike@0 53 const char *version =
mike@0 54 "Oxford Oberon-2 " MYNAME " version " PACKAGE_VERSION " [build " REVID "]"
mike@0 55 #ifdef JIT
mike@0 56 " (JIT)"
mike@0 57 #else
mike@0 58 ""
mike@0 59 #endif
mike@0 60 #ifdef DEBUG
mike@0 61 " (debug)"
mike@0 62 #else
mike@0 63 ""
mike@0 64 #endif
mike@0 65 ;
mike@0 66 const char *copyright = "Copyright (C) 1999--2012 J. M. Spivey";
mike@0 67
mike@0 68 extern int vm_debug;
mike@0 69
mike@0 70 /* Helper functions for the loader */
mike@0 71
mike@0 72 module make_module(char *name, uchar *addr, int chksum, int nlines) {
mike@0 73 module m = (module) scratch_alloc(sizeof(struct _module));
mike@0 74 m->m_name = name;
mike@0 75 m->m_addr = addr;
mike@0 76 #ifdef PROFILE
mike@0 77 m->m_nlines = nlines;
mike@0 78 m->m_lcount = NULL;
mike@0 79 if (lflag && nlines > 0) {
mike@0 80 m->m_lcount =
mike@0 81 (unsigned *) scratch_alloc(nlines * sizeof(unsigned));
mike@0 82 memset(m->m_lcount, 0, nlines * sizeof(int));
mike@0 83 }
mike@0 84 #endif
mike@0 85 #ifdef OBXDEB
mike@0 86 debug_message("module %s %#x", name, chksum);
mike@0 87 #endif
mike@0 88 return m;
mike@0 89 }
mike@0 90
mike@0 91 proc make_proc(char *name, uchar *addr) {
mike@0 92 proc p = (proc) scratch_alloc(sizeof(struct _proc));
mike@0 93 p->p_name = name;
mike@0 94 p->p_addr = (value *) addr;
mike@0 95 #ifdef PROFILE
mike@0 96 p->p_calls = p->p_rec = p->p_self = p->p_child = 0;
mike@0 97 p->p_parents = p->p_children = NULL;
mike@0 98 #endif
mike@0 99 #ifdef OBXDEB
mike@0 100 debug_message("proc %s %#x %#x %d", name, address(addr),
mike@0 101 p->p_addr[CP_CODE].a, p->p_addr[CP_SIZE].i);
mike@0 102 #endif
mike@0 103 return p;
mike@0 104 }
mike@0 105
mike@0 106 void make_symbol(const char *kind, char *name, uchar *addr) {
mike@0 107 #ifdef OBXDEB
mike@0 108 debug_message("%s %s %#x", kind, name, address(addr));
mike@0 109 #endif
mike@0 110 }
mike@0 111
mike@0 112 /* Runtime errors */
mike@0 113
mike@0 114 #ifndef OBXDEB
mike@0 115 #define TOP 5 /* Number of frames shown at top and bottom */
mike@0 116 #define BOT 5
mike@0 117 #define GAP 10 /* Don't omit less than this many frames */
mike@0 118 #define NBUF (BOT+GAP-1)
mike@0 119
mike@0 120 static void backtrace(value *bp) {
mike@0 121 value *fp = bp, *cp = valptr(bp[CP]);
mike@0 122 proc p = find_proc(cp);
mike@0 123 int n, j;
mike@0 124 proc fbuf[NBUF];
mike@0 125
mike@0 126 fprintf(stderr, "In procedure %s\n", p->p_name);
mike@0 127
mike@0 128 /* Chain down the stack, printing the first TOP frames,
mike@0 129 and saving the last NBUF in a circular buffer. */
mike@0 130 for (n = 0;; n++) {
mike@0 131 /* Each frame contains the cp and bp of its caller */
mike@0 132 fp = valptr(fp[BP]); /* Base pointer of next frame */
mike@0 133 if (fp == NULL) break;
mike@0 134 cp = valptr(fp[CP]); /* Constant pool of next frame */
mike@0 135 fbuf[n%NBUF] = p = find_proc(cp);
mike@0 136 if (n < TOP)
mike@0 137 fprintf(stderr, " called from %s\n", p->p_name);
mike@0 138 }
mike@0 139
mike@0 140 /* Now the last NBUF frames are f(n-NBUF), ..., f(n-1)
mike@0 141 where f(i) = fbuf[i%NBUF] -- unless there are fewer
mike@0 142 then NBUF frames in all. */
mike@0 143
mike@0 144 if (n < TOP+GAP+BOT)
mike@0 145 /* Print the n-TOP frames not printed already */
mike@0 146 j = TOP;
mike@0 147 else {
mike@0 148 /* Omit n-(TOP+BOT) frames (at least GAP) and print the
mike@0 149 last BOT frames */
mike@0 150 fprintf(stderr, " ... %d intervening frames omitted ...\n",
mike@0 151 n-(TOP+BOT));
mike@0 152 j = n-BOT;
mike@0 153 }
mike@0 154
mike@0 155 /* Print frames j, ..., n-1 */
mike@0 156 for (; j < n; j++)
mike@0 157 fprintf(stderr, " called from %s\n", fbuf[j%NBUF]->p_name);
mike@0 158 }
mike@0 159 #endif
mike@0 160
mike@0 161 static const char *message(int code) {
mike@0 162 switch (code) {
mike@0 163 case E_CAST:
mike@0 164 return "dynamic type error in cast";
mike@0 165 case E_ASSIGN:
mike@0 166 return "dynamic type error in record assignment";
mike@0 167 case E_CASE:
mike@0 168 return "no matching label in CASE statement";
mike@0 169 case E_WITH:
mike@0 170 return "no matching type guard in WITH statement";
mike@0 171 case E_ASSERT:
mike@0 172 return "assertion failed (%d)";
mike@0 173 case E_RETURN:
mike@0 174 return "function failed to return a result";
mike@0 175 case E_BOUND:
mike@0 176 return "array bound error";
mike@0 177 case E_NULL:
mike@0 178 return "null pointer error";
mike@0 179 case E_DIV:
mike@0 180 return "DIV or MOD by zero";
mike@0 181 case E_FDIV:
mike@0 182 return "division by zero";
mike@0 183 case E_STACK:
mike@0 184 return "stack overflow";
mike@0 185 case E_GLOB:
mike@0 186 return "assignment of local procedure";
mike@0 187 default:
mike@0 188 return "the impossible has happened";
mike@0 189 }
mike@0 190 }
mike@0 191
mike@0 192 /* error_stop -- runtime error with explicit message text */
mike@0 193 void error_stop(const char *msg, int line, value *bp, uchar *pc) {
mike@0 194 value *cp = valptr(bp[CP]);
mike@0 195
mike@0 196 #ifdef OBXDEB
mike@0 197 char buf[256];
mike@0 198 sprintf(buf, msg, ob_res.i);
mike@0 199 debug_break(cp, bp, pc, "error %d %s", line, buf);
mike@0 200 #else
mike@0 201 module mod = find_module(cp);
mike@0 202
mike@0 203 fprintf(stderr, "Runtime error: ");
mike@0 204 fprintf(stderr, msg, ob_res.i);
mike@0 205 if (line > 0) fprintf(stderr, " on line %d", line);
mike@0 206 if (mod != NULL && strcmp(mod->m_name, "_Builtin") != 0)
mike@0 207 fprintf(stderr, " in module %s", mod->m_name);
mike@0 208 fprintf(stderr, "\n");
mike@0 209 fflush(stderr);
mike@0 210
mike@0 211 if (nprocs == 0)
mike@0 212 fprintf(stderr, "(No debugging information available)\n");
mike@0 213 else if (bp != NULL)
mike@0 214 backtrace(bp);
mike@0 215
mike@0 216 fflush(stderr);
mike@0 217 #endif
mike@0 218
mike@0 219 exit(2);
mike@0 220 }
mike@0 221
mike@0 222 /* runtime_error -- report a runtime error */
mike@0 223 void runtime_error(int m, int line, value *bp, uchar *pc) {
mike@0 224 error_stop(message(m), line, bp, pc);
mike@0 225 }
mike@0 226
mike@0 227 /* rterror -- simple version of runtime_error for JIT */
mike@0 228 void rterror(int num, int line, value *bp) {
mike@0 229 runtime_error(num, line, bp, NULL);
mike@0 230 }
mike@0 231
mike@0 232 /* stkoflo -- stack overflow handler for JIT */
mike@0 233 void stkoflo(value *bp) {
mike@0 234 runtime_error(E_STACK, 0, bp, NULL);
mike@0 235 }
mike@0 236
mike@0 237
mike@0 238 /* Startup */
mike@0 239
mike@0 240 static void run(value *prog) {
mike@0 241 value *sp;
mike@0 242
mike@0 243 /* Allow 32-word safety margin (for tracing) */
mike@0 244 sp = (value *) (stack + stack_size) - 32;
mike@0 245
mike@0 246 sp -= HEAD;
mike@0 247 sp[BP].a = address(NULL);
mike@0 248 sp[PC].a = address(NULL);
mike@0 249 sp[CP].a = address(prog);
mike@0 250 primcall(prog, sp);
mike@0 251 }
mike@0 252
mike@0 253 mybool custom_file(char *name) {
mike@0 254 char buf[4];
mike@0 255 FILE *fp;
mike@0 256 int nread;
mike@0 257 mybool result;
mike@0 258
mike@0 259 fp = fopen(name, "rb");
mike@0 260 if (fp == NULL) return FALSE;
mike@0 261 fseek(fp, - (long) sizeof(trailer), SEEK_END);
mike@0 262 nread = fread(buf, 1, 4, fp);
mike@0 263 if (nread < 4 || strncmp(buf, MAGIC, 4) != 0)
mike@0 264 result = FALSE;
mike@0 265 else {
mike@0 266 fseek(fp, 0, SEEK_SET);
mike@0 267 nread = fread(buf, 1, 2, fp);
mike@0 268 result = (nread == 2 && strncmp(buf, "#!", 2) != 0);
mike@0 269 }
mike@0 270 fclose(fp);
mike@0 271 return result;
mike@0 272 }
mike@0 273
mike@0 274 #ifdef WINDOWS
mike@0 275 #include <windows.h>
mike@0 276 #include <winbase.h>
mike@0 277
mike@0 278 char *search_path(char *name) {
mike@0 279 static char buf[_MAX_PATH];
mike@0 280 char *filepart;
mike@0 281
mike@0 282 if (SearchPath(NULL, name, ".exe", _MAX_PATH, buf, &filepart) == 0)
mike@0 283 return NULL;
mike@0 284
mike@0 285 return buf;
mike@0 286 }
mike@0 287 #else
mike@0 288 #include <sys/stat.h>
mike@0 289 #ifdef HAVE_UNISTD_H
mike@0 290 #include <unistd.h>
mike@0 291 #endif
mike@0 292
mike@0 293 char *search_path(char *name) {
mike@0 294 char *path;
mike@0 295 static char buf[256];
mike@0 296 struct stat stbuf;
mike@0 297
mike@0 298 if (name == NULL || strchr(name, '/') != NULL) return name;
mike@0 299
mike@0 300 path = getenv("PATH");
mike@0 301 if (path == NULL) return NULL;
mike@0 302
mike@0 303 for (char *p = path, *q; p != NULL; p = q) {
mike@0 304 q = strchr(p, ':');
mike@0 305 char *r;
mike@0 306 if (q == NULL) {
mike@0 307 strcpy(buf, p);
mike@0 308 r = buf + strlen(p);
mike@0 309 } else {
mike@0 310 strncpy(buf, p, q-p);
mike@0 311 r = buf + (q-p); q++;
mike@0 312 }
mike@0 313 if (r > buf) *r++ = '/';
mike@0 314 strcpy(r, name);
mike@0 315
mike@0 316 if (access(buf, R_OK) == 0 && stat(buf, &stbuf) == 0
mike@0 317 && S_ISREG(stbuf.st_mode))
mike@0 318 return buf;
mike@0 319 }
mike@0 320
mike@0 321 return NULL;
mike@0 322 }
mike@0 323 #endif
mike@0 324
mike@0 325 #define argc saved_argc
mike@0 326 #define argv saved_argv
mike@0 327
mike@0 328 static char *progname;
mike@0 329 #ifdef PROFILE
mike@0 330 static char *profout;
mike@0 331 static const char *dumpname = "obprof.out";
mike@0 332 #endif
mike@0 333
mike@0 334 static void usage(void) {
mike@0 335 #ifdef PROFILE
mike@0 336 fprintf(stderr,
mike@0 337 "Usage: %s [-g] [-pl] [-o file] program [arg ...]\n",
mike@0 338 progname);
mike@0 339 #else
mike@0 340 fprintf(stderr, "Usage: %s program [arg ...]\n", progname);
mike@0 341 #endif
mike@0 342 fflush(stderr);
mike@0 343 _exit(1);
mike@0 344 }
mike@0 345
mike@0 346 #ifdef JTEST
mike@0 347 static mybool tflag = 0;
mike@0 348 #endif
mike@0 349
mike@0 350 /* read_flags -- interpret flags */
mike@0 351 static void read_flags(void) {
mike@0 352 for (;;) {
mike@0 353 argc--; argv++;
mike@0 354 if (argc == 0 || argv[0][0] != '-') return;
mike@0 355
mike@0 356 if (strcmp(argv[0], "--") == 0) {
mike@0 357 argc--; argv++;
mike@0 358 return;
mike@0 359 } else if (strcmp(argv[0], "-d") == 0) {
mike@0 360 dflag++;
mike@0 361 } else if (strcmp(argv[0], "-v") == 0) {
mike@0 362 fprintf(stderr, "%s\n", version);
mike@0 363 exit(0);
mike@0 364 }
mike@0 365 #ifdef PROFILE
mike@0 366 else if (argc >= 2 && strcmp(argv[0], "-o") == 0) {
mike@0 367 profout = argv[1];
mike@0 368 argc--; argv++;
mike@0 369 } else if (strcmp(argv[0], "-g") == 0) {
mike@0 370 gflag = TRUE;
mike@0 371 } else if (strcmp(argv[0], "-l") == 0
mike@0 372 || strcmp(argv[0], "-pl") == 0) {
mike@0 373 lflag = TRUE;
mike@0 374 }
mike@0 375 #endif
mike@0 376 #ifdef TRACE
mike@0 377 else if (strcmp(argv[0], "-q") == 0) {
mike@0 378 qflag++;
mike@0 379 }
mike@0 380 #endif
mike@0 381 #ifdef OBXDEB
mike@0 382 else if (argc >= 2 && strcmp(argv[0], "-p") == 0) {
mike@0 383 debug_socket = argv[1];
mike@0 384 argc--; argv++;
mike@0 385 }
mike@0 386 #endif
mike@0 387 #ifdef JTEST
mike@0 388 else if (strcmp(argv[0], "-t") == 0) {
mike@0 389 tflag++;
mike@0 390 }
mike@0 391 #endif
mike@0 392 else {
mike@0 393 usage();
mike@0 394 }
mike@0 395 }
mike@0 396 }
mike@0 397
mike@0 398 #ifdef PROFILE
mike@0 399 static void dump_lcounts(void) {
mike@0 400 FILE *fp = fopen(dumpname, "w");
mike@0 401 if (fp == NULL) {
mike@0 402 fprintf(stderr, "%s: cannot write\n", dumpname);
mike@0 403 exit(1);
mike@0 404 }
mike@0 405
mike@0 406 for (int m = 0; m < nmods; m++)
mike@0 407 for (int n = 1; n <= modtab[m]->m_nlines; n++)
mike@0 408 if (modtab[m]->m_lcount[n-1] > 0)
mike@0 409 fprintf(fp, "%s %d %u\n", modtab[m]->m_name, n,
mike@0 410 modtab[m]->m_lcount[n-1]);
mike@0 411
mike@0 412 fclose(fp);
mike@0 413 }
mike@0 414
mike@0 415 static void print_profile(void) {
mike@0 416 FILE *fp = stderr;
mike@0 417
mike@0 418 if (profout != NULL) {
mike@0 419 fp = fopen(profout, "w");
mike@0 420 if (fp == NULL) {
mike@0 421 fprintf(stderr, "%s: cannot write\n", profout);
mike@0 422 exit(1);
mike@0 423 }
mike@0 424
mike@0 425 fprintf(fp, "Command line:\n\n");
mike@0 426 fprintf(fp, " %s", saved_argv[0]);
mike@0 427 for (int i = 1; i < saved_argc; i++)
mike@0 428 fprintf(fp, " %s", saved_argv[i]);
mike@0 429 fprintf(fp, "\n\n");
mike@0 430 }
mike@0 431
mike@0 432 profile(fp);
mike@0 433
mike@0 434 if (fp != stderr) fclose(fp);
mike@0 435 }
mike@0 436 #endif
mike@0 437
mike@0 438 #ifdef JTEST
mike@0 439 static void jit_test(void) {
mike@0 440 dflag = vm_debug = 2; vm_aflag = 1;
mike@0 441 if (nmods < 2) panic("Can't find main module");
mike@0 442 module m = modtab[nmods-2];
mike@0 443 for (int i = 0; i < nprocs; i++) {
mike@0 444 proc p = proctab[i];
mike@0 445 if ((uchar *) p->p_addr >= m->m_addr
mike@0 446 && (uchar *) p->p_addr < m->m_addr + m->m_length)
mike@0 447 jit_compile(p->p_addr);
mike@0 448 }
mike@0 449 }
mike@0 450 #endif
mike@0 451
mike@0 452 /* xmain_exit -- exit after program has finished */
mike@0 453 void NORETURN xmain_exit(int status) {
mike@0 454 #ifdef OBXDEB
mike@0 455 debug_break(NULL, NULL, NULL, "exit");
mike@0 456 #endif
mike@0 457 #ifdef PROFILE
mike@0 458 print_profile();
mike@0 459 if (lflag) dump_lcounts();
mike@0 460 #endif
mike@0 461 exit(status);
mike@0 462 }
mike@0 463
mike@0 464 /* error_exit -- exit after fatal error */
mike@0 465 void NORETURN error_exit(int status) {
mike@0 466 #ifdef OBXDEB
mike@0 467 debug_message("quit");
mike@0 468 #endif
mike@0 469 exit(status);
mike@0 470 }
mike@0 471
mike@0 472 /* The interpreter can be invoked in three ways:
mike@0 473 (i) Explicitly as "obx [flags] bytefile args"
mike@0 474
mike@0 475 (ii) Via a #! script as "obx bytefile args"
mike@0 476 or "bytefile bytefile args" under some Unixes
mike@0 477
mike@0 478 (iii) In a glued-together executable as "bytefile args"
mike@0 479
mike@0 480 Following the example of CAML Light, we recognize (iii) by seeing
mike@0 481 if argv[0] names a bytefile that does not begin with #!. In that
mike@0 482 case, we read that file for the bytecodes, and the program's args
mike@0 483 follow immediately; otherwise, we look for flags and the name of
mike@0 484 the bytefile before the program's args. In either case, we must be
mike@0 485 prepared to search the shell path to find the bytefile.
mike@0 486
mike@0 487 These rules are modified a bit if a custom file is built for
mike@0 488 profiling: in that case, we look for switches even in case (iii). */
mike@0 489
mike@0 490 int main(int ac, char *av[]) {
mike@0 491 FILE *fp;
mike@0 492 char *codefile;
mike@0 493
mike@0 494 argc = ac; argv = av;
mike@0 495 progname = argv[0];
mike@0 496
mike@0 497 /* Read the command line first to handle -v */
mike@0 498 codefile = search_path(argv[0]);
mike@0 499 if (codefile != NULL && custom_file(codefile)) {
mike@0 500 #ifdef PROFILE
mike@0 501 char *prog = argv[0];
mike@0 502 read_flags();
mike@0 503 /* Fill the program name back in as argv[0] */
mike@0 504 argc++; argv--;
mike@0 505 argv[0] = prog;
mike@0 506 #endif
mike@0 507 } else {
mike@0 508 read_flags();
mike@0 509 if (argc < 1) usage();
mike@0 510 codefile = search_path(argv[0]);
mike@0 511 }
mike@0 512
mike@0 513 #ifdef OBXDEB
mike@0 514 /* Now connect to the debugger process */
mike@0 515 debug_init();
mike@0 516 #endif
mike@0 517
mike@0 518 if (codefile == NULL) panic("can't find %s", argv[0]);
mike@0 519
mike@0 520 gc_init();
mike@0 521
mike@0 522 #ifdef JIT
mike@0 523 vm_debug = dflag;
mike@0 524 interpreter = wrap_prim(jit_trap);
mike@0 525 #else
mike@0 526 interpreter = wrap_prim(interp);
mike@0 527 #endif
mike@0 528 dyntrap = wrap_prim(dltrap);
mike@0 529 #ifdef USEFFI
mike@0 530 dynstub = wrap_prim(dlstub);
mike@0 531 #endif
mike@0 532
mike@0 533 #ifdef M64X32
mike@0 534 /* Allocate ob_res and statlink in 32-bit addressible storage */
mike@0 535 _result = (value *) scratch_alloc(2 * sizeof(value));
mike@0 536 _stat = (value **) scratch_alloc(sizeof(value *));
mike@0 537 #endif
mike@0 538
mike@0 539 fp = fopen(codefile, "rb");
mike@0 540 if (fp == NULL) panic("can't open %s", codefile);
mike@0 541 load_file(fp);
mike@0 542 fclose(fp);
mike@0 543
mike@0 544 #ifdef TRACE
mike@0 545 if (dflag) dump();
mike@0 546 if (qflag) exit(0);
mike@0 547 #endif
mike@0 548
mike@0 549 #ifdef JTEST
mike@0 550 if (tflag) {
mike@0 551 jit_test();
mike@0 552 exit(0);
mike@0 553 }
mike@0 554 #endif
mike@0 555
mike@0 556 #ifdef PROFILE
mike@0 557 if (nprocs == 0)
mike@0 558 panic("no symbol table in object file");
mike@0 559
mike@0 560 prof_init();
mike@0 561 #endif
mike@0 562
mike@0 563 #ifdef OBXDEB
mike@0 564 debug_break(NULL, NULL, NULL, "ready");
mike@0 565 #endif
mike@0 566 #ifdef DEBUG
mike@0 567 if (dflag)
mike@0 568 printf("Starting program at address %ld\n",
mike@0 569 (long) ((uchar *) entry - dmem));
mike@0 570 #endif
mike@0 571 run(entry);
mike@0 572 xmain_exit(0);
mike@0 573 }
mike@0 574
mike@0 575 #ifdef JIT
mike@0 576 void interp(value *bp) {
mike@0 577 panic("dummy interp called");
mike@0 578 }
mike@0 579 #endif
mike@0 580
mike@0 581 word wrap_prim(primitive *prim) {
mike@0 582 #ifdef JIT
mike@0 583 return vm_wrap((funptr) prim);
mike@0 584 #else
mike@0 585 #ifndef M64X32
mike@0 586 return (word) prim;
mike@0 587 #else
mike@0 588 primitive **wrapper =
mike@0 589 (primitive **) scratch_alloc(sizeof(primitive *));
mike@0 590 *wrapper = prim;
mike@0 591 return address(wrapper);
mike@0 592 #endif
mike@0 593 #endif
mike@0 594 }