ld64 with ppc
[darwin-xtools.git] / cctools / libstuff / llvm.c
blob4d131433d8ef8574696f20890fb8eacf5b65eb54
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <libc.h>
4 #include <sys/file.h>
5 #include <dlfcn.h>
6 #include "llvm-c/Disassembler.h"
7 #include "stuff/llvm.h"
8 #include "stuff/allocate.h"
9 #include <mach-o/dyld.h>
12 * The disassembler API is currently exported from libLTO.dylib. Eventually we
13 * plan to include it (along with the current libLTO APIs) in a generic
14 * libLLVM.dylib.
16 #define LIB_LLVM "libLTO.dylib"
18 static int tried_to_load_llvm = 0;
19 static void *llvm_handle = NULL;
20 static void (*initialize)(void) = NULL;
21 static LLVMDisasmContextRef (*create)(const char *, void *, int,
22 LLVMOpInfoCallback, LLVMSymbolLookupCallback) = NULL;
23 static LLVMDisasmContextRef (*createCPU)(const char *, const char *,void *, int,
24 LLVMOpInfoCallback, LLVMSymbolLookupCallback) = NULL;
25 static void (*dispose)(LLVMDisasmContextRef) = NULL;
26 static size_t (*disasm)(LLVMDisasmContextRef, uint8_t *, uint64_t, uint64_t,
27 char *, size_t) = NULL;
28 static int (*options)(LLVMDisasmContextRef, uint64_t) = NULL;
29 static const char * (*version)(void) = NULL;
32 * load_llvm() will dynamically load libLTO.dylib if tried_to_load_llvm is 0,
33 * and set llvm_handle to the value returned by dlopen() and set the function
34 * pointers.
36 static void load_llvm(void)
38 uint32_t bufsize;
39 char *p, *prefix, *llvm_path, buf[MAXPATHLEN], resolved_name[PATH_MAX];
40 int i;
42 if(tried_to_load_llvm == 0){
43 tried_to_load_llvm = 1;
45 * Construct the prefix to this executable assuming it is in a bin
46 * directory relative to a lib directory of the matching lto library
47 * and first try to load that. If not then fall back to trying
48 * "/Applications/Xcode.app/Contents/Developer/Toolchains/
49 * XcodeDefault.xctoolchain/usr/lib/" LIB_LLVM.
51 bufsize = MAXPATHLEN;
52 p = buf;
53 i = _NSGetExecutablePath(p, &bufsize);
54 if(i == -1){
55 p = allocate(bufsize);
56 _NSGetExecutablePath(p, &bufsize);
58 prefix = realpath(p, resolved_name);
59 p = rindex(prefix, '/');
60 if(p != NULL)
61 p[1] = '\0';
62 llvm_path = makestr(prefix, "../lib/" LIB_LLVM, NULL);
64 llvm_handle = dlopen(llvm_path, RTLD_NOW);
65 if(llvm_handle == NULL){
66 free(llvm_path);
67 llvm_path = NULL;
68 llvm_handle = dlopen("/Applications/Xcode.app/Contents/"
69 "Developer/Toolchains/XcodeDefault."
70 "xctoolchain/usr/lib/" LIB_LLVM,
71 RTLD_NOW);
73 if(llvm_handle == NULL)
74 return;
76 create = dlsym(llvm_handle, "LLVMCreateDisasm");
77 dispose = dlsym(llvm_handle, "LLVMDisasmDispose");
78 disasm = dlsym(llvm_handle, "LLVMDisasmInstruction");
80 /* Note we allow these to not be defined */
81 options = dlsym(llvm_handle, "LLVMSetDisasmOptions");
82 createCPU = dlsym(llvm_handle, "LLVMCreateDisasmCPU");
83 version = dlsym(llvm_handle, "lto_get_version");
85 if(create == NULL ||
86 dispose == NULL ||
87 disasm == NULL){
89 dlclose(llvm_handle);
90 if(llvm_path != NULL)
91 free(llvm_path);
92 llvm_handle = NULL;
93 create = NULL;
94 createCPU = NULL;
95 dispose = NULL;
96 disasm = NULL;
97 options = NULL;
98 version = NULL;
99 return;
102 if(llvm_handle == NULL)
103 return;
107 * Wrapper to dynamically load LIB_LLVM and call LLVMCreateDisasm().
109 __private_extern__
110 LLVMDisasmContextRef
111 llvm_create_disasm(
112 const char *TripleName,
113 const char *CPU,
114 void *DisInfo,
115 int TagType,
116 LLVMOpInfoCallback GetOpInfo,
117 LLVMSymbolLookupCallback SymbolLookUp)
119 LLVMDisasmContextRef DC;
121 if(tried_to_load_llvm == 0){
122 load_llvm();
124 if(llvm_handle == NULL)
125 return(NULL);
128 * Note this was added after the interface was defined, so it may
129 * be undefined. But if not we must call it first.
131 initialize = dlsym(llvm_handle, "lto_initialize_disassembler");
132 if(initialize != NULL)
133 initialize();
135 if(*CPU != '\0' && createCPU != NULL)
136 DC = createCPU(TripleName, CPU, DisInfo, TagType, GetOpInfo,
137 SymbolLookUp);
138 else
139 DC = create(TripleName, DisInfo, TagType, GetOpInfo, SymbolLookUp);
140 return(DC);
144 * Wrapper to call LLVMDisasmDispose().
146 __private_extern__
147 void
148 llvm_disasm_dispose(
149 LLVMDisasmContextRef DC)
151 if(dispose != NULL)
152 dispose(DC);
156 * Wrapper to call LLVMDisasmInstruction().
158 __private_extern__
159 size_t
160 llvm_disasm_instruction(
161 LLVMDisasmContextRef DC,
162 uint8_t *Bytes,
163 uint64_t BytesSize,
164 uint64_t Pc,
165 char *OutString,
166 size_t OutStringSize)
169 if(disasm == NULL)
170 return(0);
171 return(disasm(DC, Bytes, BytesSize, Pc, OutString, OutStringSize));
175 * Wrapper to call LLVMSetDisasmOptions().
177 __private_extern__
179 llvm_disasm_set_options(
180 LLVMDisasmContextRef DC,
181 uint64_t Options)
184 if(options == NULL)
185 return(0);
186 return(options(DC, Options));
190 * Wrapper to call lto_get_version().
192 __private_extern__
193 const char *
194 llvm_disasm_version_string(void)
196 if(tried_to_load_llvm == 0){
197 load_llvm();
199 if(llvm_handle == NULL)
200 return(NULL);
201 if(version == NULL)
202 return(NULL);
203 return(version());