blob: 21925fd33e9250346e1d80c8591de06ad073fc6e [file] [log] [blame]
Chris Lattner1e27fe12006-10-14 07:06:20 +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"
Chris Lattner2194ddc2006-10-14 18:32:26 +000016#include <map>
Chris Lattner1e27fe12006-10-14 07:06:20 +000017using namespace llvm;
18using namespace clang;
19
Chris Lattner2194ddc2006-10-14 18:32:26 +000020void TargetInfoImpl::ANCHOR() {} // out-of-line virtual method for class.
21
22
Chris Lattner1e27fe12006-10-14 07:06:20 +000023/// DiagnoseNonPortability - When a use of a non-portable target feature is
24/// used, this method emits the diagnostic and marks the translation unit as
25/// non-portable.
26void TargetInfo::DiagnoseNonPortability(SourceLocation Loc, unsigned DiagKind) {
27 NonPortable = true;
28 if (Diag) Diag->Report(Loc, DiagKind);
29}
30
Chris Lattner2194ddc2006-10-14 18:32:26 +000031/// GetTargetDefineMap - Get the set of target #defines in an associative
32/// collection for easy lookup.
33static void GetTargetDefineMap(const TargetInfoImpl *Target,
34 std::map<std::string, std::string> &Map) {
35 std::vector<std::string> PrimaryDefines;
36 Target->getTargetDefines(PrimaryDefines);
37
38 while (!PrimaryDefines.empty()) {
39 const char *Str = PrimaryDefines.back().c_str();
40 if (const char *Equal = strchr(Str, '=')) {
41 // Split at the '='.
42 Map.insert(std::make_pair(std::string(Str, Equal),
43 std::string(Equal+1,
44 Str+PrimaryDefines.back().size())));
45 } else {
46 // Remember "macroname=1".
47 Map.insert(std::make_pair(PrimaryDefines.back(), std::string("1")));
48 }
49 PrimaryDefines.pop_back();
50 }
51}
52
53/// getTargetDefines - Appends the target-specific #define values for this
54/// target set to the specified buffer.
55void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
56 // This is tricky in the face of secondary targets. Specifically,
57 // target-specific #defines that are present and identical across all
58 // secondary targets are turned into #defines, #defines that are present in
59 // the primary target but are missing or different in the secondary targets
60 // are turned into #define_target, and #defines that are not defined in the
61 // primary, but are defined in a secondary are turned into
62 // #define_other_target. This allows the preprocessor to correctly track uses
63 // of target-specific macros.
64
65 // Get the set of primary #defines.
66 std::map<std::string, std::string> PrimaryDefines;
67 GetTargetDefineMap(PrimaryTarget, PrimaryDefines);
68
69 // Get the sets of secondary #defines.
70 std::vector<std::map<std::string, std::string> > SecondaryDefines;
71 SecondaryDefines.resize(SecondaryTargets.size());
72 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i)
73 GetTargetDefineMap(SecondaryTargets[i], SecondaryDefines[i]);
74
75 // Loop over all defines in the primary target, processing them until we run
76 // out.
77 while (!PrimaryDefines.empty()) {
78 std::string DefineName = PrimaryDefines.begin()->first;
79 std::string DefineValue = PrimaryDefines.begin()->second;
80 PrimaryDefines.erase(PrimaryDefines.begin());
81
82 // Check to see whether all secondary targets have this #define and whether
83 // it is to the same value. Remember if not, but remove the #define from
84 // their collection in any case if they have it.
85 bool isPortable = true;
86
87 for (unsigned i = 0, e = SecondaryDefines.size(); i != e; ++i) {
88 std::map<std::string, std::string>::iterator I =
89 SecondaryDefines[i].find(DefineName);
90 if (I == SecondaryDefines[i].end()) {
91 // Secondary target doesn't have this #define.
92 isPortable = false;
93 } else {
94 // Secondary target has this define, remember if it disagrees.
95 if (isPortable)
96 isPortable = I->second == DefineValue;
97 // Remove it from the secondary target unconditionally.
98 SecondaryDefines[i].erase(I);
99 }
100 }
101
102 // If this define is non-portable, turn it into #define_target, otherwise
103 // just use #define.
104 const char *Command = isPortable ? "#define " : "#define_target ";
105 Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
106
107 // Insert "defname defvalue\n".
108 Buffer.insert(Buffer.end(), DefineName.begin(), DefineName.end());
109 Buffer.push_back(' ');
110 Buffer.insert(Buffer.end(), DefineValue.begin(), DefineValue.end());
111 Buffer.push_back('\n');
112 }
113
114 // Now that all of the primary target's defines have been handled and removed
115 // from the secondary target's define sets, go through the remaining secondary
116 // target's #defines and taint them.
117 for (unsigned i = 0, e = SecondaryDefines.size(); i != e; ++i) {
118 std::map<std::string, std::string> &Defs = SecondaryDefines[i];
119 while (!Defs.empty()) {
120 const std::string &DefName = Defs.begin()->first;
121
122 // Insert "#define_other_target defname".
123 const char *Command = "#define_other_target ";
124 Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
125 Buffer.insert(Buffer.end(), DefName.begin(), DefName.end());
126 Buffer.push_back('\n');
127
128 // If any other secondary targets have this same define, remove it from
129 // them to avoid duplicate #define_other_target directives.
130 for (unsigned j = i+1; j != e; ++j)
131 SecondaryDefines[j].erase(DefName);
132
133 Defs.erase(Defs.begin());
134 }
135 }
136}
Chris Lattner1e27fe12006-10-14 07:06:20 +0000137
138/// ComputeWCharWidth - Determine the width of the wchar_t type for the primary
139/// target, diagnosing whether this is non-portable across the secondary
140/// targets.
141void TargetInfo::ComputeWCharWidth(SourceLocation Loc) {
142 WCharWidth = PrimaryTarget->getWCharWidth();
143
144 // Check whether this is portable across the secondary targets if the T-U is
145 // portable so far.
146 for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i)
147 if (SecondaryTargets[i]->getWCharWidth() != WCharWidth)
148 return DiagnoseNonPortability(Loc, diag::port_wchar_t);
149}
150