Home | History | Annotate | Download | only in src
      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