Mercurial > projects > ldc
comparison gen/linker.cpp @ 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 | a95056b3c996 |
children | 90a8c798b0db |
comparison
equal
deleted
inserted
replaced
275:665b81613475 | 276:21f85bac0b1a |
---|---|
1 #include "gen/llvm.h" | 1 #include "gen/llvm.h" |
2 #include "llvm/Linker.h" | 2 #include "llvm/Linker.h" |
3 #include "llvm/System/Program.h" | |
3 | 4 |
4 #include "root.h" | 5 #include "root.h" |
5 #include "mars.h" | 6 #include "mars.h" |
7 #include "module.h" | |
8 | |
9 #define NO_COUT_LOGGER | |
10 #include "gen/logger.h" | |
11 | |
12 ////////////////////////////////////////////////////////////////////////////// | |
6 | 13 |
7 typedef std::vector<llvm::Module*> Module_vector; | 14 typedef std::vector<llvm::Module*> Module_vector; |
8 | 15 |
9 void linkModules(llvm::Module* dst, const Module_vector& MV) | 16 void linkModules(llvm::Module* dst, const Module_vector& MV) |
10 { | 17 { |
21 error("%s", err.c_str()); | 28 error("%s", err.c_str()); |
22 fatal(); | 29 fatal(); |
23 } | 30 } |
24 } | 31 } |
25 } | 32 } |
33 | |
34 ////////////////////////////////////////////////////////////////////////////// | |
35 | |
36 int linkExecutable() | |
37 { | |
38 Logger::println("*** Linking executable ***"); | |
39 | |
40 // error string | |
41 std::string errstr; | |
42 | |
43 // find the llvm-ld program | |
44 llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld"); | |
45 if (ldpath.isEmpty()) | |
46 { | |
47 error("linker program not found"); | |
48 fatal(); | |
49 } | |
50 | |
51 // build arguments | |
52 std::vector<const char*> args; | |
53 | |
54 // first the program name ?? | |
55 args.push_back("llvm-ld"); | |
56 | |
57 // output filename | |
58 std::string exestr; | |
59 if (global.params.exefile) | |
60 { // explicit | |
61 exestr = global.params.exefile; | |
62 } | |
63 else | |
64 { // inferred | |
65 // try root module name | |
66 if (Module::rootModule) | |
67 exestr = Module::rootModule->toChars(); | |
68 else | |
69 exestr = "a.out"; | |
70 } | |
71 if (global.params.isWindows) | |
72 exestr.append(".exe"); | |
73 | |
74 std::string outopt = "-o=" + exestr; | |
75 args.push_back(outopt.c_str()); | |
76 | |
77 // create path to exe | |
78 llvm::sys::Path exepath(exestr); | |
79 exepath.set(exepath.getDirname()); | |
80 exepath.createDirectoryOnDisk(true, &errstr); | |
81 if (!errstr.empty()) | |
82 { | |
83 error("failed to create path to linking output\n%s", errstr.c_str()); | |
84 fatal(); | |
85 } | |
86 | |
87 // strip debug info | |
88 if (!global.params.symdebug) | |
89 args.push_back("-strip-debug"); | |
90 | |
91 // optimization level | |
92 if (!global.params.optimize) | |
93 args.push_back("-disable-opt"); | |
94 else | |
95 { | |
96 const char* s = 0; | |
97 switch(global.params.optimizeLevel) | |
98 { | |
99 case 0: | |
100 s = "-O0"; break; | |
101 case 1: | |
102 s = "-O1"; break; | |
103 case 2: | |
104 s = "-O2"; break; | |
105 case 3: | |
106 s = "-O3"; break; | |
107 case 4: | |
108 s = "-O4"; break; | |
109 case 5: | |
110 s = "-O5"; break; | |
111 default: | |
112 assert(0); | |
113 } | |
114 args.push_back(s); | |
115 } | |
116 | |
117 // inlining | |
118 if (!(global.params.useInline || global.params.llvmInline)) | |
119 { | |
120 args.push_back("-disable-inlining"); | |
121 } | |
122 | |
123 // additional linker switches | |
124 for (int i = 0; i < global.params.linkswitches->dim; i++) | |
125 { | |
126 char *p = (char *)global.params.linkswitches->data[i]; | |
127 args.push_back(p); | |
128 } | |
129 | |
130 // native please | |
131 args.push_back("-native"); | |
132 | |
133 | |
134 // user libs | |
135 for (int i = 0; i < global.params.libfiles->dim; i++) | |
136 { | |
137 char *p = (char *)global.params.libfiles->data[i]; | |
138 args.push_back(p); | |
139 } | |
140 | |
141 // default libs | |
142 args.push_back("-ltango-base-c-llvmdc"); | |
143 args.push_back("-lpthread"); | |
144 args.push_back("-ldl"); | |
145 args.push_back("-lm"); | |
146 | |
147 // object files | |
148 for (int i = 0; i < global.params.objfiles->dim; i++) | |
149 { | |
150 char *p = (char *)global.params.objfiles->data[i]; | |
151 args.push_back(p); | |
152 } | |
153 | |
154 // runtime library | |
155 // must be linked in last to null terminate the moduleinfo appending list | |
156 std::string runtime_path(global.params.runtimePath); | |
157 if (*runtime_path.rbegin() != '/') | |
158 runtime_path.append("/"); | |
159 runtime_path.append("libtango-base-llvmdc.a"); | |
160 args.push_back(runtime_path.c_str()); | |
161 | |
162 // print link command? | |
163 if (!global.params.quiet || global.params.verbose) | |
164 { | |
165 // Print it | |
166 for (int i = 0; i < args.size(); i++) | |
167 printf("%s ", args[i]); | |
168 printf("\n"); | |
169 fflush(stdout); | |
170 } | |
171 | |
172 // terminate args list | |
173 args.push_back(NULL); | |
174 | |
175 // try to call linker!!! | |
176 if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr)) | |
177 { | |
178 error("linking failed:\nstatus: %d", status); | |
179 if (!errstr.empty()) | |
180 error("message: %s", errstr.c_str()); | |
181 fatal(); | |
182 } | |
183 } |