1 //===- subzero/src/IceGlobalInits.cpp - Global declarations ---------------===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Implements the notion of function declarations, global variable
12 /// declarations, and the corresponding variable initializers in Subzero.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #include "IceGlobalInits.h"
17
18 #include "IceDefs.h"
19 #include "IceGlobalContext.h"
20 #include "IceTypes.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/Value.h"
24
25 namespace {
hexdigit(unsigned X)26 char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; }
27
dumpLinkage(Ice::Ostream & Stream,llvm::GlobalValue::LinkageTypes Linkage)28 void dumpLinkage(Ice::Ostream &Stream,
29 llvm::GlobalValue::LinkageTypes Linkage) {
30 if (!Ice::BuildDefs::dump())
31 return;
32 switch (Linkage) {
33 case llvm::GlobalValue::ExternalLinkage:
34 Stream << "external";
35 return;
36 case llvm::GlobalValue::InternalLinkage:
37 Stream << "internal";
38 return;
39 default:
40 break;
41 }
42 std::string Buffer;
43 llvm::raw_string_ostream StrBuf(Buffer);
44 StrBuf << "Unknown linkage value: " << Linkage;
45 llvm::report_fatal_error(StrBuf.str());
46 }
47
dumpCallingConv(Ice::Ostream &,llvm::CallingConv::ID CallingConv)48 void dumpCallingConv(Ice::Ostream &, llvm::CallingConv::ID CallingConv) {
49 if (!Ice::BuildDefs::dump())
50 return;
51 if (CallingConv == llvm::CallingConv::C)
52 return;
53 std::string Buffer;
54 llvm::raw_string_ostream StrBuf(Buffer);
55 StrBuf << "Unknown calling convention: " << CallingConv;
56 llvm::report_fatal_error(StrBuf.str());
57 }
58
59 } // end of anonymous namespace
60
61 namespace Ice {
62
validateTypeSignature() const63 bool FunctionDeclaration::validateTypeSignature() const {
64 for (SizeT i = 0; i < Signature.getNumArgs(); ++i) {
65 if (!isCallParameterType(Signature.getArgType(i)))
66 return false;
67 }
68 return isCallReturnType(Signature.getReturnType());
69 }
70
71 std::string
getTypeSignatureError(const GlobalContext * Ctx)72 FunctionDeclaration::getTypeSignatureError(const GlobalContext *Ctx) {
73 std::string Buffer;
74 llvm::raw_string_ostream StrBuf(Buffer);
75 StrBuf << "Invalid type signature for";
76 StrBuf << " " << getName() << ": " << getSignature();
77 return StrBuf.str();
78 }
79
dumpType(Ostream & Stream) const80 void FunctionDeclaration::dumpType(Ostream &Stream) const {
81 if (!Ice::BuildDefs::dump())
82 return;
83 Stream << Signature;
84 }
85
dump(Ostream & Stream) const86 void FunctionDeclaration::dump(Ostream &Stream) const {
87 if (!Ice::BuildDefs::dump())
88 return;
89 if (IsProto)
90 Stream << "declare ";
91 ::dumpLinkage(Stream, Linkage);
92 ::dumpCallingConv(Stream, CallingConv);
93 Stream << Signature.getReturnType() << " @" << Name << "(";
94 bool IsFirst = true;
95 for (Type ArgTy : Signature.getArgList()) {
96 if (IsFirst)
97 IsFirst = false;
98 else
99 Stream << ", ";
100 Stream << ArgTy;
101 }
102 Stream << ")";
103 }
104
dumpType(Ostream & Stream) const105 void VariableDeclaration::dumpType(Ostream &Stream) const {
106 if (!Ice::BuildDefs::dump())
107 return;
108 if (Initializers.size() == 1) {
109 Initializers.front()->dumpType(Stream);
110 } else {
111 Stream << "<{ ";
112 bool IsFirst = true;
113 for (const auto *Init : Initializers) {
114 if (IsFirst) {
115 IsFirst = false;
116 } else {
117 Stream << ", ";
118 }
119 Init->dumpType(Stream);
120 }
121 Stream << " }>";
122 }
123 }
124
dump(Ostream & Stream) const125 void VariableDeclaration::dump(Ostream &Stream) const {
126 if (!Ice::BuildDefs::dump())
127 return;
128 Stream << "@" << Name << " = ";
129 ::dumpLinkage(Stream, Linkage);
130 Stream << " " << (IsConstant ? "constant" : "global") << " ";
131
132 // Add initializer.
133 if (Initializers.size() == 1) {
134 Initializers.front()->dump(Stream);
135 } else {
136 dumpType(Stream);
137 Stream << " <{ ";
138 bool IsFirst = true;
139 for (const auto *Init : Initializers) {
140 if (IsFirst) {
141 IsFirst = false;
142 } else {
143 Stream << ", ";
144 }
145 Init->dump(Stream);
146 }
147 Stream << " }>";
148 }
149
150 // Add alignment.
151 if (Alignment > 0)
152 Stream << ", align " << Alignment;
153 Stream << "\n";
154 }
155
dumpType(Ostream & Stream) const156 void VariableDeclaration::Initializer::dumpType(Ostream &Stream) const {
157 if (!Ice::BuildDefs::dump())
158 return;
159 Stream << "[" << getNumBytes() << " x " << Ice::IceType_i8 << "]";
160 }
161
dump(Ostream & Stream) const162 void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const {
163 if (!Ice::BuildDefs::dump())
164 return;
165 dumpType(Stream);
166 Stream << " c\"";
167 // Code taken from PrintEscapedString() in AsmWriter.cpp. Keep the strings in
168 // the same format as the .ll file for practical diffing.
169 for (SizeT i = 0; i < ContentsSize; ++i) {
170 uint8_t C = Contents[i];
171 if (isprint(C) && C != '\\' && C != '"')
172 Stream << C;
173 else
174 Stream << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
175 }
176 Stream << "\"";
177 }
178
dump(Ostream & Stream) const179 void VariableDeclaration::ZeroInitializer::dump(Ostream &Stream) const {
180 if (!Ice::BuildDefs::dump())
181 return;
182 dumpType(Stream);
183 Stream << " zeroinitializer";
184 }
185
dumpType(Ostream & Stream) const186 void VariableDeclaration::RelocInitializer::dumpType(Ostream &Stream) const {
187 if (!Ice::BuildDefs::dump())
188 return;
189 Stream << Ice::IceType_i32;
190 }
191
dump(Ostream & Stream) const192 void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const {
193 if (!Ice::BuildDefs::dump())
194 return;
195 const RelocOffsetT Offset = getOffset();
196 if (Offset != 0) {
197 dumpType(Stream);
198 Stream << " add (";
199 }
200 dumpType(Stream);
201 Stream << " ptrtoint (";
202 Declaration->dumpType(Stream);
203 Stream << "* @" << Declaration->getName() << " to ";
204 dumpType(Stream);
205 Stream << ")";
206 if (Offset != 0) {
207 Stream << ", ";
208 dumpType(Stream);
209 Stream << " " << Offset << ")";
210 }
211 }
212
213 } // end of namespace Ice
214