1 //===--- TargetRegistry.cpp - Target registration -------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/TargetRegistry.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/MC/MCAsmBackend.h"
13 #include "llvm/MC/MCCodeEmitter.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCObjectStreamer.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/Support/raw_ostream.h"
22 // Clients are responsible for avoid race conditions in registration.
23 static Target
*FirstTarget
= nullptr;
25 MCStreamer
*Target::createMCObjectStreamer(
26 const Triple
&T
, MCContext
&Ctx
, std::unique_ptr
<MCAsmBackend
> TAB
,
27 std::unique_ptr
<MCObjectWriter
> OW
, std::unique_ptr
<MCCodeEmitter
> Emitter
,
28 const MCSubtargetInfo
&STI
) const {
29 MCStreamer
*S
= nullptr;
30 switch (T
.getObjectFormat()) {
31 case Triple::UnknownObjectFormat
:
32 llvm_unreachable("Unknown object format");
34 assert((T
.isOSWindows() || T
.isUEFI()) &&
35 "only Windows and UEFI COFF are supported");
36 S
= COFFStreamerCtorFn(Ctx
, std::move(TAB
), std::move(OW
),
40 if (MachOStreamerCtorFn
)
41 S
= MachOStreamerCtorFn(Ctx
, std::move(TAB
), std::move(OW
),
44 S
= createMachOStreamer(Ctx
, std::move(TAB
), std::move(OW
),
45 std::move(Emitter
), false);
48 if (ELFStreamerCtorFn
)
49 S
= ELFStreamerCtorFn(T
, Ctx
, std::move(TAB
), std::move(OW
),
52 S
= createELFStreamer(Ctx
, std::move(TAB
), std::move(OW
),
56 S
= createWasmStreamer(Ctx
, std::move(TAB
), std::move(OW
),
60 S
= createGOFFStreamer(Ctx
, std::move(TAB
), std::move(OW
),
64 S
= XCOFFStreamerCtorFn(T
, Ctx
, std::move(TAB
), std::move(OW
),
68 S
= createSPIRVStreamer(Ctx
, std::move(TAB
), std::move(OW
),
71 case Triple::DXContainer
:
72 S
= createDXContainerStreamer(Ctx
, std::move(TAB
), std::move(OW
),
76 if (ObjectTargetStreamerCtorFn
)
77 ObjectTargetStreamerCtorFn(*S
, STI
);
81 MCStreamer
*Target::createMCObjectStreamer(
82 const Triple
&T
, MCContext
&Ctx
, std::unique_ptr
<MCAsmBackend
> &&TAB
,
83 std::unique_ptr
<MCObjectWriter
> &&OW
,
84 std::unique_ptr
<MCCodeEmitter
> &&Emitter
, const MCSubtargetInfo
&STI
, bool,
86 return createMCObjectStreamer(T
, Ctx
, std::move(TAB
), std::move(OW
),
87 std::move(Emitter
), STI
);
90 MCStreamer
*Target::createAsmStreamer(MCContext
&Ctx
,
91 std::unique_ptr
<formatted_raw_ostream
> OS
,
93 std::unique_ptr
<MCCodeEmitter
> CE
,
94 std::unique_ptr
<MCAsmBackend
> TAB
) const {
95 formatted_raw_ostream
&OSRef
= *OS
;
96 MCStreamer
*S
= llvm::createAsmStreamer(Ctx
, std::move(OS
), IP
,
97 std::move(CE
), std::move(TAB
));
98 createAsmTargetStreamer(*S
, OSRef
, IP
);
102 MCStreamer
*Target::createAsmStreamer(MCContext
&Ctx
,
103 std::unique_ptr
<formatted_raw_ostream
> OS
,
104 bool IsVerboseAsm
, bool UseDwarfDirectory
,
106 std::unique_ptr
<MCCodeEmitter
> &&CE
,
107 std::unique_ptr
<MCAsmBackend
> &&TAB
,
108 bool ShowInst
) const {
109 return createAsmStreamer(Ctx
, std::move(OS
), IP
, std::move(CE
),
113 iterator_range
<TargetRegistry::iterator
> TargetRegistry::targets() {
114 return make_range(iterator(FirstTarget
), iterator());
117 const Target
*TargetRegistry::lookupTarget(StringRef ArchName
,
119 std::string
&Error
) {
120 // Allocate target machine. First, check whether the user has explicitly
121 // specified an architecture to compile for. If so we have to look it up by
122 // name, because it might be a backend that has no mapping to a target triple.
123 const Target
*TheTarget
= nullptr;
124 if (!ArchName
.empty()) {
125 auto I
= find_if(targets(),
126 [&](const Target
&T
) { return ArchName
== T
.getName(); });
128 if (I
== targets().end()) {
129 Error
= ("invalid target '" + ArchName
+ "'.\n").str();
135 // Adjust the triple to match (if known), otherwise stick with the
137 Triple::ArchType Type
= Triple::getArchTypeForLLVMName(ArchName
);
138 if (Type
!= Triple::UnknownArch
)
139 TheTriple
.setArch(Type
);
141 // Get the target specific parser.
142 std::string TempError
;
143 TheTarget
= TargetRegistry::lookupTarget(TheTriple
.getTriple(), TempError
);
145 Error
= "unable to get target for '" + TheTriple
.getTriple() +
146 "', see --version and --triple.";
154 const Target
*TargetRegistry::lookupTarget(StringRef TT
, std::string
&Error
) {
155 // Provide special warning when no targets are initialized.
156 if (targets().begin() == targets().end()) {
157 Error
= "Unable to find target for this triple (no targets are registered)";
160 Triple::ArchType Arch
= Triple(TT
).getArch();
161 auto ArchMatch
= [&](const Target
&T
) { return T
.ArchMatchFn(Arch
); };
162 auto I
= find_if(targets(), ArchMatch
);
164 if (I
== targets().end()) {
165 Error
= ("No available targets are compatible with triple \"" + TT
+ "\"")
170 auto J
= std::find_if(std::next(I
), targets().end(), ArchMatch
);
171 if (J
!= targets().end()) {
172 Error
= std::string("Cannot choose between targets \"") + I
->Name
+
173 "\" and \"" + J
->Name
+ "\"";
180 void TargetRegistry::RegisterTarget(Target
&T
, const char *Name
,
181 const char *ShortDesc
,
182 const char *BackendName
,
183 Target::ArchMatchFnTy ArchMatchFn
,
185 assert(Name
&& ShortDesc
&& ArchMatchFn
&&
186 "Missing required target information!");
188 // Check if this target has already been initialized, we allow this as a
189 // convenience to some clients.
193 // Add to the list of targets.
194 T
.Next
= FirstTarget
;
198 T
.ShortDesc
= ShortDesc
;
199 T
.BackendName
= BackendName
;
200 T
.ArchMatchFn
= ArchMatchFn
;
204 static int TargetArraySortFn(const std::pair
<StringRef
, const Target
*> *LHS
,
205 const std::pair
<StringRef
, const Target
*> *RHS
) {
206 return LHS
->first
.compare(RHS
->first
);
209 void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream
&OS
) {
210 std::vector
<std::pair
<StringRef
, const Target
*> > Targets
;
212 for (const auto &T
: TargetRegistry::targets()) {
213 Targets
.push_back(std::make_pair(T
.getName(), &T
));
214 Width
= std::max(Width
, Targets
.back().first
.size());
216 array_pod_sort(Targets
.begin(), Targets
.end(), TargetArraySortFn
);
219 OS
<< " Registered Targets:\n";
220 for (const auto &Target
: Targets
) {
221 OS
<< " " << Target
.first
;
222 OS
.indent(Width
- Target
.first
.size())
223 << " - " << Target
.second
->getShortDescription() << '\n';