blob: 20f12c7455e1bfc0eec288659f3fb197519bee64 [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- TargetInfo.cpp - Information about Target machine ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the TargetInfo and TargetInfoImpl interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/TargetInfo.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/AST/Builtins.h"
17#include "llvm/ADT/StringMap.h"
Chris Lattner858eece2007-09-22 18:29:59 +000018#include "llvm/ADT/APFloat.h"
Chris Lattner4b009652007-07-25 00:24:17 +000019#include <set>
20using namespace clang;
21
22void TargetInfoImpl::ANCHOR() {} // out-of-line virtual method for class.
23
24
Chris Lattner858eece2007-09-22 18:29:59 +000025//===----------------------------------------------------------------------===//
26// FIXME: These are temporary hacks, they should revector into the
27// TargetInfoImpl.
28
29void TargetInfo::getFloatInfo(uint64_t &Size, unsigned &Align,
30 const llvm::fltSemantics *&Format,
31 SourceLocation Loc) {
32 Align = 32; // FIXME: implement correctly.
33 Size = 32;
34 Format = &llvm::APFloat::IEEEsingle;
35}
36void TargetInfo::getDoubleInfo(uint64_t &Size, unsigned &Align,
37 const llvm::fltSemantics *&Format,
38 SourceLocation Loc) {
39 Size = Align = 64; // FIXME: implement correctly.
40 Format = &llvm::APFloat::IEEEdouble;
41}
42void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align,
43 const llvm::fltSemantics *&Format,
44 SourceLocation Loc) {
Chris Lattner36f46b82007-09-22 18:38:30 +000045 Size = Align = 64; // FIXME: implement correctly.
46 Format = &llvm::APFloat::IEEEdouble;
47 //Size = 80; Align = 32; // FIXME: implement correctly.
48 //Format = &llvm::APFloat::x87DoubleExtended;
Chris Lattner858eece2007-09-22 18:29:59 +000049}
50
51
52//===----------------------------------------------------------------------===//
53
Chris Lattner4b009652007-07-25 00:24:17 +000054/// DiagnoseNonPortability - When a use of a non-portable target feature is
55/// used, this method emits the diagnostic and marks the translation unit as
56/// non-portable.
57void TargetInfo::DiagnoseNonPortability(SourceLocation Loc, unsigned DiagKind) {
58 NonPortable = true;
59 if (Diag && Loc.isValid()) Diag->Report(Loc, DiagKind);
60}
61
62/// GetTargetDefineMap - Get the set of target #defines in an associative
63/// collection for easy lookup.
64static void GetTargetDefineMap(const TargetInfoImpl *Target,
65 llvm::StringMap<std::string> &Map) {
Chris Lattner0db667a2007-10-06 06:57:34 +000066 std::vector<char> Defines;
67 Defines.reserve(4096);
68 Target->getTargetDefines(Defines);
Chris Lattner4b009652007-07-25 00:24:17 +000069
Chris Lattner0db667a2007-10-06 06:57:34 +000070 for (const char *DefStr = &Defines[0], *E = DefStr+Defines.size();
71 DefStr != E;) {
72 // Skip the '#define ' portion.
73 assert(memcmp(DefStr, "#define ", strlen("#define ")) == 0 &&
74 "#define didn't start with #define!");
75 DefStr += strlen("#define ");
Chris Lattner4b009652007-07-25 00:24:17 +000076
Chris Lattner0db667a2007-10-06 06:57:34 +000077 // Find the divider between the key and value.
78 const char *SpacePos = strchr(DefStr, ' ');
79
80 std::string &Entry = Map.GetOrCreateValue(DefStr, SpacePos).getValue();
81
82 const char *EndPos = strchr(SpacePos+1, '\n');
83 Entry = std::string(SpacePos+1, EndPos);
84 DefStr = EndPos+1;
Chris Lattner4b009652007-07-25 00:24:17 +000085 }
86}
87
88/// getTargetDefines - Appends the target-specific #define values for this
89/// target set to the specified buffer.
90void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
Chris Lattner8c9d29f2007-10-06 06:29:41 +000091 // If we have no secondary targets, be a bit more efficient.
92 if (SecondaryTargets.empty()) {
Chris Lattner0db667a2007-10-06 06:57:34 +000093 PrimaryTarget->getTargetDefines(Buffer);
Chris Lattner8c9d29f2007-10-06 06:29:41 +000094 return;
95 }
96
Chris Lattner4b009652007-07-25 00:24:17 +000097 // This is tricky in the face of secondary targets. Specifically,
98 // target-specific #defines that are present and identical across all
99 // secondary targets are turned into #defines, #defines that are present in
100 // the primary target but are missing or different in the secondary targets
101 // are turned into #define_target, and #defines that are not defined in the
102 // primary, but are defined in a secondary are turned into
103 // #define_other_target. This allows the preprocessor to correctly track uses
104 // of target-specific macros.
105
106 // Get the set of primary #defines.
107 llvm::StringMap<std::string> PrimaryDefines;
108 GetTargetDefineMap(PrimaryTarget, PrimaryDefines);
109
Chris Lattner4b009652007-07-25 00:24:17 +0000110 // Get the sets of secondary #defines.
111 llvm::StringMap<std::string> *SecondaryDefines
112 = new llvm::StringMap<std::string>[SecondaryTargets.size()];
113 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i)
114 GetTargetDefineMap(SecondaryTargets[i], SecondaryDefines[i]);
115
116 // Loop over all defines in the primary target, processing them until we run
117 // out.
118 for (llvm::StringMap<std::string>::iterator PDI =
119 PrimaryDefines.begin(), E = PrimaryDefines.end(); PDI != E; ++PDI) {
120 std::string DefineName(PDI->getKeyData(),
121 PDI->getKeyData() + PDI->getKeyLength());
122 std::string DefineValue = PDI->getValue();
123
124 // Check to see whether all secondary targets have this #define and whether
125 // it is to the same value. Remember if not, but remove the #define from
126 // their collection in any case if they have it.
127 bool isPortable = true;
128
129 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
130 llvm::StringMap<std::string>::iterator I =
131 SecondaryDefines[i].find(&DefineName[0],
132 &DefineName[0]+DefineName.size());
133 if (I == SecondaryDefines[i].end()) {
134 // Secondary target doesn't have this #define.
135 isPortable = false;
136 } else {
137 // Secondary target has this define, remember if it disagrees.
138 if (isPortable)
139 isPortable = I->getValue() == DefineValue;
140 // Remove it from the secondary target unconditionally.
141 SecondaryDefines[i].erase(I);
142 }
143 }
144
145 // If this define is non-portable, turn it into #define_target, otherwise
146 // just use #define.
147 const char *Command = isPortable ? "#define " : "#define_target ";
148 Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
149
150 // Insert "defname defvalue\n".
151 Buffer.insert(Buffer.end(), DefineName.begin(), DefineName.end());
152 Buffer.push_back(' ');
153 Buffer.insert(Buffer.end(), DefineValue.begin(), DefineValue.end());
154 Buffer.push_back('\n');
155 }
156
157 // Now that all of the primary target's defines have been handled and removed
158 // from the secondary target's define sets, go through the remaining secondary
159 // target's #defines and taint them.
160 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
161 llvm::StringMap<std::string> &Defs = SecondaryDefines[i];
162 while (!Defs.empty()) {
163 const char *DefStart = Defs.begin()->getKeyData();
164 const char *DefEnd = DefStart + Defs.begin()->getKeyLength();
165
166 // Insert "#define_other_target defname".
167 const char *Command = "#define_other_target ";
168 Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
169 Buffer.insert(Buffer.end(), DefStart, DefEnd);
170 Buffer.push_back('\n');
171
172 // If any other secondary targets have this same define, remove it from
173 // them to avoid duplicate #define_other_target directives.
174 for (unsigned j = i+1; j != e; ++j) {
175 llvm::StringMap<std::string>::iterator I =
176 SecondaryDefines[j].find(DefStart, DefEnd);
177 if (I != SecondaryDefines[j].end())
178 SecondaryDefines[j].erase(I);
179 }
180 Defs.erase(Defs.begin());
181 }
182 }
183
184 delete[] SecondaryDefines;
185}
186
187/// ComputeWCharWidth - Determine the width of the wchar_t type for the primary
188/// target, diagnosing whether this is non-portable across the secondary
189/// targets.
190void TargetInfo::ComputeWCharInfo(SourceLocation Loc) {
191 PrimaryTarget->getWCharInfo(WCharWidth, WCharAlign);
192
193 // Check whether this is portable across the secondary targets if the T-U is
194 // portable so far.
195 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
196 unsigned Width, Align;
197 SecondaryTargets[i]->getWCharInfo(Width, Align);
198 if (Width != WCharWidth || Align != WCharAlign)
199 return DiagnoseNonPortability(Loc, diag::port_wchar_t);
200 }
201}
202
203
204/// getTargetBuiltins - Return information about target-specific builtins for
205/// the current primary target, and info about which builtins are non-portable
206/// across the current set of primary and secondary targets.
207void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
208 unsigned &NumRecords,
209 std::vector<const char *> &NPortable) const {
210 // Get info about what actual builtins we will expose.
211 PrimaryTarget->getTargetBuiltins(Records, NumRecords);
212 if (SecondaryTargets.empty()) return;
213
214 // Compute the set of non-portable builtins.
215
216 // Start by computing a mapping from the primary target's builtins to their
217 // info records for efficient lookup.
218 llvm::StringMap<const Builtin::Info*> PrimaryRecs;
219 for (unsigned i = 0, e = NumRecords; i != e; ++i) {
220 const char *BIName = Records[i].Name;
221 PrimaryRecs.GetOrCreateValue(BIName, BIName+strlen(BIName)).getValue()
222 = Records+i;
223 }
224
225 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
226 // Get the builtins for this secondary target.
227 const Builtin::Info *Records2nd;
228 unsigned NumRecords2nd;
229 SecondaryTargets[i]->getTargetBuiltins(Records2nd, NumRecords2nd);
230
231 // Remember all of the secondary builtin names.
232 std::set<std::string> BuiltinNames2nd;
233
234 for (unsigned j = 0, e = NumRecords2nd; j != e; ++j) {
235 BuiltinNames2nd.insert(Records2nd[j].Name);
236
237 // Check to see if the primary target has this builtin.
238 llvm::StringMap<const Builtin::Info*>::iterator I =
239 PrimaryRecs.find(Records2nd[j].Name,
240 Records2nd[j].Name+strlen(Records2nd[j].Name));
241 if (I != PrimaryRecs.end()) {
242 const Builtin::Info *PrimBI = I->getValue();
243 // If does. If they are not identical, mark the builtin as being
244 // non-portable.
245 if (Records2nd[j] != *PrimBI)
246 NPortable.push_back(PrimBI->Name);
247 } else {
248 // The primary target doesn't have this, it is non-portable.
249 NPortable.push_back(Records2nd[j].Name);
250 }
251 }
252
253 // Now that we checked all the secondary builtins, check to see if the
254 // primary target has any builtins that the secondary one doesn't. If so,
255 // then those are non-portable.
256 for (unsigned j = 0, e = NumRecords; j != e; ++j) {
257 if (!BuiltinNames2nd.count(Records[j].Name))
258 NPortable.push_back(Records[j].Name);
259 }
260 }
261}
262
263