comparison gen/toobj.cpp @ 850:5f5e6eb790e7

Automated merge with http://hg.dsource.org/projects/ldc
author Christian Kamm <kamm incasoftware de>
date Sun, 14 Dec 2008 16:30:20 +0100
parents ba390e5e9150
children c1aeb2d0b559
comparison
equal deleted inserted replaced
848:d54f7cf84e6b 850:5f5e6eb790e7
58 // in gen/optimize.cpp 58 // in gen/optimize.cpp
59 void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline); 59 void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline);
60 60
61 // fwd decl 61 // fwd decl
62 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out); 62 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out);
63 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath, char** envp); 63 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath);
64 64
65 ////////////////////////////////////////////////////////////////////////////////////////// 65 //////////////////////////////////////////////////////////////////////////////////////////
66 66
67 void Module::genobjfile(int multiobj, char** envp) 67 void Module::genobjfile(int multiobj)
68 { 68 {
69 bool logenabled = Logger::enabled(); 69 bool logenabled = Logger::enabled();
70 if (llvmForceLogging && !logenabled) 70 if (llvmForceLogging && !logenabled)
71 { 71 {
72 Logger::enable(); 72 Logger::enable();
259 } 259 }
260 260
261 // call gcc to convert assembly to object file 261 // call gcc to convert assembly to object file
262 if (global.params.output_o) { 262 if (global.params.output_o) {
263 LLPath objpath = LLPath(objfile->name->toChars()); 263 LLPath objpath = LLPath(objfile->name->toChars());
264 assemble(spath, objpath, envp); 264 assemble(spath, objpath);
265 } 265 }
266 266
267 if (!global.params.output_s) { 267 if (!global.params.output_s) {
268 spath.eraseFromDisk(); 268 spath.eraseFromDisk();
269 } 269 }
318 assert(rmod); 318 assert(rmod);
319 } 319 }
320 320
321 /* ================================================================== */ 321 /* ================================================================== */
322 322
323 // helper functions for gcc call to assemble
324 // based on llvm-ld code, University of Illinois Open Source License
325
326 /// CopyEnv - This function takes an array of environment variables and makes a
327 /// copy of it. This copy can then be manipulated any way the caller likes
328 /// without affecting the process's real environment.
329 ///
330 /// Inputs:
331 /// envp - An array of C strings containing an environment.
332 ///
333 /// Return value:
334 /// NULL - An error occurred.
335 ///
336 /// Otherwise, a pointer to a new array of C strings is returned. Every string
337 /// in the array is a duplicate of the one in the original array (i.e. we do
338 /// not copy the char *'s from one array to another).
339 ///
340 static char ** CopyEnv(char ** const envp) {
341 // Count the number of entries in the old list;
342 unsigned entries; // The number of entries in the old environment list
343 for (entries = 0; envp[entries] != NULL; entries++)
344 /*empty*/;
345
346 // Add one more entry for the NULL pointer that ends the list.
347 ++entries;
348
349 // If there are no entries at all, just return NULL.
350 if (entries == 0)
351 return NULL;
352
353 // Allocate a new environment list.
354 char **newenv = new char* [entries];
355 if ((newenv = new char* [entries]) == NULL)
356 return NULL;
357
358 // Make a copy of the list. Don't forget the NULL that ends the list.
359 entries = 0;
360 while (envp[entries] != NULL) {
361 newenv[entries] = new char[strlen (envp[entries]) + 1];
362 strcpy (newenv[entries], envp[entries]);
363 ++entries;
364 }
365 newenv[entries] = NULL;
366
367 return newenv;
368 }
369
370 // based on llvm-ld code, University of Illinois Open Source License
371
372 /// RemoveEnv - Remove the specified environment variable from the environment
373 /// array.
374 ///
375 /// Inputs:
376 /// name - The name of the variable to remove. It cannot be NULL.
377 /// envp - The array of environment variables. It cannot be NULL.
378 ///
379 /// Notes:
380 /// This is mainly done because functions to remove items from the environment
381 /// are not available across all platforms. In particular, Solaris does not
382 /// seem to have an unsetenv() function or a setenv() function (or they are
383 /// undocumented if they do exist).
384 ///
385 static void RemoveEnv(const char * name, char ** const envp) {
386 for (unsigned index=0; envp[index] != NULL; index++) {
387 // Find the first equals sign in the array and make it an EOS character.
388 char *p = strchr (envp[index], '=');
389 if (p == NULL)
390 continue;
391 else
392 *p = '\0';
393
394 // Compare the two strings. If they are equal, zap this string.
395 // Otherwise, restore it.
396 if (!strcmp(name, envp[index]))
397 *envp[index] = '\0';
398 else
399 *p = '=';
400 }
401
402 return;
403 }
404
405 // uses gcc to make an obj out of an assembly file 323 // uses gcc to make an obj out of an assembly file
406 // based on llvm-ld code, University of Illinois Open Source License 324 // based on llvm-ld code, University of Illinois Open Source License
407 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath, char** envp) 325 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath)
408 { 326 {
409 using namespace llvm; 327 using namespace llvm;
410 328
411 sys::Path gcc = llvm::sys::Program::FindProgramByName("gcc"); 329 sys::Path gcc = llvm::sys::Program::FindProgramByName("gcc");
412 if (gcc.empty()) 330 if (gcc.empty())
413 { 331 {
414 error("failed to locate gcc"); 332 error("failed to locate gcc");
415 fatal(); 333 fatal();
416 } 334 }
417
418 // Remove these environment variables from the environment of the
419 // programs that we will execute. It appears that GCC sets these
420 // environment variables so that the programs it uses can configure
421 // themselves identically.
422 //
423 // However, when we invoke GCC below, we want it to use its normal
424 // configuration. Hence, we must sanitize its environment.
425 char ** clean_env = CopyEnv(envp);
426 if (clean_env == NULL)
427 return;
428 RemoveEnv("LIBRARY_PATH", clean_env);
429 RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
430 RemoveEnv("GCC_EXEC_PREFIX", clean_env);
431 RemoveEnv("COMPILER_PATH", clean_env);
432 RemoveEnv("COLLECT_GCC", clean_env);
433
434 335
435 // Run GCC to assemble and link the program into native code. 336 // Run GCC to assemble and link the program into native code.
436 // 337 //
437 // Note: 338 // Note:
438 // We can't just assemble and link the file with the system assembler 339 // We can't just assemble and link the file with the system assembler
468 logstr << "\n" << std::flush; 369 logstr << "\n" << std::flush;
469 370
470 // Run the compiler to assembly the program. 371 // Run the compiler to assembly the program.
471 std::string ErrMsg; 372 std::string ErrMsg;
472 int R = sys::Program::ExecuteAndWait( 373 int R = sys::Program::ExecuteAndWait(
473 gcc, &Args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg); 374 gcc, &Args[0], 0, 0, 0, 0, &ErrMsg);
474 if (R) 375 if (R)
475 { 376 {
476 error("failed to invoke gcc"); 377 error("failed to invoke gcc");
477 fatal(); 378 fatal();
478 } 379 }