void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
                                                  raw_ostream &OS) {
  std::vector<Record *> Tags = Records.getAllDerivedDefinitions("NCR");
  std::vector<StringMatcher::StringPair> NameToUTF8;
  SmallString<32> CLiteral;
  for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end();
       I != E; ++I) {
    Record &Tag = **I;
    std::string Spelling = Tag.getValueAsString("Spelling");
    uint64_t CodePoint = Tag.getValueAsInt("CodePoint");
    CLiteral.clear();
    CLiteral.append("return ");
    if (!translateCodePointToUTF8(CodePoint, CLiteral)) {
      SrcMgr.PrintMessage(Tag.getLoc().front(),
                          SourceMgr::DK_Error,
                          Twine("invalid code point"));
      continue;
    }
    CLiteral.append(";");

    StringMatcher::StringPair Match(Spelling, CLiteral.str());
    NameToUTF8.push_back(Match);
  }

  emitSourceFileHeader("HTML named character reference to UTF-8 "
                       "translation", OS);

  OS << "StringRef translateHTMLNamedCharacterReferenceToUTF8(\n"
        "                                             StringRef Name) {\n";
  StringMatcher("Name", NameToUTF8, OS).Emit();
  OS << "  return StringRef();\n"
     << "}\n\n";
}
Ejemplo n.º 2
0
void SourceCoverageView::renderRegionMarkers(
    raw_ostream &OS, ArrayRef<const coverage::CoverageSegment *> Segments) {
  SmallString<32> Buffer;
  raw_svector_ostream BufferOS(Buffer);

  unsigned PrevColumn = 1;
  for (const auto *S : Segments) {
    if (!S->IsRegionEntry)
      continue;
    // Skip to the new region
    if (S->Col > PrevColumn)
      OS.indent(S->Col - PrevColumn);
    PrevColumn = S->Col + 1;
    BufferOS << S->Count;
    StringRef Str = BufferOS.str();
    // Trim the execution count
    Str = Str.substr(0, std::min(Str.size(), (size_t)7));
    PrevColumn += Str.size();
    OS << '^' << Str;
    Buffer.clear();
  }
  OS << "\n";

  if (Options.Debug)
    for (const auto *S : Segments)
      errs() << "Marker at " << S->Line << ":" << S->Col << " = " << S->Count
             << (S->IsRegionEntry ? "\n" : " (pop)\n");
}
Ejemplo n.º 3
0
void SourceCoverageView::renderRegionMarkers(raw_ostream &OS,
                                             ArrayRef<RegionMarker> Regions) {
  SmallString<32> Buffer;
  raw_svector_ostream BufferOS(Buffer);

  unsigned PrevColumn = 1;
  for (const auto &Region : Regions) {
    // Skip to the new region
    if (Region.Column > PrevColumn)
      OS.indent(Region.Column - PrevColumn);
    PrevColumn = Region.Column + 1;
    BufferOS << Region.ExecutionCount;
    StringRef Str = BufferOS.str();
    // Trim the execution count
    Str = Str.substr(0, std::min(Str.size(), (size_t)7));
    PrevColumn += Str.size();
    OS << '^' << Str;
    Buffer.clear();
  }
  OS << "\n";

  if (Options.Debug) {
    for (const auto &Region : Regions) {
      errs() << "Marker at " << Region.Line << ":" << Region.Column << " = "
             << Region.ExecutionCount << "\n";
    }
  }
}
Ejemplo n.º 4
0
void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
  // LocalSym record, see SymbolRecord.h for more info.
  MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(),
           *LocalEnd = MMI->getContext().createTempSymbol();
  OS.AddComment("Record length");
  OS.emitAbsoluteSymbolDiff(LocalEnd, LocalBegin, 2);
  OS.EmitLabel(LocalBegin);

  OS.AddComment("Record kind: S_LOCAL");
  OS.EmitIntValue(unsigned(SymbolRecordKind::S_LOCAL), 2);

  uint16_t Flags = 0;
  if (Var.DIVar->isParameter())
    Flags |= LocalSym::IsParameter;
  if (Var.DefRanges.empty())
    Flags |= LocalSym::IsOptimizedOut;

  OS.AddComment("TypeIndex");
  OS.EmitIntValue(TypeIndex::Int32().getIndex(), 4);
  OS.AddComment("Flags");
  OS.EmitIntValue(Flags, 2);
  // Truncate the name so we won't overflow the record length field.
  emitNullTerminatedSymbolName(OS, Var.DIVar->getName());
  OS.EmitLabel(LocalEnd);

  // Calculate the on disk prefix of the appropriate def range record. The
  // records and on disk formats are described in SymbolRecords.h. BytePrefix
  // should be big enough to hold all forms without memory allocation.
  SmallString<20> BytePrefix;
  for (const LocalVarDefRange &DefRange : Var.DefRanges) {
    BytePrefix.clear();
    // FIXME: Handle bitpieces.
    if (DefRange.StructOffset != 0)
      continue;

    if (DefRange.InMemory) {
      DefRangeRegisterRelSym Sym{};
      ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
      Sym.BaseRegister = DefRange.CVRegister;
      Sym.Flags = 0; // Unclear what matters here.
      Sym.BasePointerOffset = DefRange.DataOffset;
      BytePrefix +=
          StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
    } else {
      assert(DefRange.DataOffset == 0 && "unexpected offset into register");
      DefRangeRegisterSym Sym{};
      ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER);
      Sym.Register = DefRange.CVRegister;
      Sym.MayHaveNoName = 0; // Unclear what matters here.
      BytePrefix +=
          StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
    }
    OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
  }
}
Ejemplo n.º 5
0
void InitHeaderSearch::AddPath(const Twine &Path,
                               IncludeDirGroup Group, bool isCXXAware,
                               bool isUserSupplied, bool isFramework,
                               bool IgnoreSysRoot) {
  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
  FileManager &FM = Headers.getFileMgr();

  // Compute the actual path, taking into consideration -isysroot.
  SmallString<256> MappedPathStorage;
  StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);

  // Handle isysroot.
  if ((Group == System || Group == CXXSystem) && !IgnoreSysRoot &&
#if defined(_WIN32)
      !MappedPathStr.empty() &&
      llvm::sys::path::is_separator(MappedPathStr[0]) &&
#else
      llvm::sys::path::is_absolute(MappedPathStr) &&
#endif
      IsNotEmptyOrRoot) {
    MappedPathStorage.clear();
    MappedPathStr =
      (IncludeSysroot + Path).toStringRef(MappedPathStorage);
  }

  // Compute the DirectoryLookup type.
  SrcMgr::CharacteristicKind Type;
  if (Group == Quoted || Group == Angled || Group == IndexHeaderMap)
    Type = SrcMgr::C_User;
  else if (isCXXAware)
    Type = SrcMgr::C_System;
  else
    Type = SrcMgr::C_ExternCSystem;


  // If the directory exists, add it.
  if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
    IncludePath.push_back(std::make_pair(Group, DirectoryLookup(DE, Type,
                          isUserSupplied, isFramework)));
    return;
  }

  // Check to see if this is an apple-style headermap (which are not allowed to
  // be frameworks).
  if (!isFramework) {
    if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
        // It is a headermap, add it to the search path.
        IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type,
                              isUserSupplied, Group == IndexHeaderMap)));
        return;
      }
    }
  }

  if (Verbose)
    llvm::errs() << "ignoring nonexistent directory \""
                 << MappedPathStr << "\"\n";
}
Ejemplo n.º 6
0
ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
  bool foundFile = false;
  StringRef pathref;
  SmallString<128> path;
  for (StringRef dir : _inputSearchPaths) {
    // Search for dynamic library
    if (!_isStaticExecutable) {
      path.clear();
      if (dir.startswith("=/")) {
        path.assign(_sysrootPath);
        path.append(dir.substr(1));
      } else {
        path.assign(dir);
      }
      llvm::sys::path::append(path, Twine("lib") + libName + ".so");
      pathref = path.str();
      if (llvm::sys::fs::exists(pathref)) {
        foundFile = true;
      }
    }
    // Search for static libraries too
    if (!foundFile) {
      path.clear();
      if (dir.startswith("=/")) {
        path.assign(_sysrootPath);
        path.append(dir.substr(1));
      } else {
        path.assign(dir);
      }
      llvm::sys::path::append(path, Twine("lib") + libName + ".a");
      pathref = path.str();
      if (llvm::sys::fs::exists(pathref)) {
        foundFile = true;
      }
    }
    if (foundFile)
      return StringRef(*new (_allocator) std::string(pathref));
  }
  if (!llvm::sys::fs::exists(libName))
    return llvm::make_error_code(llvm::errc::no_such_file_or_directory);

  return libName;
}
Ejemplo n.º 7
0
std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
  SmallString<128> StringStorage;
  if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
    StringRef KeyStr = SN->getValue(StringStorage);
    if (!StringStorage.empty()) {
      // Copy string to permanent storage
      KeyStr = StringStorage.str().copy(StringAllocator);
    }
    return llvm::make_unique<ScalarHNode>(N, KeyStr);
  } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
    StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
    return llvm::make_unique<ScalarHNode>(N, ValueCopy);
  } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
    auto SQHNode = llvm::make_unique<SequenceHNode>(N);
    for (Node &SN : *SQ) {
      auto Entry = createHNodes(&SN);
      if (EC)
        break;
      SQHNode->Entries.push_back(std::move(Entry));
    }
    return std::move(SQHNode);
  } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
    auto mapHNode = llvm::make_unique<MapHNode>(N);
    for (KeyValueNode &KVN : *Map) {
      Node *KeyNode = KVN.getKey();
      ScalarNode *Key = dyn_cast<ScalarNode>(KeyNode);
      Node *Value = KVN.getValue();
      if (!Key || !Value) {
        if (!Key)
          setError(KeyNode, "Map key must be a scalar");
        if (!Value)
          setError(KeyNode, "Map value must not be empty");
        break;
      }
      StringStorage.clear();
      StringRef KeyStr = Key->getValue(StringStorage);
      if (!StringStorage.empty()) {
        // Copy string to permanent storage
        KeyStr = StringStorage.str().copy(StringAllocator);
      }
      auto ValueHNode = createHNodes(Value);
      if (EC)
        break;
      mapHNode->Mapping[KeyStr] = std::move(ValueHNode);
    }
    return std::move(mapHNode);
  } else if (isa<NullNode>(N)) {
    return llvm::make_unique<EmptyHNode>(N);
  } else {
    setError(N, "unknown node kind");
    return nullptr;
  }
}
Ejemplo n.º 8
0
void LTOCodeGenerator::applyScopeRestrictions() {
  if (ScopeRestrictionsDone)
    return;

  // Declare a callback for the internalize pass that will ask for every
  // candidate GlobalValue if it can be internalized or not.
  SmallString<64> MangledName;
  auto mustPreserveGV = [&](const GlobalValue &GV) -> bool {
    // Unnamed globals can't be mangled, but they can't be preserved either.
    if (!GV.hasName())
      return false;

    // Need to mangle the GV as the "MustPreserveSymbols" StringSet is filled
    // with the linker supplied name, which on Darwin includes a leading
    // underscore.
    MangledName.clear();
    MangledName.reserve(GV.getName().size() + 1);
    Mangler::getNameWithPrefix(MangledName, GV.getName(),
                               MergedModule->getDataLayout());
    return MustPreserveSymbols.count(MangledName);
  };

  // Preserve linkonce value on linker request
  preserveDiscardableGVs(*MergedModule, mustPreserveGV);

  if (!ShouldInternalize)
    return;

  if (ShouldRestoreGlobalsLinkage) {
    // Record the linkage type of non-local symbols so they can be restored
    // prior
    // to module splitting.
    auto RecordLinkage = [&](const GlobalValue &GV) {
      if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
          GV.hasName())
        ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage()));
    };
    for (auto &GV : *MergedModule)
      RecordLinkage(GV);
    for (auto &GV : MergedModule->globals())
      RecordLinkage(GV);
    for (auto &GV : MergedModule->aliases())
      RecordLinkage(GV);
  }

  // Update the llvm.compiler_used globals to force preserving libcalls and
  // symbols referenced from asm
  updateCompilerUsed(*MergedModule, *TargetMach, AsmUndefinedRefs);

  internalizeModule(*MergedModule, mustPreserveGV);

  ScopeRestrictionsDone = true;
}
Ejemplo n.º 9
0
Input::HNode *Input::createHNodes(Node *N) {
  SmallString<128> StringStorage;
  if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
    StringRef KeyStr = SN->getValue(StringStorage);
    if (!StringStorage.empty()) {
      // Copy string to permanent storage
      unsigned Len = StringStorage.size();
      char *Buf = StringAllocator.Allocate<char>(Len);
      memcpy(Buf, &StringStorage[0], Len);
      KeyStr = StringRef(Buf, Len);
    }
    return new ScalarHNode(N, KeyStr);
  } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
    SequenceHNode *SQHNode = new SequenceHNode(N);
    for (Node &SN : *SQ) {
      HNode *Entry = this->createHNodes(&SN);
      if (EC)
        break;
      SQHNode->Entries.push_back(Entry);
    }
    return SQHNode;
  } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
    MapHNode *mapHNode = new MapHNode(N);
    for (KeyValueNode &KVN : *Map) {
      Node *KeyNode = KVN.getKey();
      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode);
      if (!KeyScalar) {
        setError(KeyNode, "Map key must be a scalar");
        break;
      }
      StringStorage.clear();
      StringRef KeyStr = KeyScalar->getValue(StringStorage);
      if (!StringStorage.empty()) {
        // Copy string to permanent storage
        unsigned Len = StringStorage.size();
        char *Buf = StringAllocator.Allocate<char>(Len);
        memcpy(Buf, &StringStorage[0], Len);
        KeyStr = StringRef(Buf, Len);
      }
      HNode *ValueHNode = this->createHNodes(KVN.getValue());
      if (EC)
        break;
      mapHNode->Mapping[KeyStr] = ValueHNode;
    }
    return mapHNode;
  } else if (isa<NullNode>(N)) {
    return new EmptyHNode(N);
  } else {
    setError(N, "unknown node kind");
    return nullptr;
  }
}
Ejemplo n.º 10
0
Input::HNode *Input::createHNodes(Node *N) {
  SmallString<128> StringStorage;
  if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
    StringRef KeyStr = SN->getValue(StringStorage);
    if (!StringStorage.empty()) {
      // Copy string to permanent storage
      unsigned Len = StringStorage.size();
      char *Buf = StringAllocator.Allocate<char>(Len);
      memcpy(Buf, &StringStorage[0], Len);
      KeyStr = StringRef(Buf, Len);
    }
    return new ScalarHNode(N, KeyStr);
  } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
    SequenceHNode *SQHNode = new SequenceHNode(N);
    for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End;
         ++i) {
      HNode *Entry = this->createHNodes(i);
      if (EC)
        break;
      SQHNode->Entries.push_back(Entry);
    }
    return SQHNode;
  } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
    MapHNode *mapHNode = new MapHNode(N);
    for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End;
         ++i) {
      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(i->getKey());
      StringStorage.clear();
      StringRef KeyStr = KeyScalar->getValue(StringStorage);
      if (!StringStorage.empty()) {
        // Copy string to permanent storage
        unsigned Len = StringStorage.size();
        char *Buf = StringAllocator.Allocate<char>(Len);
        memcpy(Buf, &StringStorage[0], Len);
        KeyStr = StringRef(Buf, Len);
      }
      HNode *ValueHNode = this->createHNodes(i->getValue());
      if (EC)
        break;
      mapHNode->Mapping[KeyStr] = ValueHNode;
    }
    return mapHNode;
  } else if (isa<NullNode>(N)) {
    return new EmptyHNode(N);
  } else {
    setError(N, "unknown node kind");
    return NULL;
  }
}
Ejemplo n.º 11
0
/// \brief Compute the relative path that names the given file relative to
/// the given directory.
static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
                                const FileEntry *File,
                                SmallString<128> &Result) {
  Result.clear();

  StringRef FilePath = File->getDir()->getName();
  StringRef Path = FilePath;
  while (!Path.empty()) {
    if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) {
      if (CurDir == Dir) {
        Result = FilePath.substr(Path.size());
        llvm::sys::path::append(Result, 
                                llvm::sys::path::filename(File->getName()));
        return;
      }
    }
    
    Path = llvm::sys::path::parent_path(Path);
  }
  
  Result = File->getName();
}
Ejemplo n.º 12
0
/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest
/// module from a type definition in the source module.
void TypeMapTy::linkDefinedTypeBodies() {
  SmallVector<Type*, 16> Elements;
  SmallString<16> TmpName;
  
  // Note that processing entries in this loop (calling 'get') can add new
  // entries to the SrcDefinitionsToResolve vector.
  while (!SrcDefinitionsToResolve.empty()) {
    StructType *SrcSTy = SrcDefinitionsToResolve.pop_back_val();
    StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]);
    
    // TypeMap is a many-to-one mapping, if there were multiple types that
    // provide a body for DstSTy then previous iterations of this loop may have
    // already handled it.  Just ignore this case.
    if (!DstSTy->isOpaque()) continue;
    assert(!SrcSTy->isOpaque() && "Not resolving a definition?");
    
    // Map the body of the source type over to a new body for the dest type.
    Elements.resize(SrcSTy->getNumElements());
    for (unsigned i = 0, e = Elements.size(); i != e; ++i)
      Elements[i] = getImpl(SrcSTy->getElementType(i));
    
    DstSTy->setBody(Elements, SrcSTy->isPacked());
    
    // If DstSTy has no name or has a longer name than STy, then viciously steal
    // STy's name.
    if (!SrcSTy->hasName()) continue;
    StringRef SrcName = SrcSTy->getName();
    
    if (!DstSTy->hasName() || DstSTy->getName().size() > SrcName.size()) {
      TmpName.insert(TmpName.end(), SrcName.begin(), SrcName.end());
      SrcSTy->setName("");
      DstSTy->setName(TmpName.str());
      TmpName.clear();
    }
  }
  
  DstResolvedOpaqueTypes.clear();
}
// Build the unmodified AsmString used by the IR.  Also build the individual
// asm instruction(s) and place them in the AsmStrings vector; these are fed
// to the AsmParser.
static std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks,
                                    std::vector<std::string> &AsmStrings,
                     std::vector<std::pair<unsigned,unsigned> > &AsmTokRanges) {
  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");

  SmallString<512> Res;
  SmallString<512> Asm;
  unsigned startTok = 0;
  for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
    bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
      AsmToks[i].is(tok::kw_asm);

    if (isNewAsm) {
      if (i) {
        AsmStrings.push_back(Asm.str());
        AsmTokRanges.push_back(std::make_pair(startTok, i-1));
        startTok = i;
        Res += Asm;
        Asm.clear();
        Res += '\n';
      }
      if (AsmToks[i].is(tok::kw_asm)) {
        i++; // Skip __asm
        assert (i != e && "Expected another token");
      }
    }

    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
      Asm += ' ';

    Asm += getSpelling(SemaRef, AsmToks[i]);
  }
  AsmStrings.push_back(Asm.str());
  AsmTokRanges.push_back(std::make_pair(startTok, AsmToks.size()-1));
  Res += Asm;
  return Res.str();
}
Ejemplo n.º 14
0
void
irgen::emitTypeLayoutVerifier(IRGenFunction &IGF,
                              ArrayRef<CanType> formalTypes) {
  llvm::Type *verifierArgTys[] = {
    IGF.IGM.TypeMetadataPtrTy,
    IGF.IGM.Int8PtrTy,
    IGF.IGM.Int8PtrTy,
    IGF.IGM.SizeTy,
    IGF.IGM.Int8PtrTy,
  };
  auto verifierFnTy = llvm::FunctionType::get(IGF.IGM.VoidTy,
                                              verifierArgTys,
                                              /*var arg*/ false);
  auto verifierFn = IGF.IGM.Module.getOrInsertFunction(
      "_swift_debug_verifyTypeLayoutAttribute", verifierFnTy);
  if (IGF.IGM.useDllStorage()) 
    if (auto *F = dyn_cast<llvm::Function>(verifierFn))
      F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

  struct VerifierArgumentBuffers {
    Address runtimeBuf, staticBuf;
  };
  llvm::DenseMap<llvm::Type *, VerifierArgumentBuffers>
    verifierArgBufs;
  
  auto getSizeConstant = [&](Size sz) -> llvm::Constant * {
    return llvm::ConstantInt::get(IGF.IGM.SizeTy, sz.getValue());
  };
  auto getAlignmentMaskConstant = [&](Alignment a) -> llvm::Constant * {
    return llvm::ConstantInt::get(IGF.IGM.SizeTy, a.getValue() - 1);
  };
  auto getBoolConstant = [&](bool b) -> llvm::Constant * {
    return llvm::ConstantInt::get(IGF.IGM.Int1Ty, b);
  };

  SmallString<20> numberBuf;

  for (auto formalType : formalTypes) {
    // Runtime type metadata always represents the maximal abstraction level of
    // the type.
    auto anyTy = IGF.IGM.Context.TheAnyType;
    auto openedAnyTy = ArchetypeType::getOpened(anyTy);
    auto maxAbstraction = AbstractionPattern(openedAnyTy);
    auto &ti = IGF.getTypeInfoForUnlowered(maxAbstraction, formalType);
    
    // If there's no fixed type info, we rely on the runtime anyway, so there's
    // nothing to verify.
    // TODO: There are some traits of partially-fixed layouts we could check too.
    auto *fixedTI = dyn_cast<FixedTypeInfo>(&ti);
    if (!fixedTI)
      return;
    
    auto metadata = IGF.emitTypeMetadataRef(formalType);
    
    auto verify = [&](llvm::Value *runtimeVal,
                      llvm::Value *staticVal,
                      const llvm::Twine &description) {
      assert(runtimeVal->getType() == staticVal->getType());
      // Get or create buffers for the arguments.
      VerifierArgumentBuffers bufs;
      auto foundBufs = verifierArgBufs.find(runtimeVal->getType());
      if (foundBufs != verifierArgBufs.end()) {
        bufs = foundBufs->second;
      } else {
        Address runtimeBuf = IGF.createAlloca(runtimeVal->getType(),
                                              IGF.IGM.getPointerAlignment(),
                                              "runtime");
        Address staticBuf = IGF.createAlloca(staticVal->getType(),
                                             IGF.IGM.getPointerAlignment(),
                                             "static");
        bufs = {runtimeBuf, staticBuf};
        verifierArgBufs[runtimeVal->getType()] = bufs;
      }
      
      IGF.Builder.CreateStore(runtimeVal, bufs.runtimeBuf);
      IGF.Builder.CreateStore(staticVal, bufs.staticBuf);
      
      auto runtimePtr = IGF.Builder.CreateBitCast(bufs.runtimeBuf.getAddress(),
                                                  IGF.IGM.Int8PtrTy);
      auto staticPtr = IGF.Builder.CreateBitCast(bufs.staticBuf.getAddress(),
                                                 IGF.IGM.Int8PtrTy);
      auto count = llvm::ConstantInt::get(IGF.IGM.SizeTy,
                    IGF.IGM.DataLayout.getTypeStoreSize(runtimeVal->getType()));
      auto msg
        = IGF.IGM.getAddrOfGlobalString(description.str());
      
      IGF.Builder.CreateCall(
          verifierFn, {metadata, runtimePtr, staticPtr, count, msg});
    };

    // Check that the fixed layout matches the runtime layout.
    SILType layoutType = SILType::getPrimitiveObjectType(formalType);
    verify(emitLoadOfSize(IGF, layoutType),
           getSizeConstant(fixedTI->getFixedSize()),
           "size");
    verify(emitLoadOfAlignmentMask(IGF, layoutType),
           getAlignmentMaskConstant(fixedTI->getFixedAlignment()),
           "alignment mask");
    verify(emitLoadOfStride(IGF, layoutType),
           getSizeConstant(fixedTI->getFixedStride()),
           "stride");
    verify(emitLoadOfIsInline(IGF, layoutType),
           getBoolConstant(fixedTI->getFixedPacking(IGF.IGM)
                             == FixedPacking::OffsetZero),
           "is-inline bit");
    verify(emitLoadOfIsPOD(IGF, layoutType),
           getBoolConstant(fixedTI->isPOD(ResilienceExpansion::Maximal)),
           "is-POD bit");
    verify(emitLoadOfIsBitwiseTakable(IGF, layoutType),
           getBoolConstant(fixedTI->isBitwiseTakable(ResilienceExpansion::Maximal)),
           "is-bitwise-takable bit");
    unsigned xiCount = fixedTI->getFixedExtraInhabitantCount(IGF.IGM);
    verify(emitLoadOfHasExtraInhabitants(IGF, layoutType),
           getBoolConstant(xiCount != 0),
           "has-extra-inhabitants bit");

    // Check extra inhabitants.
    if (xiCount > 0) {
      verify(emitLoadOfExtraInhabitantCount(IGF, layoutType),
             getSizeConstant(Size(xiCount)),
             "extra inhabitant count");
      
      // Verify that the extra inhabitant representations are consistent.
      
      // TODO: Update for EnumPayload implementation changes.
#if 0
      auto xiBuf = IGF.createAlloca(fixedTI->getStorageType(),
                                    fixedTI->getFixedAlignment(),
                                    "extra-inhabitant");
      auto xiOpaque = IGF.Builder.CreateBitCast(xiBuf, IGF.IGM.OpaquePtrTy);
      
      // TODO: Randomize the set of extra inhabitants we check.
      unsigned bits = fixedTI->getFixedSize().getValueInBits();
      for (unsigned i = 0, e = std::min(xiCount, 1024u);
           i < e; ++i) {
        // Initialize the buffer with junk, to help ensure we're insensitive to
        // insignificant bits.
        // TODO: Randomize the filler.
        IGF.Builder.CreateMemSet(xiBuf.getAddress(),
                                 llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0x5A),
                                 fixedTI->getFixedSize().getValue(),
                                 fixedTI->getFixedAlignment().getValue());
        
        // Ask the runtime to store an extra inhabitant.
        auto index = llvm::ConstantInt::get(IGF.IGM.Int32Ty, i);
        emitStoreExtraInhabitantCall(IGF, layoutType, index,
                                     xiOpaque.getAddress());
        
        // Compare the stored extra inhabitant against the fixed extra
        // inhabitant pattern.
        auto fixedXI = fixedTI->getFixedExtraInhabitantValue(IGF.IGM, bits, i);
        auto xiBuf2 = IGF.Builder.CreateBitCast(xiBuf,
                                            fixedXI->getType()->getPointerTo());
        llvm::Value *runtimeXI = IGF.Builder.CreateLoad(xiBuf2);
        runtimeXI = fixedTI->maskFixedExtraInhabitant(IGF, runtimeXI);
        
        numberBuf.clear();
        {
          llvm::raw_svector_ostream os(numberBuf);
          os << i;
          os.flush();
        }
        
        verify(runtimeXI, fixedXI,
               llvm::Twine("stored extra inhabitant ") + numberBuf.str());
        
        // Now store the fixed extra inhabitant and ask the runtime to identify
        // it.
        // Mask in junk to make sure the runtime correctly ignores it.
        auto xiMask = fixedTI->getFixedExtraInhabitantMask(IGF.IGM).asAPInt();
        auto maskVal = llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), xiMask);
        auto notMaskVal
          = llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), ~xiMask);
        // TODO: Randomize the filler.
        auto xiFill = llvm::ConstantInt::getAllOnesValue(fixedXI->getType());
        llvm::Value *xiFillMask = IGF.Builder.CreateAnd(notMaskVal, xiFill);
        llvm::Value *xiValMask = IGF.Builder.CreateAnd(maskVal, fixedXI);
        llvm::Value *filledXI = IGF.Builder.CreateOr(xiFillMask, xiValMask);
        
        IGF.Builder.CreateStore(filledXI, xiBuf2);
        
        auto runtimeIndex = emitGetExtraInhabitantIndexCall(IGF, layoutType,
                                                        xiOpaque.getAddress());
        verify(runtimeIndex, index,
               llvm::Twine("extra inhabitant index calculation ")
                 + numberBuf.str());
      }
