|  | //===- subzero/src/IceGlobalInits.cpp - Global declarations ---------------===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Implements the notion of function declarations, global variable | 
|  | /// declarations, and the corresponding variable initializers in Subzero. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "IceGlobalInits.h" | 
|  |  | 
|  | #include "IceDefs.h" | 
|  | #include "IceGlobalContext.h" | 
|  | #include "IceTypes.h" | 
|  | #include "llvm/ADT/STLExtras.h" | 
|  | #include "llvm/IR/Function.h" | 
|  | #include "llvm/IR/Value.h" | 
|  |  | 
|  | namespace { | 
|  | char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; } | 
|  |  | 
|  | void dumpLinkage(Ice::Ostream &Stream, | 
|  | llvm::GlobalValue::LinkageTypes Linkage) { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | switch (Linkage) { | 
|  | case llvm::GlobalValue::ExternalLinkage: | 
|  | Stream << "external"; | 
|  | return; | 
|  | case llvm::GlobalValue::InternalLinkage: | 
|  | Stream << "internal"; | 
|  | return; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | std::string Buffer; | 
|  | llvm::raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Unknown linkage value: " << Linkage; | 
|  | llvm::report_fatal_error(StrBuf.str()); | 
|  | } | 
|  |  | 
|  | void dumpCallingConv(Ice::Ostream &, llvm::CallingConv::ID CallingConv) { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | if (CallingConv == llvm::CallingConv::C) | 
|  | return; | 
|  | std::string Buffer; | 
|  | llvm::raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Unknown calling convention: " << CallingConv; | 
|  | llvm::report_fatal_error(StrBuf.str()); | 
|  | } | 
|  |  | 
|  | } // end of anonymous namespace | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | const Intrinsics::FullIntrinsicInfo * | 
|  | FunctionDeclaration::getIntrinsicInfo(const GlobalContext *Ctx, | 
|  | bool *IsIntrinsic) const { | 
|  | *IsIntrinsic = false; | 
|  | if (!hasName()) | 
|  | return nullptr; | 
|  | bool BadIntrinsic; | 
|  | const Intrinsics::FullIntrinsicInfo *Info = | 
|  | Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic); | 
|  | *IsIntrinsic = Info || BadIntrinsic; | 
|  | return Info; | 
|  | } | 
|  |  | 
|  | bool FunctionDeclaration::validateRegularTypeSignature() const { | 
|  | for (SizeT i = 0; i < Signature.getNumArgs(); ++i) { | 
|  | if (!isCallParameterType(Signature.getArgType(i))) | 
|  | return false; | 
|  | } | 
|  | return isCallReturnType(Signature.getReturnType()); | 
|  | } | 
|  |  | 
|  | bool FunctionDeclaration::validateIntrinsicTypeSignature( | 
|  | const Intrinsics::FullIntrinsicInfo *Info) const { | 
|  | if (Signature.getNumArgs() != Info->getNumArgs()) | 
|  | return false; | 
|  | for (SizeT i = 0; i < Signature.getNumArgs(); ++i) { | 
|  | if (Signature.getArgType(i) != Info->getArgType(i)) | 
|  | return false; | 
|  | } | 
|  | return Signature.getReturnType() == Info->getReturnType(); | 
|  | } | 
|  |  | 
|  | std::string | 
|  | FunctionDeclaration::getTypeSignatureError(const GlobalContext *Ctx) { | 
|  | std::string Buffer; | 
|  | llvm::raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Invalid"; | 
|  | bool IsIntrinsic; | 
|  | const Intrinsics::FullIntrinsicInfo *Info = | 
|  | getIntrinsicInfo(Ctx, &IsIntrinsic); | 
|  | if (IsIntrinsic && Info == nullptr) { | 
|  | StrBuf << " intrinsic name: " << getName(); | 
|  | return StrBuf.str(); | 
|  | } | 
|  | StrBuf << " type signature for"; | 
|  | if (IsIntrinsic) | 
|  | StrBuf << " intrinsic"; | 
|  | StrBuf << " " << getName() << ": " << getSignature(); | 
|  | return StrBuf.str(); | 
|  | } | 
|  |  | 
|  | void FunctionDeclaration::dumpType(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | Stream << Signature; | 
|  | } | 
|  |  | 
|  | void FunctionDeclaration::dump(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | if (IsProto) | 
|  | Stream << "declare "; | 
|  | ::dumpLinkage(Stream, Linkage); | 
|  | ::dumpCallingConv(Stream, CallingConv); | 
|  | Stream << Signature.getReturnType() << " @" << Name << "("; | 
|  | bool IsFirst = true; | 
|  | for (Type ArgTy : Signature.getArgList()) { | 
|  | if (IsFirst) | 
|  | IsFirst = false; | 
|  | else | 
|  | Stream << ", "; | 
|  | Stream << ArgTy; | 
|  | } | 
|  | Stream << ")"; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::dumpType(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | if (Initializers.size() == 1) { | 
|  | Initializers.front()->dumpType(Stream); | 
|  | } else { | 
|  | Stream << "<{ "; | 
|  | bool IsFirst = true; | 
|  | for (const auto *Init : Initializers) { | 
|  | if (IsFirst) { | 
|  | IsFirst = false; | 
|  | } else { | 
|  | Stream << ", "; | 
|  | } | 
|  | Init->dumpType(Stream); | 
|  | } | 
|  | Stream << " }>"; | 
|  | } | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::dump(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | Stream << "@" << Name << " = "; | 
|  | ::dumpLinkage(Stream, Linkage); | 
|  | Stream << " " << (IsConstant ? "constant" : "global") << " "; | 
|  |  | 
|  | // Add initializer. | 
|  | if (Initializers.size() == 1) { | 
|  | Initializers.front()->dump(Stream); | 
|  | } else { | 
|  | dumpType(Stream); | 
|  | Stream << " <{ "; | 
|  | bool IsFirst = true; | 
|  | for (const auto *Init : Initializers) { | 
|  | if (IsFirst) { | 
|  | IsFirst = false; | 
|  | } else { | 
|  | Stream << ", "; | 
|  | } | 
|  | Init->dump(Stream); | 
|  | } | 
|  | Stream << " }>"; | 
|  | } | 
|  |  | 
|  | // Add alignment. | 
|  | if (Alignment > 0) | 
|  | Stream << ", align " << Alignment; | 
|  | Stream << "\n"; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::Initializer::dumpType(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | Stream << "[" << getNumBytes() << " x " << Ice::IceType_i8 << "]"; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | dumpType(Stream); | 
|  | Stream << " c\""; | 
|  | // Code taken from PrintEscapedString() in AsmWriter.cpp. Keep the strings in | 
|  | // the same format as the .ll file for practical diffing. | 
|  | for (SizeT i = 0; i < ContentsSize; ++i) { | 
|  | uint8_t C = Contents[i]; | 
|  | if (isprint(C) && C != '\\' && C != '"') | 
|  | Stream << C; | 
|  | else | 
|  | Stream << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); | 
|  | } | 
|  | Stream << "\""; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::ZeroInitializer::dump(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | dumpType(Stream); | 
|  | Stream << " zeroinitializer"; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::RelocInitializer::dumpType(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | Stream << Ice::IceType_i32; | 
|  | } | 
|  |  | 
|  | void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const { | 
|  | if (!Ice::BuildDefs::dump()) | 
|  | return; | 
|  | const RelocOffsetT Offset = getOffset(); | 
|  | if (Offset != 0) { | 
|  | dumpType(Stream); | 
|  | Stream << " add ("; | 
|  | } | 
|  | dumpType(Stream); | 
|  | Stream << " ptrtoint ("; | 
|  | Declaration->dumpType(Stream); | 
|  | Stream << "* @" << Declaration->getName() << " to "; | 
|  | dumpType(Stream); | 
|  | Stream << ")"; | 
|  | if (Offset != 0) { | 
|  | Stream << ", "; | 
|  | dumpType(Stream); | 
|  | Stream << " " << Offset << ")"; | 
|  | } | 
|  | } | 
|  |  | 
|  | } // end of namespace Ice |