]> git.proxmox.com Git - rustc.git/blob - src/rustllvm/PassWrapper.cpp
New upstream version 1.19.0+dfsg1
[rustc.git] / src / rustllvm / PassWrapper.cpp
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #include <stdio.h>
12
13 #include "rustllvm.h"
14
15 #include "llvm/Analysis/TargetLibraryInfo.h"
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/IR/AutoUpgrade.h"
18 #include "llvm/Support/CBindingWrapping.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Host.h"
21 #include "llvm/Target/TargetMachine.h"
22 #include "llvm/Target/TargetSubtargetInfo.h"
23 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
24
25 #if LLVM_VERSION_GE(4, 0)
26 #include "llvm/Transforms/IPO/AlwaysInliner.h"
27 #endif
28
29 #include "llvm-c/Transforms/PassManagerBuilder.h"
30
31 using namespace llvm;
32 using namespace llvm::legacy;
33
34 extern cl::opt<bool> EnableARMEHABI;
35
36 typedef struct LLVMOpaquePass *LLVMPassRef;
37 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
38
39 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
40 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
41 DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
42 LLVMPassManagerBuilderRef)
43
44 extern "C" void LLVMInitializePasses() {
45 PassRegistry &Registry = *PassRegistry::getPassRegistry();
46 initializeCore(Registry);
47 initializeCodeGen(Registry);
48 initializeScalarOpts(Registry);
49 initializeVectorization(Registry);
50 initializeIPO(Registry);
51 initializeAnalysis(Registry);
52 #if LLVM_VERSION_EQ(3, 7)
53 initializeIPA(Registry);
54 #endif
55 initializeTransformUtils(Registry);
56 initializeInstCombine(Registry);
57 initializeInstrumentation(Registry);
58 initializeTarget(Registry);
59 }
60
61 enum class LLVMRustPassKind {
62 Other,
63 Function,
64 Module,
65 };
66
67 static LLVMRustPassKind toRust(PassKind Kind) {
68 switch (Kind) {
69 case PT_Function:
70 return LLVMRustPassKind::Function;
71 case PT_Module:
72 return LLVMRustPassKind::Module;
73 default:
74 return LLVMRustPassKind::Other;
75 }
76 }
77
78 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
79 StringRef SR(PassName);
80 PassRegistry *PR = PassRegistry::getPassRegistry();
81
82 const PassInfo *PI = PR->getPassInfo(SR);
83 if (PI) {
84 return wrap(PI->createPass());
85 }
86 return nullptr;
87 }
88
89 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
90 assert(RustPass);
91 Pass *Pass = unwrap(RustPass);
92 return toRust(Pass->getPassKind());
93 }
94
95 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
96 assert(RustPass);
97 Pass *Pass = unwrap(RustPass);
98 PassManagerBase *PMB = unwrap(PMR);
99 PMB->add(Pass);
100 }
101
102 #ifdef LLVM_COMPONENT_X86
103 #define SUBTARGET_X86 SUBTARGET(X86)
104 #else
105 #define SUBTARGET_X86
106 #endif
107
108 #ifdef LLVM_COMPONENT_ARM
109 #define SUBTARGET_ARM SUBTARGET(ARM)
110 #else
111 #define SUBTARGET_ARM
112 #endif
113
114 #ifdef LLVM_COMPONENT_AARCH64
115 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
116 #else
117 #define SUBTARGET_AARCH64
118 #endif
119
120 #ifdef LLVM_COMPONENT_MIPS
121 #define SUBTARGET_MIPS SUBTARGET(Mips)
122 #else
123 #define SUBTARGET_MIPS
124 #endif
125
126 #ifdef LLVM_COMPONENT_POWERPC
127 #define SUBTARGET_PPC SUBTARGET(PPC)
128 #else
129 #define SUBTARGET_PPC
130 #endif
131
132 #ifdef LLVM_COMPONENT_SYSTEMZ
133 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
134 #else
135 #define SUBTARGET_SYSTEMZ
136 #endif
137
138 #ifdef LLVM_COMPONENT_MSP430
139 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
140 #else
141 #define SUBTARGET_MSP430
142 #endif
143
144 #ifdef LLVM_COMPONENT_SPARC
145 #define SUBTARGET_SPARC SUBTARGET(Sparc)
146 #else
147 #define SUBTARGET_SPARC
148 #endif
149
150 #ifdef LLVM_COMPONENT_HEXAGON
151 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
152 #else
153 #define SUBTARGET_HEXAGON
154 #endif
155
156 #define GEN_SUBTARGETS \
157 SUBTARGET_X86 \
158 SUBTARGET_ARM \
159 SUBTARGET_AARCH64 \
160 SUBTARGET_MIPS \
161 SUBTARGET_PPC \
162 SUBTARGET_SYSTEMZ \
163 SUBTARGET_MSP430 \
164 SUBTARGET_SPARC \
165 SUBTARGET_HEXAGON
166
167 #define SUBTARGET(x) \
168 namespace llvm { \
169 extern const SubtargetFeatureKV x##FeatureKV[]; \
170 extern const SubtargetFeatureKV x##SubTypeKV[]; \
171 }
172
173 GEN_SUBTARGETS
174 #undef SUBTARGET
175
176 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
177 const char *Feature) {
178 TargetMachine *Target = unwrap(TM);
179 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
180 const FeatureBitset &Bits = MCInfo->getFeatureBits();
181 const llvm::SubtargetFeatureKV *FeatureEntry;
182
183 #define SUBTARGET(x) \
184 if (MCInfo->isCPUStringValid(x##SubTypeKV[0].Key)) { \
185 FeatureEntry = x##FeatureKV; \
186 } else
187
188 GEN_SUBTARGETS { return false; }
189 #undef SUBTARGET
190
191 while (strcmp(Feature, FeatureEntry->Key) != 0)
192 FeatureEntry++;
193
194 return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
195 }
196
197 enum class LLVMRustCodeModel {
198 Other,
199 Default,
200 JITDefault,
201 Small,
202 Kernel,
203 Medium,
204 Large,
205 };
206
207 static CodeModel::Model fromRust(LLVMRustCodeModel Model) {
208 switch (Model) {
209 case LLVMRustCodeModel::Default:
210 return CodeModel::Default;
211 case LLVMRustCodeModel::JITDefault:
212 return CodeModel::JITDefault;
213 case LLVMRustCodeModel::Small:
214 return CodeModel::Small;
215 case LLVMRustCodeModel::Kernel:
216 return CodeModel::Kernel;
217 case LLVMRustCodeModel::Medium:
218 return CodeModel::Medium;
219 case LLVMRustCodeModel::Large:
220 return CodeModel::Large;
221 default:
222 llvm_unreachable("Bad CodeModel.");
223 }
224 }
225
226 enum class LLVMRustCodeGenOptLevel {
227 Other,
228 None,
229 Less,
230 Default,
231 Aggressive,
232 };
233
234 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
235 switch (Level) {
236 case LLVMRustCodeGenOptLevel::None:
237 return CodeGenOpt::None;
238 case LLVMRustCodeGenOptLevel::Less:
239 return CodeGenOpt::Less;
240 case LLVMRustCodeGenOptLevel::Default:
241 return CodeGenOpt::Default;
242 case LLVMRustCodeGenOptLevel::Aggressive:
243 return CodeGenOpt::Aggressive;
244 default:
245 llvm_unreachable("Bad CodeGenOptLevel.");
246 }
247 }
248
249 enum class LLVMRustRelocMode {
250 Default,
251 Static,
252 PIC,
253 DynamicNoPic,
254 ROPI,
255 RWPI,
256 ROPIRWPI,
257 };
258
259 #if LLVM_VERSION_LE(3, 8)
260 static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) {
261 #else
262 static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
263 #endif
264 switch (RustReloc) {
265 case LLVMRustRelocMode::Default:
266 #if LLVM_VERSION_LE(3, 8)
267 return Reloc::Default;
268 #else
269 return None;
270 #endif
271 case LLVMRustRelocMode::Static:
272 return Reloc::Static;
273 case LLVMRustRelocMode::PIC:
274 return Reloc::PIC_;
275 case LLVMRustRelocMode::DynamicNoPic:
276 return Reloc::DynamicNoPIC;
277 #if LLVM_VERSION_GE(4, 0)
278 case LLVMRustRelocMode::ROPI:
279 return Reloc::ROPI;
280 case LLVMRustRelocMode::RWPI:
281 return Reloc::RWPI;
282 case LLVMRustRelocMode::ROPIRWPI:
283 return Reloc::ROPI_RWPI;
284 #endif
285 default:
286 llvm_unreachable("Bad RelocModel.");
287 }
288 }
289
290 #if LLVM_RUSTLLVM
291 /// getLongestEntryLength - Return the length of the longest entry in the table.
292 ///
293 static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
294 size_t MaxLen = 0;
295 for (auto &I : Table)
296 MaxLen = std::max(MaxLen, std::strlen(I.Key));
297 return MaxLen;
298 }
299
300 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
301 const TargetMachine *Target = unwrap(TM);
302 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
303 const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
304 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
305
306 printf("Available CPUs for this target:\n");
307 for (auto &CPU : CPUTable)
308 printf(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
309 printf("\n");
310 }
311
312 extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
313 const TargetMachine *Target = unwrap(TM);
314 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
315 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
316 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
317
318 printf("Available features for this target:\n");
319 for (auto &Feature : FeatTable)
320 printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
321 printf("\n");
322
323 printf("Use +feature to enable a feature, or -feature to disable it.\n"
324 "For example, rustc -C -target-cpu=mycpu -C "
325 "target-feature=+feature1,-feature2\n\n");
326 }
327
328 #else
329
330 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
331 printf("Target CPU help is not supported by this LLVM version.\n\n");
332 }
333
334 extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
335 printf("Target features help is not supported by this LLVM version.\n\n");
336 }
337 #endif
338
339 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
340 const char *TripleStr, const char *CPU, const char *Feature,
341 LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
342 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
343 bool PositionIndependentExecutable, bool FunctionSections,
344 bool DataSections) {
345
346 auto CM = fromRust(RustCM);
347 auto OptLevel = fromRust(RustOptLevel);
348 auto RM = fromRust(RustReloc);
349
350 std::string Error;
351 Triple Trip(Triple::normalize(TripleStr));
352 const llvm::Target *TheTarget =
353 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
354 if (TheTarget == nullptr) {
355 LLVMRustSetLastError(Error.c_str());
356 return nullptr;
357 }
358
359 StringRef RealCPU = CPU;
360 if (RealCPU == "native") {
361 RealCPU = sys::getHostCPUName();
362 }
363
364 TargetOptions Options;
365 #if LLVM_VERSION_LE(3, 8)
366 Options.PositionIndependentExecutable = PositionIndependentExecutable;
367 #endif
368
369 Options.FloatABIType = FloatABI::Default;
370 if (UseSoftFloat) {
371 Options.FloatABIType = FloatABI::Soft;
372 }
373 Options.DataSections = DataSections;
374 Options.FunctionSections = FunctionSections;
375
376 TargetMachine *TM = TheTarget->createTargetMachine(
377 Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel);
378 return wrap(TM);
379 }
380
381 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
382 delete unwrap(TM);
383 }
384
385 // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
386 // passes for a target to a pass manager. We export that functionality through
387 // this function.
388 extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
389 LLVMPassManagerRef PMR,
390 LLVMModuleRef M) {
391 PassManagerBase *PM = unwrap(PMR);
392 PM->add(
393 createTargetTransformInfoWrapperPass(unwrap(TM)->getTargetIRAnalysis()));
394 }
395
396 extern "C" void LLVMRustConfigurePassManagerBuilder(
397 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
398 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize) {
399 // Ignore mergefunc for now as enabling it causes crashes.
400 // unwrap(PMBR)->MergeFunctions = MergeFunctions;
401 unwrap(PMBR)->SLPVectorize = SLPVectorize;
402 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
403 unwrap(PMBR)->LoopVectorize = LoopVectorize;
404 }
405
406 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
407 // field of a PassManagerBuilder, we expose our own method of doing so.
408 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
409 LLVMModuleRef M,
410 bool DisableSimplifyLibCalls) {
411 Triple TargetTriple(unwrap(M)->getTargetTriple());
412 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
413 if (DisableSimplifyLibCalls)
414 TLI->disableAllFunctions();
415 unwrap(PMBR)->LibraryInfo = TLI;
416 }
417
418 // Unfortunately, the LLVM C API doesn't provide a way to create the
419 // TargetLibraryInfo pass, so we use this method to do so.
420 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
421 bool DisableSimplifyLibCalls) {
422 Triple TargetTriple(unwrap(M)->getTargetTriple());
423 TargetLibraryInfoImpl TLII(TargetTriple);
424 if (DisableSimplifyLibCalls)
425 TLII.disableAllFunctions();
426 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
427 }
428
429 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
430 // all the functions in a module, so we do that manually here. You'll find
431 // similar code in clang's BackendUtil.cpp file.
432 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
433 LLVMModuleRef M) {
434 llvm::legacy::FunctionPassManager *P =
435 unwrap<llvm::legacy::FunctionPassManager>(PMR);
436 P->doInitialization();
437
438 // Upgrade all calls to old intrinsics first.
439 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
440 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
441
442 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
443 ++I)
444 if (!I->isDeclaration())
445 P->run(*I);
446
447 P->doFinalization();
448 }
449
450 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
451 // Initializing the command-line options more than once is not allowed. So,
452 // check if they've already been initialized. (This could happen if we're
453 // being called from rustpkg, for example). If the arguments change, then
454 // that's just kinda unfortunate.
455 static bool Initialized = false;
456 if (Initialized)
457 return;
458 Initialized = true;
459 cl::ParseCommandLineOptions(Argc, Argv);
460 }
461
462 enum class LLVMRustFileType {
463 Other,
464 AssemblyFile,
465 ObjectFile,
466 };
467
468 static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
469 switch (Type) {
470 case LLVMRustFileType::AssemblyFile:
471 return TargetMachine::CGFT_AssemblyFile;
472 case LLVMRustFileType::ObjectFile:
473 return TargetMachine::CGFT_ObjectFile;
474 default:
475 llvm_unreachable("Bad FileType.");
476 }
477 }
478
479 extern "C" LLVMRustResult
480 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
481 LLVMModuleRef M, const char *Path,
482 LLVMRustFileType RustFileType) {
483 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
484 auto FileType = fromRust(RustFileType);
485
486 std::string ErrorInfo;
487 std::error_code EC;
488 raw_fd_ostream OS(Path, EC, sys::fs::F_None);
489 if (EC)
490 ErrorInfo = EC.message();
491 if (ErrorInfo != "") {
492 LLVMRustSetLastError(ErrorInfo.c_str());
493 return LLVMRustResult::Failure;
494 }
495
496 unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
497 PM->run(*unwrap(M));
498
499 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
500 // stream (OS), so the only real safe place to delete this is here? Don't we
501 // wish this was written in Rust?
502 delete PM;
503 return LLVMRustResult::Success;
504 }
505
506 extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
507 const char *Path) {
508 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
509 std::string ErrorInfo;
510
511 std::error_code EC;
512 raw_fd_ostream OS(Path, EC, sys::fs::F_None);
513 if (EC)
514 ErrorInfo = EC.message();
515
516 formatted_raw_ostream FOS(OS);
517
518 PM->add(createPrintModulePass(FOS));
519
520 PM->run(*unwrap(M));
521 }
522
523 extern "C" void LLVMRustPrintPasses() {
524 LLVMInitializePasses();
525 struct MyListener : PassRegistrationListener {
526 void passEnumerate(const PassInfo *Info) {
527 #if LLVM_VERSION_GE(4, 0)
528 StringRef PassArg = Info->getPassArgument();
529 StringRef PassName = Info->getPassName();
530 if (!PassArg.empty()) {
531 // These unsigned->signed casts could theoretically overflow, but
532 // realistically never will (and even if, the result is implementation
533 // defined rather plain UB).
534 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
535 (int)PassName.size(), PassName.data());
536 }
537 #else
538 if (Info->getPassArgument() && *Info->getPassArgument()) {
539 printf("%15s - %s\n", Info->getPassArgument(), Info->getPassName());
540 }
541 #endif
542 }
543 } Listener;
544
545 PassRegistry *PR = PassRegistry::getPassRegistry();
546 PR->enumerateWith(&Listener);
547 }
548
549 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
550 bool AddLifetimes) {
551 #if LLVM_VERSION_GE(4, 0)
552 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
553 #else
554 unwrap(PMBR)->Inliner = createAlwaysInlinerPass(AddLifetimes);
555 #endif
556 }
557
558 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
559 size_t Len) {
560 llvm::legacy::PassManager passes;
561
562 #if LLVM_VERSION_LE(3, 8)
563 ArrayRef<const char *> Ref(Symbols, Len);
564 passes.add(llvm::createInternalizePass(Ref));
565 #else
566 auto PreserveFunctions = [=](const GlobalValue &GV) {
567 for (size_t I = 0; I < Len; I++) {
568 if (GV.getName() == Symbols[I]) {
569 return true;
570 }
571 }
572 return false;
573 };
574
575 passes.add(llvm::createInternalizePass(PreserveFunctions));
576 #endif
577
578 passes.run(*unwrap(M));
579 }
580
581 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
582 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
583 ++GV) {
584 GV->setDoesNotThrow();
585 Function *F = dyn_cast<Function>(GV);
586 if (F == nullptr)
587 continue;
588
589 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
590 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
591 if (isa<InvokeInst>(I)) {
592 InvokeInst *CI = cast<InvokeInst>(I);
593 CI->setDoesNotThrow();
594 }
595 }
596 }
597 }
598 }
599
600 extern "C" void
601 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
602 LLVMTargetMachineRef TMR) {
603 TargetMachine *Target = unwrap(TMR);
604 unwrap(Module)->setDataLayout(Target->createDataLayout());
605 }
606
607 extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
608 return wrap(&unwrap(M)->getDataLayout());
609 }
610
611 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
612 #if LLVM_VERSION_GE(3, 9)
613 unwrap(M)->setPIELevel(PIELevel::Level::Large);
614 #endif
615 }