/// Canonicalize whitespaces in the input file. Line endings are replaced /// with UNIX-style '\n'. /// /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace /// characters to a single space. static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, bool PreserveHorizontal) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); Ptr != End; ++Ptr) { // Eliminate trailing dosish \r. if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { continue; } // If current char is not a horizontal whitespace or if horizontal // whitespace canonicalization is disabled, dump it to output as is. if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) { NewFile.push_back(*Ptr); continue; } // Otherwise, add one space and advance over neighboring space. NewFile.push_back(' '); while (Ptr+1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t')) ++Ptr; } // Free the old buffer and return a new one. MemoryBuffer *MB2 = MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); delete MB; return MB2; }
/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified /// memory buffer, free it, and return a new one. static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); Ptr != End; ++Ptr) { // If C is not a horizontal whitespace, skip it. if (*Ptr != ' ' && *Ptr != '\t') { NewFile.push_back(*Ptr); continue; } // Otherwise, add one space and advance over neighboring space. NewFile.push_back(' '); while (Ptr+1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t')) ++Ptr; } // Free the old buffer and return a new one. MemoryBuffer *MB2 = MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); delete MB; return MB2; }
const X86Subtarget * X86TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString() : (StringRef)TargetCPU; StringRef FS = !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : (StringRef)TargetFS; SmallString<512> Key; Key.reserve(CPU.size() + FS.size()); Key += CPU; Key += FS; // FIXME: This is related to the code below to reset the target options, // we need to know whether or not the soft float flag is set on the // function before we can generate a subtarget. We also need to use // it as a key for the subtarget since that can be the only difference // between two functions. bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsString() == "true"; // If the soft float attribute is set on the function turn on the soft float // subtarget feature. if (SoftFloat) Key += FS.empty() ? "+soft-float" : ",+soft-float"; FS = Key.substr(CPU.size()); auto &I = SubtargetMap[Key]; if (!I) { // This needs to be done before we create a new subtarget since any // creation will depend on the TM and the code generation flags on the // function that reside in TargetOptions. resetTargetOptions(F); I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this, Options.StackAlignmentOverride); #ifndef LLVM_BUILD_GLOBAL_ISEL GISelAccessor *GISel = new GISelAccessor(); #else X86GISelActualAccessor *GISel = new X86GISelActualAccessor(); GISel->CallLoweringInfo.reset(new X86CallLowering(*I->getTargetLowering())); GISel->Legalizer.reset(new X86LegalizerInfo(*I, *this)); auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo()); GISel->RegBankInfo.reset(RBI); GISel->InstSelector.reset(createX86InstructionSelector( *this, *I, *RBI)); #endif I->setGISelAccessor(*GISel); } return I.get(); }
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; }
static ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBufferForStream(int FD, const Twine &BufferName) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(FD, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return std::error_code(errno, std::generic_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); return MemoryBuffer::getMemBufferCopy(Buffer, BufferName); }
const X86Subtarget * X86TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString() : (StringRef)TargetCPU; StringRef FS = !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : (StringRef)TargetFS; SmallString<512> Key; Key.reserve(CPU.size() + FS.size()); Key += CPU; Key += FS; // FIXME: This is related to the code below to reset the target options, // we need to know whether or not the soft float flag is set on the // function before we can generate a subtarget. We also need to use // it as a key for the subtarget since that can be the only difference // between two functions. bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsString() == "true"; // If the soft float attribute is set on the function turn on the soft float // subtarget feature. if (SoftFloat) Key += FS.empty() ? "+soft-float" : ",+soft-float"; FS = Key.substr(CPU.size()); auto &I = SubtargetMap[Key]; if (!I) { // This needs to be done before we create a new subtarget since any // creation will depend on the TM and the code generation flags on the // function that reside in TargetOptions. resetTargetOptions(F); I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this, Options.StackAlignmentOverride); } return I.get(); }
static error_code getMemoryBufferForStream(int FD, StringRef BufferName, std::unique_ptr<MemoryBuffer> &Result) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(FD, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return error_code(errno, posix_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); Result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); return error_code::success(); }
error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { // Read in all of the data from stdin, we cannot mmap stdin. // // FIXME: That isn't necessarily true, we should try to mmap stdin and // fallback if it fails. sys::Program::ChangeStdinToBinary(); const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); ReadBytes = read(0, Buffer.end(), ChunkSize); if (ReadBytes == -1) { if (errno == EINTR) continue; return error_code(errno, posix_category()); } Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); result.reset(getMemBufferCopy(Buffer, "<stdin>")); return error_code::success(); }
const X86Subtarget * X86TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString() : (StringRef)TargetCPU; StringRef FS = !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : (StringRef)TargetFS; SmallString<512> Key; Key.reserve(CPU.size() + FS.size()); Key += CPU; Key += FS; // FIXME: This is related to the code below to reset the target options, // we need to know whether or not the soft float flag is set on the // function before we can generate a subtarget. We also need to use // it as a key for the subtarget since that can be the only difference // between two functions. bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsString() == "true"; // If the soft float attribute is set on the function turn on the soft float // subtarget feature. if (SoftFloat) Key += FS.empty() ? "+soft-float" : ",+soft-float"; // Keep track of the key width after all features are added so we can extract // the feature string out later. unsigned CPUFSWidth = Key.size(); // Extract prefer-vector-width attribute. unsigned PreferVectorWidthOverride = 0; if (F.hasFnAttribute("prefer-vector-width")) { StringRef Val = F.getFnAttribute("prefer-vector-width").getValueAsString(); unsigned Width; if (!Val.getAsInteger(0, Width)) { Key += ",prefer-vector-width="; Key += Val; PreferVectorWidthOverride = Width; } } // Extract min-legal-vector-width attribute. unsigned RequiredVectorWidth = UINT32_MAX; if (F.hasFnAttribute("min-legal-vector-width")) { StringRef Val = F.getFnAttribute("min-legal-vector-width").getValueAsString(); unsigned Width; if (!Val.getAsInteger(0, Width)) { Key += ",min-legal-vector-width="; Key += Val; RequiredVectorWidth = Width; } } // Extracted here so that we make sure there is backing for the StringRef. If // we assigned earlier, its possible the SmallString reallocated leaving a // dangling StringRef. FS = Key.slice(CPU.size(), CPUFSWidth); auto &I = SubtargetMap[Key]; if (!I) { // This needs to be done before we create a new subtarget since any // creation will depend on the TM and the code generation flags on the // function that reside in TargetOptions. resetTargetOptions(F); I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this, Options.StackAlignmentOverride, PreferVectorWidthOverride, RequiredVectorWidth); } return I.get(); }
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); } } }
// 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); } }