Mercurial > projects > ldc
comparison dmd/link.c @ 276:21f85bac0b1a trunk
[svn r297] Fixed: rewrote linker code to use LLVM's Program facilities instead of DMD's oldschool broken "native" approach.
author | lindquist |
---|---|
date | Fri, 20 Jun 2008 17:45:13 +0200 |
parents | b77664331d06 |
children |
comparison
equal
deleted
inserted
replaced
275:665b81613475 | 276:21f85bac0b1a |
---|---|
34 | 34 |
35 #include "gen/logger.h" | 35 #include "gen/logger.h" |
36 | 36 |
37 int executecmd(char *cmd, char *args, int useenv); | 37 int executecmd(char *cmd, char *args, int useenv); |
38 int executearg0(char *cmd, char *args); | 38 int executearg0(char *cmd, char *args); |
39 | |
40 /***************************** | |
41 * Run the linker. Return status of execution. | |
42 */ | |
43 | |
44 int runLINK() | |
45 { | |
46 Logger::println("*** Linking executable ***"); | |
47 | |
48 #if _WIN32 | |
49 assert(0 && "linking not done for win32"); | |
50 | |
51 char *p; | |
52 int i; | |
53 int status; | |
54 OutBuffer cmdbuf; | |
55 | |
56 global.params.libfiles->push((void *) "user32"); | |
57 global.params.libfiles->push((void *) "kernel32"); | |
58 | |
59 for (i = 0; i < global.params.objfiles->dim; i++) | |
60 { | |
61 if (i) | |
62 cmdbuf.writeByte('+'); | |
63 p = (char *)global.params.objfiles->data[i]; | |
64 char *ext = FileName::ext(p); | |
65 if (ext) | |
66 cmdbuf.write(p, ext - p - 1); | |
67 else | |
68 cmdbuf.writestring(p); | |
69 } | |
70 cmdbuf.writeByte(','); | |
71 if (global.params.exefile) | |
72 cmdbuf.writestring(global.params.exefile); | |
73 else | |
74 { // Generate exe file name from first obj name | |
75 char *n = (char *)global.params.objfiles->data[0]; | |
76 char *ex; | |
77 | |
78 n = FileName::name(n); | |
79 FileName *fn = FileName::forceExt(n, "exe"); | |
80 global.params.exefile = fn->toChars(); | |
81 } | |
82 | |
83 // Make sure path to exe file exists | |
84 { char *p = FileName::path(global.params.exefile); | |
85 FileName::ensurePathExists(p); | |
86 mem.free(p); | |
87 } | |
88 | |
89 cmdbuf.writeByte(','); | |
90 if (global.params.run) | |
91 cmdbuf.writestring("nul"); | |
92 // if (mapfile) | |
93 // cmdbuf.writestring(output); | |
94 cmdbuf.writeByte(','); | |
95 | |
96 for (i = 0; i < global.params.libfiles->dim; i++) | |
97 { | |
98 if (i) | |
99 cmdbuf.writeByte('+'); | |
100 cmdbuf.writestring((char *) global.params.libfiles->data[i]); | |
101 } | |
102 | |
103 if (global.params.deffile) | |
104 { | |
105 cmdbuf.writeByte(','); | |
106 cmdbuf.writestring(global.params.deffile); | |
107 } | |
108 | |
109 /* Eliminate unnecessary trailing commas */ | |
110 while (1) | |
111 { i = cmdbuf.offset; | |
112 if (!i || cmdbuf.data[i - 1] != ',') | |
113 break; | |
114 cmdbuf.offset--; | |
115 } | |
116 | |
117 if (global.params.resfile) | |
118 { | |
119 cmdbuf.writestring("/RC:"); | |
120 cmdbuf.writestring(global.params.resfile); | |
121 } | |
122 | |
123 #if 0 | |
124 if (mapfile) | |
125 cmdbuf.writestring("/m"); | |
126 if (debuginfo) | |
127 cmdbuf.writestring("/li"); | |
128 if (codeview) | |
129 { | |
130 cmdbuf.writestring("/co"); | |
131 if (codeview3) | |
132 cmdbuf.writestring(":3"); | |
133 } | |
134 #else | |
135 if (global.params.symdebug) | |
136 cmdbuf.writestring("/co"); | |
137 #endif | |
138 | |
139 cmdbuf.writestring("/noi"); | |
140 for (i = 0; i < global.params.linkswitches->dim; i++) | |
141 { | |
142 cmdbuf.writestring((char *) global.params.linkswitches->data[i]); | |
143 } | |
144 cmdbuf.writeByte(';'); | |
145 | |
146 p = cmdbuf.toChars(); | |
147 | |
148 FileName *lnkfilename = NULL; | |
149 size_t plen = strlen(p); | |
150 if (plen > 7000) | |
151 { | |
152 lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); | |
153 File flnk(lnkfilename); | |
154 flnk.setbuffer(p, plen); | |
155 flnk.ref = 1; | |
156 if (flnk.write()) | |
157 error("error writing file %s", lnkfilename); | |
158 if (lnkfilename->len() < plen) | |
159 sprintf(p, "@%s", lnkfilename->toChars()); | |
160 } | |
161 | |
162 char *linkcmd = getenv("LINKCMD"); | |
163 if (!linkcmd) | |
164 linkcmd = "link"; | |
165 status = executecmd(linkcmd, p, 1); | |
166 if (lnkfilename) | |
167 { | |
168 remove(lnkfilename->toChars()); | |
169 delete lnkfilename; | |
170 } | |
171 return status; | |
172 #elif linux | |
173 pid_t childpid; | |
174 int i; | |
175 int status; | |
176 | |
177 // Build argv[] | |
178 Array argv; | |
179 | |
180 //char *cc = getenv("CC"); | |
181 //if (!cc) | |
182 //cc = "gcc"; | |
183 char *cc = "llvm-ld"; | |
184 argv.push((void *)cc); | |
185 | |
186 // None of that a.out stuff. Use explicit exe file name, or | |
187 // generate one from name of first source file. | |
188 OutBuffer* exestr = new OutBuffer; | |
189 if (global.params.exefile) | |
190 { | |
191 exestr->printf("-o=%s", global.params.exefile); | |
192 argv.push(exestr->toChars()); | |
193 } | |
194 else | |
195 { // Generate exe file name from first obj name | |
196 char *n = (char *)global.params.objfiles->data[0]; | |
197 char *e; | |
198 char *ex; | |
199 | |
200 n = FileName::name(n); | |
201 e = FileName::ext(n); | |
202 if (e) | |
203 { | |
204 e--; // back up over '.' | |
205 ex = (char *)mem.malloc(e - n + 1); | |
206 memcpy(ex, n, e - n); | |
207 ex[e - n] = 0; | |
208 } | |
209 else | |
210 ex = (char *)"a.out"; // no extension, so give up | |
211 exestr->printf("-o=%s", ex); | |
212 ex = exestr->toChars(); | |
213 argv.push(ex); | |
214 global.params.exefile = ex; | |
215 } | |
216 | |
217 // Make sure path to exe file exists | |
218 { char *p = FileName::path(global.params.exefile); | |
219 FileName::ensurePathExists(p); | |
220 mem.free(p); | |
221 } | |
222 | |
223 argv.insert(argv.dim, global.params.libfiles); | |
224 | |
225 if (!global.params.symdebug) | |
226 argv.push((void *)"-strip-debug"); | |
227 | |
228 //argv.push((void *)"-m32"); | |
229 | |
230 | |
231 if (!global.params.optimize) | |
232 argv.push((void *)"-disable-opt"); | |
233 else { | |
234 const char* s = 0; | |
235 switch(global.params.optimizeLevel) { | |
236 case 0: | |
237 s = "-O0"; break; | |
238 case 1: | |
239 s = "-O1"; break; | |
240 case 2: | |
241 s = "-O2"; break; | |
242 case 3: | |
243 s = "-O3"; break; | |
244 case 4: | |
245 s = "-O4"; break; | |
246 case 5: | |
247 s = "-O5"; break; | |
248 default: | |
249 assert(0); | |
250 } | |
251 argv.push((void*)s); | |
252 } | |
253 | |
254 if (!(global.params.useInline || global.params.llvmInline)) { | |
255 argv.push((void *)"-disable-inlining"); | |
256 } | |
257 | |
258 #if 0 | |
259 if (0 && global.params.exefile) | |
260 { | |
261 /* This switch enables what is known as 'smart linking' | |
262 * in the Windows world, where unreferenced sections | |
263 * are removed from the executable. It eliminates unreferenced | |
264 * functions, essentially making a 'library' out of a module. | |
265 * Although it is documented to work with ld version 2.13, | |
266 * in practice it does not, but just seems to be ignored. | |
267 * Thomas Kuehne has verified that it works with ld 2.16.1. | |
268 * BUG: disabled because it causes exception handling to fail | |
269 */ | |
270 argv.push((void *)"-Xlinker"); | |
271 argv.push((void *)"--gc-sections"); | |
272 } | |
273 #endif | |
274 | |
275 for (i = 0; i < global.params.linkswitches->dim; i++) | |
276 { char *p = (char *)global.params.linkswitches->data[i]; | |
277 //if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) | |
278 //{ // Don't need -Xlinker if switch starts with -l | |
279 // argv.push((void *)"-Xlinker"); | |
280 //} | |
281 argv.push((void *) p); | |
282 } | |
283 | |
284 argv.push((void*)"-native"); | |
285 | |
286 /* Standard libraries must go after user specified libraries | |
287 * passed with -l. | |
288 */ | |
289 | |
290 argv.push((void*)"-ltango-base-c-llvmdc"); | |
291 argv.push((void*)"-lpthread"); | |
292 argv.push((void*)"-ldl"); | |
293 argv.push((void*)"-lm"); | |
294 | |
295 argv.append(global.params.objfiles); | |
296 | |
297 std::string runtime_path(global.params.runtimePath); | |
298 if (*runtime_path.rbegin() != '/') | |
299 runtime_path.append("/"); | |
300 runtime_path.append("libtango-base-llvmdc.a"); | |
301 argv.push((void*)runtime_path.c_str()); | |
302 | |
303 if (!global.params.quiet || global.params.verbose) | |
304 { | |
305 // Print it | |
306 for (i = 0; i < argv.dim; i++) | |
307 printf("%s ", (char *)argv.data[i]); | |
308 printf("\n"); | |
309 fflush(stdout); | |
310 } | |
311 | |
312 argv.push(NULL); | |
313 childpid = fork(); | |
314 if (childpid == 0) | |
315 { | |
316 execvp((char *)argv.data[0], (char **)argv.data); | |
317 perror((char *)argv.data[0]); // failed to execute | |
318 return -1; | |
319 } | |
320 | |
321 waitpid(childpid, &status, 0); | |
322 | |
323 status=WEXITSTATUS(status); | |
324 if (status) | |
325 printf("--- errorlevel %d\n", status); | |
326 return status; | |
327 #else | |
328 printf ("Linking is not yet supported for this version of LLVMDC.\n"); | |
329 return -1; | |
330 #endif | |
331 } | |
332 | 39 |
333 /********************************** | 40 /********************************** |
334 * Delete generated EXE file. | 41 * Delete generated EXE file. |
335 */ | 42 */ |
336 | 43 |