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 { 26 char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; } 27 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 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 63 const Intrinsics::FullIntrinsicInfo * 64 FunctionDeclaration::getIntrinsicInfo(const GlobalContext *Ctx, 65 bool *IsIntrinsic) const { 66 *IsIntrinsic = false; 67 if (!hasName()) 68 return nullptr; 69 bool BadIntrinsic; 70 const Intrinsics::FullIntrinsicInfo *Info = 71 Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic); 72 *IsIntrinsic = Info || BadIntrinsic; 73 return Info; 74 } 75 76 bool FunctionDeclaration::validateRegularTypeSignature() const { 77 for (SizeT i = 0; i < Signature.getNumArgs(); ++i) { 78 if (!isCallParameterType(Signature.getArgType(i))) 79 return false; 80 } 81 return isCallReturnType(Signature.getReturnType()); 82 } 83 84 bool FunctionDeclaration::validateIntrinsicTypeSignature( 85 const Intrinsics::FullIntrinsicInfo *Info) const { 86 if (Signature.getNumArgs() != Info->getNumArgs()) 87 return false; 88 for (SizeT i = 0; i < Signature.getNumArgs(); ++i) { 89 if (Signature.getArgType(i) != Info->getArgType(i)) 90 return false; 91 } 92 return Signature.getReturnType() == Info->getReturnType(); 93 } 94 95 std::string 96 FunctionDeclaration::getTypeSignatureError(const GlobalContext *Ctx) { 97 std::string Buffer; 98 llvm::raw_string_ostream StrBuf(Buffer); 99 StrBuf << "Invalid"; 100 bool IsIntrinsic; 101 const Intrinsics::FullIntrinsicInfo *Info = 102 getIntrinsicInfo(Ctx, &IsIntrinsic); 103 if (IsIntrinsic && Info == nullptr) { 104 StrBuf << " intrinsic name: " << getName(); 105 return StrBuf.str(); 106 } 107 StrBuf << " type signature for"; 108 if (IsIntrinsic) 109 StrBuf << " intrinsic"; 110 StrBuf << " " << getName() << ": " << getSignature(); 111 return StrBuf.str(); 112 } 113 114 void FunctionDeclaration::dumpType(Ostream &Stream) const { 115 if (!Ice::BuildDefs::dump()) 116 return; 117 Stream << Signature; 118 } 119 120 void FunctionDeclaration::dump(Ostream &Stream) const { 121 if (!Ice::BuildDefs::dump()) 122 return; 123 if (IsProto) 124 Stream << "declare "; 125 ::dumpLinkage(Stream, Linkage); 126 ::dumpCallingConv(Stream, CallingConv); 127 Stream << Signature.getReturnType() << " @" << Name << "("; 128 bool IsFirst = true; 129 for (Type ArgTy : Signature.getArgList()) { 130 if (IsFirst) 131 IsFirst = false; 132 else 133 Stream << ", "; 134 Stream << ArgTy; 135 } 136 Stream << ")"; 137 } 138 139 void VariableDeclaration::dumpType(Ostream &Stream) const { 140 if (!Ice::BuildDefs::dump()) 141 return; 142 if (Initializers.size() == 1) { 143 Initializers.front()->dumpType(Stream); 144 } else { 145 Stream << "<{ "; 146 bool IsFirst = true; 147 for (const auto *Init : Initializers) { 148 if (IsFirst) { 149 IsFirst = false; 150 } else { 151 Stream << ", "; 152 } 153 Init->dumpType(Stream); 154 } 155 Stream << " }>"; 156 } 157 } 158 159 void VariableDeclaration::dump(Ostream &Stream) const { 160 if (!Ice::BuildDefs::dump()) 161 return; 162 Stream << "@" << Name << " = "; 163 ::dumpLinkage(Stream, Linkage); 164 Stream << " " << (IsConstant ? "constant" : "global") << " "; 165 166 // Add initializer. 167 if (Initializers.size() == 1) { 168 Initializers.front()->dump(Stream); 169 } else { 170 dumpType(Stream); 171 Stream << " <{ "; 172 bool IsFirst = true; 173 for (const auto *Init : Initializers) { 174 if (IsFirst) { 175 IsFirst = false; 176 } else { 177 Stream << ", "; 178 } 179 Init->dump(Stream); 180 } 181 Stream << " }>"; 182 } 183 184 // Add alignment. 185 if (Alignment > 0) 186 Stream << ", align " << Alignment; 187 Stream << "\n"; 188 } 189 190 void VariableDeclaration::Initializer::dumpType(Ostream &Stream) const { 191 if (!Ice::BuildDefs::dump()) 192 return; 193 Stream << "[" << getNumBytes() << " x " << Ice::IceType_i8 << "]"; 194 } 195 196 void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const { 197 if (!Ice::BuildDefs::dump()) 198 return; 199 dumpType(Stream); 200 Stream << " c\""; 201 // Code taken from PrintEscapedString() in AsmWriter.cpp. Keep the strings in 202 // the same format as the .ll file for practical diffing. 203 for (SizeT i = 0; i < ContentsSize; ++i) { 204 uint8_t C = Contents[i]; 205 if (isprint(C) && C != '\\' && C != '"') 206 Stream << C; 207 else 208 Stream << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); 209 } 210 Stream << "\""; 211 } 212 213 void VariableDeclaration::ZeroInitializer::dump(Ostream &Stream) const { 214 if (!Ice::BuildDefs::dump()) 215 return; 216 dumpType(Stream); 217 Stream << " zeroinitializer"; 218 } 219 220 void VariableDeclaration::RelocInitializer::dumpType(Ostream &Stream) const { 221 if (!Ice::BuildDefs::dump()) 222 return; 223 Stream << Ice::IceType_i32; 224 } 225 226 void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const { 227 if (!Ice::BuildDefs::dump()) 228 return; 229 const RelocOffsetT Offset = getOffset(); 230 if (Offset != 0) { 231 dumpType(Stream); 232 Stream << " add ("; 233 } 234 dumpType(Stream); 235 Stream << " ptrtoint ("; 236 Declaration->dumpType(Stream); 237 Stream << "* @" << Declaration->getName() << " to "; 238 dumpType(Stream); 239 Stream << ")"; 240 if (Offset != 0) { 241 Stream << ", "; 242 dumpType(Stream); 243 Stream << " " << Offset << ")"; 244 } 245 } 246 247 } // end of namespace Ice 248