#endif
    }

    // TODO: Verify interesting layout properties specific to the kind of type,
    // such as struct or class field offsets, enum case tags, vtable entries,
    // etc.
  }
}
Ejemplo n.º 15
0
// Ensure ELF .symver aliases get the same binding as the defined symbol
// they alias with.
static void handleSymverAliases(const Module &M, RecordStreamer &Streamer) {
  if (Streamer.symverAliases().empty())
    return;

  // The name in the assembler will be mangled, but the name in the IR
  // might not, so we first compute a mapping from mangled name to GV.
  Mangler Mang;
  SmallString<64> MangledName;
  StringMap<const GlobalValue *> MangledNameMap;
  auto GetMangledName = [&](const GlobalValue &GV) {
    if (!GV.hasName())
      return;

    MangledName.clear();
    MangledName.reserve(GV.getName().size() + 1);
    Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
    MangledNameMap[MangledName] = &GV;
  };
  for (const Function &F : M)
    GetMangledName(F);
  for (const GlobalVariable &GV : M.globals())
    GetMangledName(GV);
  for (const GlobalAlias &GA : M.aliases())
    GetMangledName(GA);

  // Walk all the recorded .symver aliases, and set up the binding
  // for each alias.
  for (auto &Symver : Streamer.symverAliases()) {
    const MCSymbol *Aliasee = Symver.first;
    MCSymbolAttr Attr = MCSA_Invalid;

    // First check if the aliasee binding was recorded in the asm.
    RecordStreamer::State state = Streamer.getSymbolState(Aliasee);
    switch (state) {
    case RecordStreamer::Global:
    case RecordStreamer::DefinedGlobal:
      Attr = MCSA_Global;
      break;
    case RecordStreamer::UndefinedWeak:
    case RecordStreamer::DefinedWeak:
      Attr = MCSA_Weak;
      break;
    default:
      break;
    }

    // If we don't have a symbol attribute from assembly, then check if
    // the aliasee was defined in the IR.
    if (Attr == MCSA_Invalid) {
      const auto *GV = M.getNamedValue(Aliasee->getName());
      if (!GV) {
        auto MI = MangledNameMap.find(Aliasee->getName());
        if (MI != MangledNameMap.end())
          GV = MI->second;
        else
          continue;
      }
      if (GV->hasExternalLinkage())
        Attr = MCSA_Global;
      else if (GV->hasLocalLinkage())
        Attr = MCSA_Local;
      else if (GV->isWeakForLinker())
        Attr = MCSA_Weak;
    }
    if (Attr == MCSA_Invalid)
      continue;

    // Set the detected binding on each alias with this aliasee.
    for (auto &Alias : Symver.second)
      Streamer.EmitSymbolAttribute(Alias, Attr);
  }
}
Ejemplo n.º 16
0
void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
  // We will either get a quoted filename or a bracketed filename, and we
  // have to track which we got.  The first filename is the source name,
  // and the second name is the mapped filename.  If the first is quoted,
  // the second must be as well (cannot mix and match quotes and brackets).

  // Get the open paren
  Lex(Tok);
  if (Tok.isNot(tok::l_paren)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << "(";
    return;
  }

  // We expect either a quoted string literal, or a bracketed name
  Token SourceFilenameTok;
  CurPPLexer->LexIncludeFilename(SourceFilenameTok);
  if (SourceFilenameTok.is(tok::eod)) {
    // The diagnostic has already been handled
    return;
  }

  StringRef SourceFileName;
  SmallString<128> FileNameBuffer;
  if (SourceFilenameTok.is(tok::string_literal) ||
      SourceFilenameTok.is(tok::angle_string_literal)) {
    SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
  } else if (SourceFilenameTok.is(tok::less)) {
    // This could be a path instead of just a name
    FileNameBuffer.push_back('<');
    SourceLocation End;
    if (ConcatenateIncludeName(FileNameBuffer, End))
      return; // Diagnostic already emitted
    SourceFileName = FileNameBuffer.str();
  } else {
    Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
    return;
  }
  FileNameBuffer.clear();

  // Now we expect a comma, followed by another include name
  Lex(Tok);
  if (Tok.isNot(tok::comma)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << ",";
    return;
  }

  Token ReplaceFilenameTok;
  CurPPLexer->LexIncludeFilename(ReplaceFilenameTok);
  if (ReplaceFilenameTok.is(tok::eod)) {
    // The diagnostic has already been handled
    return;
  }

  StringRef ReplaceFileName;
  if (ReplaceFilenameTok.is(tok::string_literal) ||
      ReplaceFilenameTok.is(tok::angle_string_literal)) {
    ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
  } else if (ReplaceFilenameTok.is(tok::less)) {
    // This could be a path instead of just a name
    FileNameBuffer.push_back('<');
    SourceLocation End;
    if (ConcatenateIncludeName(FileNameBuffer, End))
      return; // Diagnostic already emitted
    ReplaceFileName = FileNameBuffer.str();
  } else {
    Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
    return;
  }

  // Finally, we expect the closing paren
  Lex(Tok);
  if (Tok.isNot(tok::r_paren)) {
    Diag(Tok, diag::warn_pragma_include_alias_expected) << ")";
    return;
  }

  // Now that we have the source and target filenames, we need to make sure
  // they're both of the same type (angled vs non-angled)
  StringRef OriginalSource = SourceFileName;

  bool SourceIsAngled =
    GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
                                SourceFileName);
  bool ReplaceIsAngled =
    GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
                                ReplaceFileName);
  if (!SourceFileName.empty() && !ReplaceFileName.empty() &&
      (SourceIsAngled != ReplaceIsAngled)) {
    unsigned int DiagID;
    if (SourceIsAngled)
      DiagID = diag::warn_pragma_include_alias_mismatch_angle;
    else
      DiagID = diag::warn_pragma_include_alias_mismatch_quote;

    Diag(SourceFilenameTok.getLocation(), DiagID)
      << SourceFileName
      << ReplaceFileName;

    return;
  }

  // Now we can let the include handler know about this mapping
  getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
}
Ejemplo n.º 17
0
/// EmitMatcher - Emit bytes for the specified matcher and return
/// the number of bytes emitted.
unsigned MatcherTableEmitter::
EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
            formatted_raw_ostream &OS) {
  OS.PadToColumn(Indent*2);

  switch (N->getKind()) {
  case Matcher::Scope: {
    const ScopeMatcher *SM = cast<ScopeMatcher>(N);
    assert(SM->getNext() == nullptr && "Shouldn't have next after scope");

    unsigned StartIdx = CurrentIdx;

    // Emit all of the children.
    for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
      if (i == 0) {
        OS << "OPC_Scope, ";
        ++CurrentIdx;
      } else  {
        if (!OmitComments) {
          OS << "/*" << CurrentIdx << "*/";
          OS.PadToColumn(Indent*2) << "/*Scope*/ ";
        } else
          OS.PadToColumn(Indent*2);
      }

      // We need to encode the child and the offset of the failure code before
      // emitting either of them.  Handle this by buffering the output into a
      // string while we get the size.  Unfortunately, the offset of the
      // children depends on the VBR size of the child, so for large children we
      // have to iterate a bit.
      SmallString<128> TmpBuf;
      unsigned ChildSize = 0;
      unsigned VBRSize = 0;
      do {
        VBRSize = GetVBRSize(ChildSize);

        TmpBuf.clear();
        raw_svector_ostream OS(TmpBuf);
        formatted_raw_ostream FOS(OS);
        ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
                                    CurrentIdx+VBRSize, FOS);
      } while (GetVBRSize(ChildSize) != VBRSize);

      assert(ChildSize != 0 && "Should not have a zero-sized child!");

      CurrentIdx += EmitVBRValue(ChildSize, OS);
      if (!OmitComments) {
        OS << "/*->" << CurrentIdx+ChildSize << "*/";

        if (i == 0)
          OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
            << " children in Scope";
      }

      OS << '\n' << TmpBuf;
      CurrentIdx += ChildSize;
    }

    // Emit a zero as a sentinel indicating end of 'Scope'.
    if (!OmitComments)
      OS << "/*" << CurrentIdx << "*/";
    OS.PadToColumn(Indent*2) << "0, ";
    if (!OmitComments)
      OS << "/*End of Scope*/";
    OS << '\n';
    return CurrentIdx - StartIdx + 1;
  }

  case Matcher::RecordNode:
    OS << "OPC_RecordNode,";
    if (!OmitComments)
      OS.PadToColumn(CommentIndent) << "// #"
        << cast<RecordMatcher>(N)->getResultNo() << " = "
        << cast<RecordMatcher>(N)->getWhatFor();
    OS << '\n';
    return 1;

  case Matcher::RecordChild:
    OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
       << ',';
    if (!OmitComments)
      OS.PadToColumn(CommentIndent) << "// #"
        << cast<RecordChildMatcher>(N)->getResultNo() << " = "
        << cast<RecordChildMatcher>(N)->getWhatFor();
    OS << '\n';
    return 1;

  case Matcher::RecordMemRef:
    OS << "OPC_RecordMemRef,\n";
    return 1;

  case Matcher::CaptureGlueInput:
    OS << "OPC_CaptureGlueInput,\n";
    return 1;

  case Matcher::MoveChild:
    OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
    return 2;

  case Matcher::MoveParent:
    OS << "OPC_MoveParent,\n";
    return 1;

  case Matcher::CheckSame:
    OS << "OPC_CheckSame, "
       << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
    return 2;

  case Matcher::CheckChildSame:
    OS << "OPC_CheckChild"
       << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "
       << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
    return 2;

  case Matcher::CheckPatternPredicate: {
    StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
    OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
    if (!OmitComments)
      OS.PadToColumn(CommentIndent) << "// " << Pred;
    OS << '\n';
    return 2;
  }
  case Matcher::CheckPredicate: {
    TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
    OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
    if (!OmitComments)
      OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();
    OS << '\n';
    return 2;
  }

  case Matcher::CheckOpcode:
    OS << "OPC_CheckOpcode, TARGET_VAL("
       << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
    return 3;

  case Matcher::SwitchOpcode:
  case Matcher::SwitchType: {
    unsigned StartIdx = CurrentIdx;

    unsigned NumCases;
    if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
      OS << "OPC_SwitchOpcode ";
      NumCases = SOM->getNumCases();
    } else {
      OS << "OPC_SwitchType ";
      NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
    }

    if (!OmitComments)
      OS << "/*" << NumCases << " cases */";
    OS << ", ";
    ++CurrentIdx;

    // For each case we emit the size, then the opcode, then the matcher.
    for (unsigned i = 0, e = NumCases; i != e; ++i) {
      const Matcher *Child;
      unsigned IdxSize;
      if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
        Child = SOM->getCaseMatcher(i);
        IdxSize = 2;  // size of opcode in table is 2 bytes.
      } else {
        Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
        IdxSize = 1;  // size of type in table is 1 byte.
      }

      // We need to encode the opcode and the offset of the case code before
      // emitting the case code.  Handle this by buffering the output into a
      // string while we get the size.  Unfortunately, the offset of the
      // children depends on the VBR size of the child, so for large children we
      // have to iterate a bit.
      SmallString<128> TmpBuf;
      unsigned ChildSize = 0;
      unsigned VBRSize = 0;
      do {
        VBRSize = GetVBRSize(ChildSize);

        TmpBuf.clear();
        raw_svector_ostream OS(TmpBuf);
        formatted_raw_ostream FOS(OS);
        ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
                                    FOS);
      } while (GetVBRSize(ChildSize) != VBRSize);

      assert(ChildSize != 0 && "Should not have a zero-sized child!");

      if (i != 0) {
        if (!OmitComments)
          OS << "/*" << CurrentIdx << "*/";
        OS.PadToColumn(Indent*2);
        if (!OmitComments)
          OS << (isa<SwitchOpcodeMatcher>(N) ?
                     "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
      }

      // Emit the VBR.
      CurrentIdx += EmitVBRValue(ChildSize, OS);

      if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
        OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";
      else
        OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';

      CurrentIdx += IdxSize;

      if (!OmitComments)
        OS << "// ->" << CurrentIdx+ChildSize;
      OS << '\n';
      OS << TmpBuf;
      CurrentIdx += ChildSize;
    }

    // Emit the final zero to terminate the switch.
    if (!OmitComments)
      OS << "/*" << CurrentIdx << "*/";
    OS.PadToColumn(Indent*2) << "0, ";
    if (!OmitComments)
      OS << (isa<SwitchOpcodeMatcher>(N) ?
             "// EndSwitchOpcode" : "// EndSwitchType");

    OS << '\n';
    ++CurrentIdx;
    return CurrentIdx-StartIdx;
  }

 case Matcher::CheckType:
    assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&
           "FIXME: Add support for CheckType of resno != 0");
    OS << "OPC_CheckType, "
       << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
    return 2;

  case Matcher::CheckChildType:
    OS << "OPC_CheckChild"
       << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
       << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
    return 2;

  case Matcher::CheckInteger: {
    OS << "OPC_CheckInteger, ";
    unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
    OS << '\n';
    return Bytes;
  }
  case Matcher::CheckChildInteger: {
    OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo()
       << "Integer, ";
    unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(),
                                  OS);
    OS << '\n';
    return Bytes;
  }
  case Matcher::CheckCondCode:
    OS << "OPC_CheckCondCode, ISD::"
       << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
    return 2;

  case Matcher::CheckValueType:
    OS << "OPC_CheckValueType, MVT::"
       << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
    return 2;

  case Matcher::CheckComplexPat: {
    const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
    const ComplexPattern &Pattern = CCPM->getPattern();
    OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
       << CCPM->getMatchNumber() << ',';

    if (!OmitComments) {
      OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
      OS << ":$" << CCPM->getName();
      for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
        OS << " #" << CCPM->getFirstResult()+i;

      if (Pattern.hasProperty(SDNPHasChain))
        OS << " + chain result";
    }
    OS << '\n';
    return 3;
  }

  case Matcher::CheckAndImm: {
    OS << "OPC_CheckAndImm, ";
    unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
    OS << '\n';
    return Bytes;
  }

  case Matcher::CheckOrImm: {
    OS << "OPC_CheckOrImm, ";
    unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
    OS << '\n';
    return Bytes;
  }

  case Matcher::CheckFoldableChainNode:
    OS << "OPC_CheckFoldableChainNode,\n";
    return 1;

  case Matcher::EmitInteger: {
    int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
    OS << "OPC_EmitInteger, "
       << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
    unsigned Bytes = 2+EmitVBRValue(Val, OS);
    OS << '\n';
    return Bytes;
  }
  case Matcher::EmitStringInteger: {
    const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
    // These should always fit into one byte.
    OS << "OPC_EmitInteger, "
      << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
      << Val << ",\n";
    return 3;
  }

  case Matcher::EmitRegister: {
    const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N);
    const CodeGenRegister *Reg = Matcher->getReg();
    // If the enum value of the register is larger than one byte can handle,
    // use EmitRegister2.
    if (Reg && Reg->EnumValue > 255) {
      OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", ";
      OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n";
      return 4;
    } else {
      OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", ";
      if (Reg) {
        OS << getQualifiedName(Reg->TheDef) << ",\n";
      } else {
        OS << "0 ";
        if (!OmitComments)
          OS << "/*zero_reg*/";
        OS << ",\n";
      }
      return 3;
    }
  }

  case Matcher::EmitConvertToTarget:
    OS << "OPC_EmitConvertToTarget, "
       << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
    return 2;

  case Matcher::EmitMergeInputChains: {
    const EmitMergeInputChainsMatcher *MN =
      cast<EmitMergeInputChainsMatcher>(N);

    // Handle the specialized forms OPC_EmitMergeInputChains1_0, 1_1, and 1_2.
    if (MN->getNumNodes() == 1 && MN->getNode(0) < 3) {
      OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
      return 1;
    }

    OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
    for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
      OS << MN->getNode(i) << ", ";
    OS << '\n';
    return 2+MN->getNumNodes();
  }
  case Matcher::EmitCopyToReg:
    OS << "OPC_EmitCopyToReg, "
       << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "
       << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())
       << ",\n";
    return 3;
  case Matcher::EmitNodeXForm: {
    const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);
    OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
       << XF->getSlot() << ',';
    if (!OmitComments)
      OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();
    OS <<'\n';
    return 3;
  }

  case Matcher::EmitNode:
  case Matcher::MorphNodeTo: {
    const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
    OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
    OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0";

    if (EN->hasChain())   OS << "|OPFL_Chain";
    if (EN->hasInFlag())  OS << "|OPFL_GlueInput";
    if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput";
    if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
    if (EN->getNumFixedArityOperands() != -1)
      OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
    OS << ",\n";

    OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
    if (!OmitComments)
      OS << "/*#VTs*/";
    OS << ", ";
    for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)
      OS << getEnumName(EN->getVT(i)) << ", ";

    OS << EN->getNumOperands();
    if (!OmitComments)
      OS << "/*#Ops*/";
    OS << ", ";
    unsigned NumOperandBytes = 0;
    for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
      NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);

    if (!OmitComments) {
      // Print the result #'s for EmitNode.
      if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
        if (unsigned NumResults = EN->getNumVTs()) {
          OS.PadToColumn(CommentIndent) << "// Results =";
          unsigned First = E->getFirstResultSlot();
          for (unsigned i = 0; i != NumResults; ++i)
            OS << " #" << First+i;
        }
      }
      OS << '\n';

      if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
        OS.PadToColumn(Indent*2) << "// Src: "
          << *SNT->getPattern().getSrcPattern() << " - Complexity = "
          << SNT->getPattern().getPatternComplexity(CGP) << '\n';
        OS.PadToColumn(Indent*2) << "// Dst: "
          << *SNT->getPattern().getDstPattern() << '\n';
      }
    } else
      OS << '\n';

    return 6+EN->getNumVTs()+NumOperandBytes;
  }
  case Matcher::MarkGlueResults: {
    const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);
    OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";
    unsigned NumOperandBytes = 0;
    for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
      NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
    OS << '\n';
    return 2+NumOperandBytes;
  }
  case Matcher::CompleteMatch: {
    const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
    OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
    unsigned NumResultBytes = 0;
    for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
      NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
    OS << '\n';
    if (!OmitComments) {
      OS.PadToColumn(Indent*2) << "// Src: "
        << *CM->getPattern().getSrcPattern() << " - Complexity = "
        << CM->getPattern().getPatternComplexity(CGP) << '\n';
      OS.PadToColumn(Indent*2) << "// Dst: "
        << *CM->getPattern().getDstPattern();
    }
    OS << '\n';
    return 2 + NumResultBytes;
  }
  }
  llvm_unreachable("Unreachable");
}
Ejemplo n.º 18
0
void RecordStreamer::flushSymverDirectives() {
  // Mapping from mangled name to GV.
  StringMap<const GlobalValue *> MangledNameMap;
  // The name in the assembler will be mangled, but the name in the IR
  // might not, so we first compute a mapping from mangled name to GV.
  Mangler Mang;
  SmallString<64> MangledName;
  for (const GlobalValue &GV : M.global_values()) {
    if (!GV.hasName())
      continue;
    MangledName.clear();
    MangledName.reserve(GV.getName().size() + 1);
    Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
    MangledNameMap[MangledName] = &GV;
  }

  // Walk all the recorded .symver aliases, and set up the binding
  // for each alias.
  for (auto &Symver : SymverAliasMap) {
    const MCSymbol *Aliasee = Symver.first;
    MCSymbolAttr Attr = MCSA_Invalid;
    bool IsDefined = false;

    // First check if the aliasee binding was recorded in the asm.
    RecordStreamer::State state = getSymbolState(Aliasee);
    switch (state) {
    case RecordStreamer::Global:
    case RecordStreamer::DefinedGlobal:
      Attr = MCSA_Global;
      break;
    case RecordStreamer::UndefinedWeak:
    case RecordStreamer::DefinedWeak:
      Attr = MCSA_Weak;
      break;
    default:
      break;
    }

    switch (state) {
    case RecordStreamer::Defined:
    case RecordStreamer::DefinedGlobal:
    case RecordStreamer::DefinedWeak:
      IsDefined = true;
      break;
    case RecordStreamer::NeverSeen:
    case RecordStreamer::Global:
    case RecordStreamer::Used:
    case RecordStreamer::UndefinedWeak:
      break;
    }

    if (Attr == MCSA_Invalid || !IsDefined) {
      const GlobalValue *GV = M.getNamedValue(Aliasee->getName());
      if (!GV) {
        auto MI = MangledNameMap.find(Aliasee->getName());
        if (MI != MangledNameMap.end())
          GV = MI->second;
      }
      if (GV) {
        // If we don't have a symbol attribute from assembly, then check if
        // the aliasee was defined in the IR.
        if (Attr == MCSA_Invalid) {
          if (GV->hasExternalLinkage())
            Attr = MCSA_Global;
          else if (GV->hasLocalLinkage())
            Attr = MCSA_Local;
          else if (GV->isWeakForLinker())
            Attr = MCSA_Weak;
        }
        IsDefined = IsDefined || !GV->isDeclarationForLinker();
      }
    }

    // Set the detected binding on each alias with this aliasee.
    for (auto AliasName : Symver.second) {
      std::pair<StringRef, StringRef> Split = AliasName.split("@@@");
      SmallString<128> NewName;
      if (!Split.second.empty() && !Split.second.startswith("@")) {
        // Special processing for "@@@" according
        // https://sourceware.org/binutils/docs/as/Symver.html
        const char *Separator = IsDefined ? "@@" : "@";
        AliasName =
            (Split.first + Separator + Split.second).toStringRef(NewName);
      }
      MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
      // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be
      // converted into @ or @@.
      const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
      if (IsDefined)
        markDefined(*Alias);
      // Don't use EmitAssignment override as it always marks alias as defined.
      MCStreamer::EmitAssignment(Alias, Value);
      if (Attr != MCSA_Invalid)
        EmitSymbolAttribute(Alias, Attr);
    }
  }
}
Ejemplo n.º 19
0
static void deriveBodyError_enum_code(AbstractFunctionDecl *codeDecl) {
  // enum SomeEnum {
  //   case A,B,C,D
  //
  //   @derived
  //   var code: Int {
  //     switch self {
  //     case A: return 0
  //     case B: return 1
  //     case C: return 2
  //     ...
  //     }
  //   }
  // }
  //
  // TODO: Some convenient way to override the code if that's desired.

  auto parentDC = codeDecl->getDeclContext();
  ASTContext &C = parentDC->getASTContext();

  auto enumDecl = parentDC->getAsEnumOrEnumExtensionContext();
  Type enumType = parentDC->getDeclaredTypeInContext();

  SmallVector<CaseStmt*, 4> cases;
  SmallString<11> strBuf;

  unsigned code = 0;
  for (auto elt : enumDecl->getAllElements()) {
    auto pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
                                          SourceLoc(), SourceLoc(),
                                          Identifier(), elt, nullptr);
    pat->setImplicit();
    
    auto labelItem =
      CaseLabelItem(/*IsDefault=*/false, pat, SourceLoc(), nullptr);

    {
      strBuf.clear();
      llvm::raw_svector_ostream os(strBuf);
      os << code;
    }
    
    auto codeStr = C.AllocateCopy(StringRef(strBuf));

    auto returnExpr = new (C) IntegerLiteralExpr(codeStr, SourceLoc(),
                                                 /*implicit*/ true);
    auto returnStmt = new (C) ReturnStmt(SourceLoc(), returnExpr,
                                         /*implicit*/ true);
    
    auto body = BraceStmt::create(C, SourceLoc(),
                                  ASTNode(returnStmt), SourceLoc());

    cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
                                     /*HasBoundDecls=*/false, SourceLoc(),
                                     body));
    
    ++code;
  }
  
  Stmt *bodyStmt;
  // If the enum is empty, simply return zero. (It doesn't really matter, since
  // the enum can't be instantiated regardless.)
  if (cases.empty()) {
    static const char zero[] = "0";
    auto returnExpr = new (C) IntegerLiteralExpr(zero, SourceLoc(),
                                                 /*implicit*/ true);
    bodyStmt = new (C) ReturnStmt(SourceLoc(), returnExpr,
                                  /*implicit*/ true);
  } else {
    auto selfRef = createSelfDeclRef(codeDecl);
    bodyStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(), selfRef,
                                  SourceLoc(), cases, SourceLoc(), C);
  }
  auto body = BraceStmt::create(C, SourceLoc(),
                                ASTNode(bodyStmt),
                                SourceLoc());

  codeDecl->setBody(body);
}