Fequently Asked Questions about LLVM. Mainly focuses on build problems, but
[oota-llvm.git] / tools / llee / ExecveHandler.c
1 //===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===//
2 //
3 // This file implements a replacement execve() to spawn off LLVM programs to run
4 // transparently, without needing to be (JIT-)compiled manually by the user.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "OSInterface.h"
9 #include "SysUtils.h"
10 #include "Config/errno.h"
11 #include "Config/stdlib.h"
12 #include "Config/unistd.h"
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <string.h>
16
17 /*
18  * This is the expected header for all valid LLVM bytecode files.
19  * The first four characters must be exactly this.
20  */
21 static const char llvmHeader[] = "llvm";
22
23 /*
24  * This replacement execve() function first checks the file to be executed
25  * to see if it is a valid LLVM bytecode file, and then either invokes our
26  * execution environment or passes it on to the system execve() call.
27  */
28 int execve(const char *filename, char *const argv[], char *const envp[])
29 {
30   /* Open the file, test to see if first four characters are "llvm" */
31   size_t headerSize = strlen(llvmHeader);
32   char header[headerSize];
33   char* realFilename = 0;
34   /* 
35    * If the program is specified with a relative or absolute path, 
36    * then just use the path and filename as is, otherwise search for it.
37    */
38   if (filename[0] != '.' && filename[0] != '/')
39     realFilename = FindExecutable(filename);
40   else
41     realFilename = (char*) filename;
42   if (!realFilename) {
43     fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
44     return -1;
45   }
46   errno = 0;
47   int file = open(realFilename, O_RDONLY);
48   /* Check validity of `file' */
49   if (errno) return EIO;
50   /* Read the header from the file */
51   ssize_t bytesRead = read(file, header, headerSize);
52   close(file);
53   if (bytesRead != (ssize_t)headerSize) return EIO;
54   if (!memcmp(llvmHeader, header, headerSize)) {
55     /*
56      * Check if we have a cached translation on disk
57      */ 
58     struct stat buf;
59     llvmStat(realFilename, &buf);
60     if (isExecutable(&buf)) {
61       size_t size;
62       void *fileAddr = llvmReadFile(realFilename, &size);
63       fprintf(stderr, "Found in cache: '%s'\n", realFilename);
64       if (fileAddr) {
65         free(fileAddr);
66       }
67       llvmExecve(realFilename, argv, envp);
68     } else {
69       /* 
70        * Not in cache: save translation
71        */ 
72       //llvmSaveFile(realFilename, addr, len);
73       //fprintf(stderr, "Cached: '%s'\n", realFilename);
74     }
75     
76     /* 
77      * This is a bytecode file, so execute the JIT with the program and
78      * parameters.
79      */
80     unsigned argvSize, idx;
81     for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
82       ++argvSize;
83     char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
84     char *LLIpath = FindExecutable("lli");
85     if (!LLIpath) {
86       fprintf(stderr, "Cannot find path to `lli', exiting.\n");
87       return -1;
88     }
89     LLIargs[0] = LLIpath;
90     LLIargs[1] = realFilename;
91     for (idx = 1; idx != argvSize; ++idx)
92       LLIargs[idx+1] = argv[idx];
93     LLIargs[argvSize + 1] = '\0';
94     return executeProgram(LLIpath, LLIargs, envp);
95   }
96   return executeProgram(filename, argv, envp); 
97 }