forked from OSchip/llvm-project
Use raw_pwrite_stream in clang.
This is a small improvement to -emit-pth and allows llvm to start requiring it. llvm-svn: 234897
This commit is contained in:
parent
b913653b91
commit
2f16bc1095
|
@ -45,6 +45,7 @@ namespace llvm {
|
|||
class RefCountedBaseVPTR;
|
||||
|
||||
class raw_ostream;
|
||||
class raw_pwrite_stream;
|
||||
// TODO: DenseMap, ...
|
||||
}
|
||||
|
||||
|
@ -76,6 +77,7 @@ namespace clang {
|
|||
using llvm::RefCountedBaseVPTR;
|
||||
|
||||
using llvm::raw_ostream;
|
||||
using llvm::raw_pwrite_stream;
|
||||
} // end namespace clang.
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace clang {
|
|||
void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
|
||||
const TargetOptions &TOpts, const LangOptions &LOpts,
|
||||
StringRef TDesc, llvm::Module *M, BackendAction Action,
|
||||
raw_ostream *OS);
|
||||
raw_pwrite_stream *OS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -161,6 +161,11 @@ class CompilerInstance : public ModuleLoader {
|
|||
TempFilename(std::move(O.TempFilename)), OS(std::move(O.OS)) {}
|
||||
};
|
||||
|
||||
/// If the output doesn't support seeking (terminal, pipe). we switch
|
||||
/// the stream to a buffer_ostream. These are the buffer and the original
|
||||
/// stream.
|
||||
std::unique_ptr<llvm::raw_fd_ostream> NonSeekStream;
|
||||
|
||||
/// The list of active output files.
|
||||
std::list<OutputFile> OutputFiles;
|
||||
|
||||
|
@ -631,21 +636,19 @@ public:
|
|||
/// atomically replace the target output on success).
|
||||
///
|
||||
/// \return - Null on error.
|
||||
llvm::raw_fd_ostream *
|
||||
createDefaultOutputFile(bool Binary = true, StringRef BaseInput = "",
|
||||
StringRef Extension = "");
|
||||
raw_pwrite_stream *createDefaultOutputFile(bool Binary = true,
|
||||
StringRef BaseInput = "",
|
||||
StringRef Extension = "");
|
||||
|
||||
/// Create a new output file and add it to the list of tracked output files,
|
||||
/// optionally deriving the output path name.
|
||||
///
|
||||
/// \return - Null on error.
|
||||
llvm::raw_fd_ostream *
|
||||
createOutputFile(StringRef OutputPath,
|
||||
bool Binary, bool RemoveFileOnSignal,
|
||||
StringRef BaseInput,
|
||||
StringRef Extension,
|
||||
bool UseTemporary,
|
||||
bool CreateMissingDirectories = false);
|
||||
raw_pwrite_stream *createOutputFile(StringRef OutputPath, bool Binary,
|
||||
bool RemoveFileOnSignal,
|
||||
StringRef BaseInput, StringRef Extension,
|
||||
bool UseTemporary,
|
||||
bool CreateMissingDirectories = false);
|
||||
|
||||
/// Create a new output file, optionally deriving the output path name.
|
||||
///
|
||||
|
@ -672,7 +675,7 @@ public:
|
|||
/// stored here on success.
|
||||
/// \param TempPathName [out] - If given, the temporary file path name
|
||||
/// will be stored here on success.
|
||||
static std::unique_ptr<llvm::raw_fd_ostream>
|
||||
std::unique_ptr<raw_pwrite_stream>
|
||||
createOutputFile(StringRef OutputPath, std::error_code &Error, bool Binary,
|
||||
bool RemoveFileOnSignal, StringRef BaseInput,
|
||||
StringRef Extension, bool UseTemporary,
|
||||
|
|
|
@ -159,9 +159,8 @@ void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
|
|||
StringRef OutputPath = "",
|
||||
bool ShowDepth = true, bool MSStyle = false);
|
||||
|
||||
/// CacheTokens - Cache tokens for use with PCH. Note that this requires
|
||||
/// a seekable stream.
|
||||
void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
|
||||
/// Cache tokens for use with PCH. Note that this requires a seekable stream.
|
||||
void CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS);
|
||||
|
||||
/// The ChainedIncludesSource class converts headers to chained PCHs in
|
||||
/// memory, mainly for testing.
|
||||
|
|
|
@ -96,7 +96,7 @@ private:
|
|||
|
||||
void CreatePasses();
|
||||
|
||||
/// CreateTargetMachine - Generates the TargetMachine.
|
||||
/// Generates the TargetMachine.
|
||||
/// Returns Null if it is unable to create the target machine.
|
||||
/// Some of our clang tests specify triples which are not built
|
||||
/// into clang. This is okay because these tests check the generated
|
||||
|
@ -106,10 +106,10 @@ private:
|
|||
/// the requested target.
|
||||
TargetMachine *CreateTargetMachine(bool MustCreateTM);
|
||||
|
||||
/// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
|
||||
/// Add passes necessary to emit assembly or LLVM IR.
|
||||
///
|
||||
/// \return True on success.
|
||||
bool AddEmitPasses(BackendAction Action, raw_ostream &OS);
|
||||
bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS);
|
||||
|
||||
public:
|
||||
EmitAssemblyHelper(DiagnosticsEngine &_Diags,
|
||||
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
|
||||
void EmitAssembly(BackendAction Action, raw_ostream *OS);
|
||||
void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS);
|
||||
};
|
||||
|
||||
// We need this wrapper to access LangOpts and CGOpts from extension functions
|
||||
|
@ -545,7 +545,8 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
|
|||
return TM;
|
||||
}
|
||||
|
||||
bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, raw_ostream &OS) {
|
||||
bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
|
||||
raw_pwrite_stream &OS) {
|
||||
|
||||
// Create the code generator passes.
|
||||
legacy::PassManager *PM = getCodeGenPasses();
|
||||
|
@ -582,7 +583,8 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, raw_ostream &OS) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
|
||||
void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
|
||||
raw_pwrite_stream *OS) {
|
||||
TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
|
||||
|
||||
bool UsesCodeGen = (Action != Backend_EmitNothing &&
|
||||
|
@ -644,7 +646,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
|
|||
const clang::TargetOptions &TOpts,
|
||||
const LangOptions &LOpts, StringRef TDesc,
|
||||
Module *M, BackendAction Action,
|
||||
raw_ostream *OS) {
|
||||
raw_pwrite_stream *OS) {
|
||||
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
|
||||
|
||||
AsmHelper.EmitAssembly(Action, OS);
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace clang {
|
|||
const CodeGenOptions &CodeGenOpts;
|
||||
const TargetOptions &TargetOpts;
|
||||
const LangOptions &LangOpts;
|
||||
raw_ostream *AsmOutStream;
|
||||
raw_pwrite_stream *AsmOutStream;
|
||||
ASTContext *Context;
|
||||
|
||||
Timer LLVMIRGeneration;
|
||||
|
@ -61,7 +61,7 @@ namespace clang {
|
|||
const TargetOptions &targetopts,
|
||||
const LangOptions &langopts, bool TimePasses,
|
||||
const std::string &infile, llvm::Module *LinkModule,
|
||||
raw_ostream *OS, LLVMContext &C,
|
||||
raw_pwrite_stream *OS, LLVMContext &C,
|
||||
CoverageSourceInfo *CoverageInfo = nullptr)
|
||||
: Diags(_Diags), Action(action), CodeGenOpts(compopts),
|
||||
TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
|
||||
|
@ -601,9 +601,8 @@ llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
|
|||
return VMContext;
|
||||
}
|
||||
|
||||
static raw_ostream *GetOutputStream(CompilerInstance &CI,
|
||||
StringRef InFile,
|
||||
BackendAction Action) {
|
||||
static raw_pwrite_stream *
|
||||
GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
|
||||
switch (Action) {
|
||||
case Backend_EmitAssembly:
|
||||
return CI.createDefaultOutputFile(false, InFile, "s");
|
||||
|
@ -625,7 +624,7 @@ static raw_ostream *GetOutputStream(CompilerInstance &CI,
|
|||
std::unique_ptr<ASTConsumer>
|
||||
CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
|
||||
BackendAction BA = static_cast<BackendAction>(Act);
|
||||
std::unique_ptr<raw_ostream> OS(GetOutputStream(CI, InFile, BA));
|
||||
std::unique_ptr<raw_pwrite_stream> OS(GetOutputStream(CI, InFile, BA));
|
||||
if (BA != Backend_EmitNothing && !OS)
|
||||
return nullptr;
|
||||
|
||||
|
@ -678,7 +677,7 @@ void CodeGenAction::ExecuteAction() {
|
|||
if (getCurrentFileKind() == IK_LLVM_IR) {
|
||||
BackendAction BA = static_cast<BackendAction>(Act);
|
||||
CompilerInstance &CI = getCompilerInstance();
|
||||
raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA);
|
||||
raw_pwrite_stream *OS = GetOutputStream(CI, getCurrentFile(), BA);
|
||||
if (BA != Backend_EmitNothing && !OS)
|
||||
return;
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ class PTHWriter {
|
|||
typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
|
||||
|
||||
IDMap IM;
|
||||
llvm::raw_fd_ostream& Out;
|
||||
raw_pwrite_stream &Out;
|
||||
Preprocessor& PP;
|
||||
uint32_t idcount;
|
||||
PTHMap PM;
|
||||
|
@ -236,8 +236,8 @@ class PTHWriter {
|
|||
Offset EmitCachedSpellings();
|
||||
|
||||
public:
|
||||
PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
|
||||
: Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
|
||||
PTHWriter(raw_pwrite_stream &out, Preprocessor &pp)
|
||||
: Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
|
||||
|
||||
PTHMap &getPM() { return PM; }
|
||||
void GeneratePTH(const std::string &MainFile);
|
||||
|
@ -468,6 +468,16 @@ Offset PTHWriter::EmitCachedSpellings() {
|
|||
return SpellingsOff;
|
||||
}
|
||||
|
||||
static uint32_t swap32le(uint32_t X) {
|
||||
return llvm::support::endian::byte_swap<uint32_t, llvm::support::little>(X);
|
||||
}
|
||||
|
||||
static void pwrite32le(raw_pwrite_stream &OS, uint32_t Val, uint64_t &Off) {
|
||||
uint32_t LEVal = swap32le(Val);
|
||||
OS.pwrite(reinterpret_cast<const char *>(&LEVal), 4, Off);
|
||||
Off += 4;
|
||||
}
|
||||
|
||||
void PTHWriter::GeneratePTH(const std::string &MainFile) {
|
||||
// Generate the prologue.
|
||||
Out << "cfe-pth" << '\0';
|
||||
|
@ -520,11 +530,11 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) {
|
|||
Offset FileTableOff = EmitFileTable();
|
||||
|
||||
// Finally, write the prologue.
|
||||
Out.seek(PrologueOffset);
|
||||
Emit32(IdTableOff.first);
|
||||
Emit32(IdTableOff.second);
|
||||
Emit32(FileTableOff);
|
||||
Emit32(SpellingOff);
|
||||
uint64_t Off = PrologueOffset;
|
||||
pwrite32le(Out, IdTableOff.first, Off);
|
||||
pwrite32le(Out, IdTableOff.second, Off);
|
||||
pwrite32le(Out, FileTableOff, Off);
|
||||
pwrite32le(Out, SpellingOff, Off);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -559,8 +569,7 @@ public:
|
|||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
|
||||
void clang::CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS) {
|
||||
// Get the name of the main file.
|
||||
const SourceManager &SrcMgr = PP.getSourceManager();
|
||||
const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
|
||||
|
|
|
@ -550,11 +550,11 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) {
|
|||
|
||||
}
|
||||
OutputFiles.clear();
|
||||
NonSeekStream.reset();
|
||||
}
|
||||
|
||||
llvm::raw_fd_ostream *
|
||||
CompilerInstance::createDefaultOutputFile(bool Binary,
|
||||
StringRef InFile,
|
||||
raw_pwrite_stream *
|
||||
CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
|
||||
StringRef Extension) {
|
||||
return createOutputFile(getFrontendOpts().OutputFile, Binary,
|
||||
/*RemoveFileOnSignal=*/true, InFile, Extension,
|
||||
|
@ -568,16 +568,14 @@ llvm::raw_null_ostream *CompilerInstance::createNullOutputFile() {
|
|||
return Ret;
|
||||
}
|
||||
|
||||
llvm::raw_fd_ostream *
|
||||
CompilerInstance::createOutputFile(StringRef OutputPath,
|
||||
bool Binary, bool RemoveFileOnSignal,
|
||||
StringRef InFile,
|
||||
StringRef Extension,
|
||||
bool UseTemporary,
|
||||
raw_pwrite_stream *
|
||||
CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
|
||||
bool RemoveFileOnSignal, StringRef InFile,
|
||||
StringRef Extension, bool UseTemporary,
|
||||
bool CreateMissingDirectories) {
|
||||
std::string OutputPathName, TempPathName;
|
||||
std::error_code EC;
|
||||
std::unique_ptr<llvm::raw_fd_ostream> OS = createOutputFile(
|
||||
std::unique_ptr<raw_pwrite_stream> OS = createOutputFile(
|
||||
OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,
|
||||
UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);
|
||||
if (!OS) {
|
||||
|
@ -586,7 +584,7 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
llvm::raw_fd_ostream *Ret = OS.get();
|
||||
raw_pwrite_stream *Ret = OS.get();
|
||||
// Add the output file -- but don't try to remove "-", since this means we are
|
||||
// using stdin.
|
||||
addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
|
||||
|
@ -595,7 +593,7 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
|
|||
return Ret;
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::raw_fd_ostream> CompilerInstance::createOutputFile(
|
||||
std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
|
||||
StringRef OutputPath, std::error_code &Error, bool Binary,
|
||||
bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,
|
||||
bool UseTemporary, bool CreateMissingDirectories,
|
||||
|
@ -683,7 +681,13 @@ std::unique_ptr<llvm::raw_fd_ostream> CompilerInstance::createOutputFile(
|
|||
if (TempPathName)
|
||||
*TempPathName = TempFile;
|
||||
|
||||
return OS;
|
||||
if (!Binary || OS->supportsSeeking())
|
||||
return std::move(OS);
|
||||
|
||||
auto B = llvm::make_unique<llvm::buffer_ostream>(*OS);
|
||||
assert(!NonSeekStream);
|
||||
NonSeekStream = std::move(OS);
|
||||
return std::move(B);
|
||||
}
|
||||
|
||||
// Initialization Utilities
|
||||
|
|
|
@ -599,15 +599,10 @@ void DumpTokensAction::ExecuteAction() {
|
|||
|
||||
void GeneratePTHAction::ExecuteAction() {
|
||||
CompilerInstance &CI = getCompilerInstance();
|
||||
llvm::raw_fd_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
|
||||
raw_pwrite_stream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
|
||||
if (!OS)
|
||||
return;
|
||||
|
||||
if (!OS->supportsSeeking()) {
|
||||
// FIXME: Don't fail this way.
|
||||
llvm::report_fatal_error("PTH requires a seekable file for output!");
|
||||
}
|
||||
|
||||
CacheTokens(CI.getPreprocessor(), OS);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o %t1 %s
|
||||
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o - %s > %t2
|
||||
// RUN: cmp %t1 %t2
|
||||
// RUN: not %clang_cc1 -triple i386-unknown-unknown -emit-pth -o - %s 2>&1 | \
|
||||
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o - %s | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
// CHECK: PTH requires a seekable file for output!
|
||||
// CHECK: cfe-pth
|
||||
|
|
|
@ -315,8 +315,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|||
MAI->setCompressDebugSections(true);
|
||||
|
||||
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
|
||||
std::unique_ptr<raw_fd_ostream> Out = getOutputStream(Opts, Diags, IsBinary);
|
||||
if (!Out)
|
||||
std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags, IsBinary);
|
||||
if (!FDOS)
|
||||
return true;
|
||||
|
||||
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
|
||||
|
@ -355,6 +355,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|||
std::unique_ptr<MCSubtargetInfo> STI(
|
||||
TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
|
||||
|
||||
raw_pwrite_stream *Out = FDOS.get();
|
||||
std::unique_ptr<buffer_ostream> BOS;
|
||||
|
||||
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
|
||||
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
|
||||
MCInstPrinter *IP = TheTarget->createMCInstPrinter(
|
||||
|
@ -374,6 +377,11 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|||
} else {
|
||||
assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
|
||||
"Invalid file type!");
|
||||
if (!FDOS->supportsSeeking()) {
|
||||
BOS = make_unique<buffer_ostream>(*FDOS);
|
||||
Out = BOS.get();
|
||||
}
|
||||
|
||||
MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
|
||||
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
|
||||
Opts.CPU);
|
||||
|
@ -402,7 +410,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|||
}
|
||||
|
||||
// Close the output stream early.
|
||||
Out.reset();
|
||||
BOS.reset();
|
||||
FDOS.reset();
|
||||
|
||||
// Delete output file if there were errors.
|
||||
if (Failed && Opts.OutputPath != "-")
|
||||
|
|
Loading…
Reference in New Issue