diff options
author | Mark Doffman <mark.doffman@codethink.co.uk> | 2014-10-29 15:48:44 +0000 |
---|---|---|
committer | Mark Doffman <mark.doffman@codethink.co.uk> | 2014-11-03 21:02:29 +0000 |
commit | 5e1f661d0a5cc9d86ecccdd2224254571aaede21 (patch) | |
tree | 5a51cfa56376bc61e0f02b3dd4abcf639352c410 | |
parent | 1646423aa7d657da1e95126c5b1bf2a9e72d8160 (diff) | |
download | flang-5e1f661d0a5cc9d86ecccdd2224254571aaede21.tar.gz |
Update code to llvm 3.6.
Updating API's to build with llvm 3.6.
30 files changed, 2705 insertions, 50 deletions
diff --git a/include/flang/AST/ASTContext.h b/include/flang/AST/ASTContext.h index 5191122dcd..7e9c00405a 100644 --- a/include/flang/AST/ASTContext.h +++ b/include/flang/AST/ASTContext.h @@ -79,8 +79,8 @@ public: void *Allocate(unsigned Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } - void Deallocate(void *Ptr) const { - BumpAlloc.Deallocate(Ptr); + void Deallocate(void *Ptr, size_t size) const { + BumpAlloc.Deallocate((const void*) Ptr, size); } LangOptions getLangOpts() const { @@ -259,9 +259,9 @@ inline void *operator new(size_t Bytes, const flang::ASTContext &C, /// invoking it directly; see the new operator for more details. This operator /// is called implicitly by the compiler if a placement new expression using the /// ASTContext throws in the object constructor. -inline void operator delete(void *Ptr, const flang::ASTContext &C, size_t) +inline void operator delete(void *Ptr, const flang::ASTContext &C, size_t size) throw () { - C.Deallocate(Ptr); + C.Deallocate(Ptr, size); } /// This placement form of operator new[] uses the ASTContext's allocator for @@ -297,9 +297,9 @@ inline void *operator new[](size_t Bytes, const flang::ASTContext& C, /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the ASTContext throws in the object constructor. -inline void operator delete[](void *Ptr, const flang::ASTContext &C, size_t) +inline void operator delete[](void *Ptr, const flang::ASTContext &C, size_t size) throw () { - C.Deallocate(Ptr); + C.Deallocate(Ptr, size); } #endif diff --git a/include/flang/AST/Decl.h b/include/flang/AST/Decl.h index a3248e3dc4..230968542a 100644 --- a/include/flang/AST/Decl.h +++ b/include/flang/AST/Decl.h @@ -1035,7 +1035,7 @@ static inline llvm::raw_ostream &operator<<(llvm::raw_ostream &O, // Specialization selected when ToTy is not a known subclass of DeclContext. template <class ToTy, - bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> + bool IsKnownSubtype = ::std::is_base_of< DeclContext, ToTy>::value> struct cast_convert_decl_context { static const ToTy *doit(const DeclContext *Val) { return static_cast<const ToTy*>(Decl::castFromDeclContext(Val)); diff --git a/include/flang/Basic/TargetOptions.h b/include/flang/Basic/TargetOptions.h new file mode 100644 index 0000000000..6b06e9b5b5 --- /dev/null +++ b/include/flang/Basic/TargetOptions.h @@ -0,0 +1,55 @@ +//===--- TargetOptions.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the flang::TargetOptions class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_TARGETOPTIONS_H +#define LLVM_FLANG_FRONTEND_TARGETOPTIONS_H + +#include "flang/Basic/LLVM.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <string> +#include <vector> + +namespace flang { + +/// \brief Options for controlling the target. +class TargetOptions : public llvm::RefCountedBase<TargetOptions> { +public: + /// If given, the name of the target triple to compile for. If not given the + /// target will be selected to match the host. + std::string Triple; + + /// If given, the name of the target CPU to generate code for. + std::string CPU; + + /// If given, the name of the target ABI to use. + std::string ABI; + + /// If given, the name of the target C++ ABI to use. If not given, defaults + /// to "itanium". + std::string CXXABI; + + /// If given, the version string of the linker in use. + std::string LinkerVersion; + + /// \brief The list of target specific features to enable or disable, as written on the command line. + std::vector<std::string> FeaturesAsWritten; + + /// The list of target specific features to enable or disable -- this should + /// be a list of strings starting with by '+' or '-'. + std::vector<std::string> Features; +}; + +} // end namespace clang + +#endif diff --git a/include/flang/CodeGen/BackendUtil.h b/include/flang/CodeGen/BackendUtil.h new file mode 100644 index 0000000000..3daac9f40c --- /dev/null +++ b/include/flang/CodeGen/BackendUtil.h @@ -0,0 +1,40 @@ +//===--- BackendUtil.h - LLVM Backend Utilities -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_CODEGEN_BACKEND_UTIL_H +#define LLVM_FLANG_CODEGEN_BACKEND_UTIL_H + +#include "flang/Basic/LLVM.h" + +namespace llvm { + class Module; +} + +namespace flang { + class DiagnosticsEngine; + class CodeGenOptions; + class TargetOptions; + class LangOptions; + + enum BackendAction { + Backend_EmitAssembly, ///< Emit native assembly files + Backend_EmitBC, ///< Emit LLVM bitcode files + Backend_EmitLL, ///< Emit human-readable LLVM assembly + Backend_EmitNothing, ///< Don't emit anything (benchmarking mode) + Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything + Backend_EmitObj ///< Emit native object files + }; + + void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, const LangOptions &LOpts, + llvm::Module *M, + BackendAction Action, raw_ostream *OS); +} + +#endif diff --git a/include/flang/CodeGen/CodeGenAction.h b/include/flang/CodeGen/CodeGenAction.h new file mode 100644 index 0000000000..2951ac8429 --- /dev/null +++ b/include/flang/CodeGen/CodeGenAction.h @@ -0,0 +1,102 @@ +//===--- CodeGenAction.h - LLVM Code Generation Frontend Action -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_CODEGEN_CODE_GEN_ACTION_H +#define LLVM_FLANG_CODEGEN_CODE_GEN_ACTION_H + +#include "flang/Frontend/FrontendAction.h" + +namespace llvm { + class LLVMContext; + class Module; +} + +namespace flang { +class BackendConsumer; + +class CodeGenAction : public ASTFrontendAction { +private: + unsigned Act; + std::unique_ptr<llvm::Module> TheModule; + llvm::Module *LinkModule; + llvm::LLVMContext *VMContext; + bool OwnsVMContext; + +protected: + /// Create a new code generation action. If the optional \p _VMContext + /// parameter is supplied, the action uses it without taking ownership, + /// otherwise it creates a fresh LLVM context and takes ownership. + CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = 0); + + virtual bool hasIRSupport() const; + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + + virtual void ExecuteAction(); + + virtual void EndSourceFileAction(); + +public: + ~CodeGenAction(); + + /// setLinkModule - Set the link module to be used by this action. If a link + /// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty, + /// the action will load it from the specified file. + void setLinkModule(llvm::Module *Mod) { LinkModule = Mod; } + + /// takeModule - Take the generated LLVM module, for use after the action has + /// been run. The result may be null on failure. + llvm::Module *takeModule(); + + /// Take the LLVM context used by this action. + llvm::LLVMContext *takeLLVMContext(); + + BackendConsumer *BEConsumer; +}; + +class EmitAssemblyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0); +}; + +class EmitBCAction : public CodeGenAction { + virtual void anchor(); +public: + EmitBCAction(llvm::LLVMContext *_VMContext = 0); +}; + +class EmitLLVMAction : public CodeGenAction { + virtual void anchor(); +public: + EmitLLVMAction(llvm::LLVMContext *_VMContext = 0); +}; + +class EmitLLVMOnlyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0); +}; + +class EmitCodeGenOnlyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0); +}; + +class EmitObjAction : public CodeGenAction { + virtual void anchor(); +public: + EmitObjAction(llvm::LLVMContext *_VMContext = 0); +}; + +} + +#endif diff --git a/include/flang/CodeGen/ModuleBuilder.h b/include/flang/CodeGen/ModuleBuilder.h new file mode 100644 index 0000000000..b3de50e442 --- /dev/null +++ b/include/flang/CodeGen/ModuleBuilder.h @@ -0,0 +1,48 @@ +//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ModuleBuilder interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_CODEGEN_MODULEBUILDER_H +#define LLVM_FLANG_CODEGEN_MODULEBUILDER_H + +#include "flang/AST/ASTConsumer.h" +#include "flang/Basic/TargetOptions.h" +#include "flang/Frontend/CodeGenOptions.h" +#include <string> + +namespace llvm { + class LLVMContext; + class Module; +} + +namespace flang { + class DiagnosticsEngine; + class LangOptions; + + class CodeGenerator : public ASTConsumer { + virtual void anchor(); + public: + virtual llvm::Module* GetModule() = 0; + virtual llvm::Module* ReleaseModule() = 0; + }; + + /// CreateLLVMCodeGen - Create a CodeGenerator instance. + /// It is the responsibility of the caller to call delete on + /// the allocated CodeGenerator instance. + CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, + const std::string &ModuleName, + const CodeGenOptions &CGO, + const TargetOptions &TO, + llvm::LLVMContext& C); +} + +#endif diff --git a/include/flang/Frontend/ASTUnit.h b/include/flang/Frontend/ASTUnit.h new file mode 100644 index 0000000000..31ab83d522 --- /dev/null +++ b/include/flang/Frontend/ASTUnit.h @@ -0,0 +1,198 @@ +//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ASTUnit utility class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_ASTUNIT_H +#define LLVM_FLANG_FRONTEND_ASTUNIT_H + +#include "flang/AST/ASTContext.h" +#include "flang/AST/ASTConsumer.h" +#include "flang/Basic/LangOptions.h" +#include "flang/Basic/TargetOptions.h" +#include "flang/Sema/Sema.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Path.h" +#include <cassert> +#include <map> +#include <string> +#include <sys/types.h> +#include <utility> +#include <vector> + +namespace llvm { + class MemoryBuffer; +} + +namespace flang { +class ASTContext; +class ASTReader; +class CodeCompleteConsumer; +class CompilerInvocation; +class CompilerInstance; +class Decl; +class DiagnosticsEngine; +class FileEntry; +class FileManager; +class HeaderSearch; +class Preprocessor; +class SourceManager; +class TargetInfo; +class ASTFrontendAction; +class ASTDeserializationListener; + +/// \brief Utility class for loading a ASTContext from an AST file. +/// +class ASTUnit { +private: + llvm::IntrusiveRefCntPtr<LangOptions> LangOpts; + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + llvm::IntrusiveRefCntPtr<TargetInfo> Target; + llvm::IntrusiveRefCntPtr<ASTContext> Ctx; + llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts; + + /// \brief The AST consumer that received information about the translation + /// unit as it was parsed or loaded. + std::unique_ptr<ASTConsumer> Consumer; + + /// \brief The semantic analysis object used to type-check the translation + /// unit. + std::unique_ptr<Sema> TheSema; + + /// Optional owned invocation, just used to make the invocation used in + /// LoadFromCommandLine available. + llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; + + /// The name of the original source file used to generate this ASTUnit. + std::string OriginalSourceFile; + + + /// \brief The language options used when we load an AST file. + LangOptions ASTFileLangOpts; + + ASTUnit(const ASTUnit &) LLVM_DELETED_FUNCTION; + void operator=(const ASTUnit &) LLVM_DELETED_FUNCTION; + + explicit ASTUnit(bool MainFileIsAST); + + void CleanTemporaryFiles(); + bool Parse(llvm::MemoryBuffer *OverrideMainBuffer); + + /// \brief Transfers ownership of the objects (like SourceManager) from + /// \param CI to this ASTUnit. + void transferASTDataFromCompilerInstance(CompilerInstance &CI); + +public: + + ~ASTUnit(); + + const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; } + DiagnosticsEngine &getDiagnostics() { return *Diagnostics; } + + + const ASTContext &getASTContext() const { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } + + void setASTContext(ASTContext *ctx) { Ctx = ctx; } + + bool hasSema() const { return TheSema.get() != nullptr; } + Sema &getSema() const { + assert(TheSema && "ASTUnit does not have a Sema object!"); + return *TheSema; + } + + StringRef getOriginalSourceFileName() { + return OriginalSourceFile; + } + + + /// \brief Get the source location for the given file:line:col triplet. + /// + /// The difference with SourceManager::getLocation is that this method checks + /// whether the requested location points inside the precompiled preamble + /// in which case the returned source location will be a "loaded" one. + SourceLocation getLocation(const FileEntry *File, + unsigned Line, unsigned Col) const; + + /// \brief Get the source location for the given file:offset pair. + SourceLocation getLocation(const FileEntry *File, unsigned Offset) const; + + + llvm::MemoryBuffer *getBufferForFile(StringRef Filename, + std::string *ErrorStr = 0); + + /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. + static ASTUnit *create(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags); + +public: + + /// \brief Create an ASTUnit from a source file, via a CompilerInvocation + /// object, by invoking the optionally provided ASTFrontendAction. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \param Action - The ASTFrontendAction to invoke. Its ownership is not + /// transfered. + /// + /// \param Unit - optionally an already created ASTUnit. Its ownership is not + /// transfered. + /// + /// \param Persistent - if true the returned ASTUnit will be complete. + /// false means the caller is only interested in getting info through the + /// provided \see Action. + /// + /// \param ErrAST - If non-null and parsing failed without any AST to return + /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit + /// mainly to allow the caller to see the diagnostics. + /// This will only receive an ASTUnit if a new one was created. If an already + /// created ASTUnit was passed in \p Unit then the caller can check that. + /// + static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + ASTFrontendAction *Action = 0, + ASTUnit *Unit = 0, + bool Persistent = true, + StringRef ResourceFilesPath = StringRef(), + bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false, + std::unique_ptr<ASTUnit> *ErrAST = 0); + + /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a + /// CompilerInvocation object. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + // + // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we + // shouldn't need to specify them at construction time. + static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags); + + +}; + +} // namespace clang + +#endif diff --git a/include/flang/Frontend/CodeGenOptions.def b/include/flang/Frontend/CodeGenOptions.def new file mode 100644 index 0000000000..80046620f6 --- /dev/null +++ b/include/flang/Frontend/CodeGenOptions.def @@ -0,0 +1,157 @@ +//===--- CodeGenOptions.def - Code generation option database ------ C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the code generation options. Users of this file +// must define the CODEGENOPT macro to make use of this information. +// Optionally, the user may also define ENUM_CODEGENOPT (for options +// that have enumeration type and VALUE_CODEGENOPT is a code +// generation option that describes a value rather than a flag. +// +//===----------------------------------------------------------------------===// +#ifndef CODEGENOPT +# error Define the CODEGENOPT macro to handle language options +#endif + +#ifndef VALUE_CODEGENOPT +# define VALUE_CODEGENOPT(Name, Bits, Default) \ +CODEGENOPT(Name, Bits, Default) +#endif + +#ifndef ENUM_CODEGENOPT +# define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ +CODEGENOPT(Name, Bits, Default) +#endif + +CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink +CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. +CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. +CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. +CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files. +CODEGENOPT(CUDAIsDevice , 1, 0) ///< Set when compiling for CUDA device. +CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. +CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker + ///< aliases to base ctors when possible. +CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled. +CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled. +CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. +CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing. +CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in + ///< getting .bc files that correspond to the + ///< internal state before optimizations are + ///< done. +CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. +CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. +CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what + ///< Decl* various IR entities came from. + ///< Only useful when running CodeGen as a + ///< subroutine. +CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. +CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. +CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. +/// \brief FP_CONTRACT mode (on/off/fast). +ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) +CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables + ///< are required. +CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. +CODEGENOPT(HiddenWeakVTables , 1, 0) ///< Emit weak vtables, RTTI, and thunks with + ///< hidden visibility. +CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is + ///< enabled. +CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. +CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to + ///< be generated. +CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. +CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. +CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enabled. +CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is + ///< enabled. +CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. +CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. +CODEGENOPT(NoGlobalMerge , 1, 0) ///< Set when -mno-global-merge is enabled. +CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. +CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. +CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled. + ///< Disables use of the inline keyword. +CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. +CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss. +/// \brief Method of Objective-C dispatch to use. +ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) +CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is + ///< enabled. +VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. +VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. + + /// If -fpcc-struct-return or -freg-struct-return is specified. +ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + +CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. +CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. +CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. +CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero + ///< offset in AddressSanitizer. +CODEGENOPT(SanitizeMemoryTrackOrigins, 1, 0) ///< Enable tracking origins in + ///< MemorySanitizer +CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on + /// -fsanitize-undefined-trap-on-error +CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. +CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. +CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. +CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization + ///< selection. +CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled. +CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. +CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. +CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer. +CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. +CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. + + /// Attempt to use register sized accesses to bit-fields in structures, when + /// possible. +CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) + +CODEGENOPT(VerifyModule , 1, 1) ///< Control whether the module should be run + ///< through the LLVM Verifier. + +CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to permit stack + ///< realignment. +CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or + ///< .ctors. +VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack + ///< alignment, if not 0. +CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information + ///< in debug info. + +/// The user specified number of registers to be used for integral arguments, +/// or 0 if unspecified. +VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) + +/// The lower bound for a buffer to be considered for stack protection. +VALUE_CODEGENOPT(SSPBufferSize, 32, 0) + +/// The kind of generated debug info. +ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 2, NoDebugInfo) + +/// Dwarf version. +VALUE_CODEGENOPT(DwarfVersion, 3, 0) + +/// The kind of inlining to perform. +ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining) + +/// The default TLS model to use. +ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) + +CODEGENOPT(SanitizeRecover, 1, 1) ///< Attempt to recover from sanitizer checks + ///< by continuing execution when possible + +#undef CODEGENOPT +#undef ENUM_CODEGENOPT +#undef VALUE_CODEGENOPT + diff --git a/include/flang/Frontend/CodeGenOptions.h b/include/flang/Frontend/CodeGenOptions.h new file mode 100644 index 0000000000..6aae15b4c8 --- /dev/null +++ b/include/flang/Frontend/CodeGenOptions.h @@ -0,0 +1,153 @@ +//===--- CodeGenOptions.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CodeGenOptions interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_CODEGENOPTIONS_H +#define LLVM_FLANG_FRONTEND_CODEGENOPTIONS_H + +#include <string> +#include <vector> +#include <string.h> + +namespace flang { + +/// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure +/// that this large collection of bitfields is a trivial class type. +class CodeGenOptionsBase { +public: +#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits; +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) +#include "flang/Frontend/CodeGenOptions.def" + +protected: +#define CODEGENOPT(Name, Bits, Default) +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) unsigned Name : Bits; +#include "flang/Frontend/CodeGenOptions.def" +}; + +/// CodeGenOptions - Track various options which control how the code +/// is optimized and passed to the backend. +class CodeGenOptions : public CodeGenOptionsBase { +public: + enum InliningMethod { + NoInlining, // Perform no inlining whatsoever. + NormalInlining, // Use the standard function inlining pass. + OnlyAlwaysInlining // Only run the always inlining pass. + }; + + enum ObjCDispatchMethodKind { + Legacy = 0, + NonLegacy = 1, + Mixed = 2 + }; + + enum DebugInfoKind { + NoDebugInfo, // Don't generate debug info. + DebugLineTablesOnly, // Emit only debug info necessary for generating + // line number tables (-gline-tables-only). + LimitedDebugInfo, // Limit generated debug info to reduce size + // (-flimit-debug-info). + FullDebugInfo // Generate complete debug info. + }; + + enum TLSModel { + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + + enum FPContractModeKind { + FPC_Off, // Form fused FP ops only where result will not be affected. + FPC_On, // Form fused FP ops according to FP_CONTRACT rules. + FPC_Fast // Aggressively fuse FP ops (E.g. FMA). + }; + + enum StructReturnConventionKind { + SRCK_Default, // No special option was passed. + SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return). + SRCK_InRegs // Small structs in registers (-freg-struct-return). + }; + + /// The code model to use (-mcmodel). + std::string CodeModel; + + /// The filename with path we use for coverage files. The extension will be + /// replaced. + std::string CoverageFile; + + /// The version string to put into coverage files. + char CoverageVersion[4]; + + /// Enable additional debugging information. + std::string DebugPass; + + /// The string to embed in debug information as the current working directory. + std::string DebugCompilationDir; + + /// The string to embed in the debug information for the compile unit, if + /// non-empty. + std::string DwarfDebugFlags; + + /// The ABI to use for passing floating point arguments. + std::string FloatABI; + + /// The float precision limit to use, if non-empty. + std::string LimitFloatPrecision; + + /// The name of the bitcode file to link before optzns. + std::string LinkBitcodeFile; + + /// The user provided name for the "main file", if non-empty. This is useful + /// in situations where the input file name does not match the original input + /// file, for example with -save-temps. + std::string MainFileName; + + /// The name for the split debug info file that we'll break out. This is used + /// in the backend for setting the name in the skeleton cu. + std::string SplitDwarfFile; + + /// The name of the relocation model to use. + std::string RelocationModel; + + /// Path to blacklist file for sanitizers. + std::string SanitizerBlacklistFile; + + /// If not an empty string, trap intrinsics are lowered to calls to this + /// function instead of to trap instructions. + std::string TrapFuncName; + + /// A list of command-line options to forward to the LLVM backend. + std::vector<std::string> BackendOptions; + +public: + // Define accessors/mutators for code generation options of enumeration type. +#define CODEGENOPT(Name, Bits, Default) +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ + Type get##Name() const { return static_cast<Type>(Name); } \ + void set##Name(Type Value) { Name = static_cast<unsigned>(Value); } +#include "flang/Frontend/CodeGenOptions.def" + + CodeGenOptions() { +#define CODEGENOPT(Name, Bits, Default) Name = Default; +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ + set##Name(Default); +#include "flang/Frontend/CodeGenOptions.def" + + RelocationModel = "pic"; + memcpy(CoverageVersion, "402*", 4); + } +}; + +} // end namespace flang + +#endif diff --git a/include/flang/Frontend/CommandLineSourceLoc.h b/include/flang/Frontend/CommandLineSourceLoc.h new file mode 100644 index 0000000000..8dfc50b8b7 --- /dev/null +++ b/include/flang/Frontend/CommandLineSourceLoc.h @@ -0,0 +1,87 @@ + +//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Command line parsing for source locations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_COMMANDLINESOURCELOC_H +#define LLVM_FLANG_FRONTEND_COMMANDLINESOURCELOC_H + +#include "flang/Basic/LLVM.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +namespace flang { + +/// \brief A source location that has been parsed on the command line. +struct ParsedSourceLocation { + std::string FileName; + unsigned Line; + unsigned Column; + +public: + /// Construct a parsed source location from a string; the Filename is empty on + /// error. + static ParsedSourceLocation FromString(StringRef Str) { + ParsedSourceLocation PSL; + std::pair<StringRef, StringRef> ColSplit = Str.rsplit(':'); + std::pair<StringRef, StringRef> LineSplit = + ColSplit.first.rsplit(':'); + + // If both tail splits were valid integers, return success. + if (!ColSplit.second.getAsInteger(10, PSL.Column) && + !LineSplit.second.getAsInteger(10, PSL.Line)) { + PSL.FileName = LineSplit.first; + + // On the command-line, stdin may be specified via "-". Inside the + // compiler, stdin is called "<stdin>". + if (PSL.FileName == "-") + PSL.FileName = "<stdin>"; + } + + return PSL; + } +}; + +} + +namespace llvm { + namespace cl { + /// \brief Command-line option parser that parses source locations. + /// + /// Source locations are of the form filename:line:column. + template<> + class parser<flang::ParsedSourceLocation> + : public basic_parser<flang::ParsedSourceLocation> { + public: + inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue, + flang::ParsedSourceLocation &Val); + }; + + bool + parser<flang::ParsedSourceLocation>:: + parse(Option &O, StringRef ArgName, StringRef ArgValue, + flang::ParsedSourceLocation &Val) { + using namespace flang; + + Val = ParsedSourceLocation::FromString(ArgValue); + if (Val.FileName.empty()) { + errs() << "error: " + << "source location must be of the form filename:line:column\n"; + return true; + } + + return false; + } + } +} + +#endif diff --git a/include/flang/Frontend/CompilerInstance.h b/include/flang/Frontend/CompilerInstance.h new file mode 100644 index 0000000000..948e8b336e --- /dev/null +++ b/include/flang/Frontend/CompilerInstance.h @@ -0,0 +1,528 @@ +//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_COMPILERINSTANCE_H_ +#define LLVM_FLANG_FRONTEND_COMPILERINSTANCE_H_ + +#include "flang/Basic/Diagnostic.h" +#include "flang/Frontend/CompilerInvocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SourceMgr.h" +#include <cassert> +#include <list> +#include <string> +#include <utility> + +namespace llvm { +class raw_fd_ostream; +class Timer; +} + +namespace flang { +class ASTContext; +class ASTConsumer; +class ASTReader; +class CodeCompleteConsumer; +class DiagnosticsEngine; +class DiagnosticClient; +class ExternalASTSource; +class FileEntry; +class FrontendAction; +class Module; +class Preprocessor; +class Sema; +class TargetInfo; + +/// CompilerInstance - Helper class for managing a single instance of the Clang +/// compiler. +/// +/// The CompilerInstance serves two purposes: +/// (1) It manages the various objects which are necessary to run the compiler, +/// for example the preprocessor, the target information, and the AST +/// context. +/// (2) It provides utility routines for constructing and manipulating the +/// common Clang objects. +/// +/// The compiler instance generally owns the instance of all the objects that it +/// manages. However, clients can still share objects by manually setting the +/// object and retaking ownership prior to destroying the CompilerInstance. +/// +/// The compiler instance is intended to simplify clients, but not to lock them +/// in to the compiler instance for everything. When possible, utility functions +/// come in two forms; a short form that reuses the CompilerInstance objects, +/// and a long form that takes explicit instances of any required objects. +class CompilerInstance { + /// The options used in this compiler instance. + llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; + + /// The diagnostics engine instance. + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + + /// The target being compiled for. + llvm::IntrusiveRefCntPtr<TargetInfo> Target; + + /// The source manager. + llvm::IntrusiveRefCntPtr<llvm::SourceMgr> SourceMgr; + + /// The preprocessor. + llvm::IntrusiveRefCntPtr<Preprocessor> PP; + + /// The AST context. + llvm::IntrusiveRefCntPtr<ASTContext> Context; + + /// The AST consumer. + std::unique_ptr<ASTConsumer> Consumer; + + /// The code completion consumer. + std::unique_ptr<CodeCompleteConsumer> CompletionConsumer; + + /// \brief The semantic analysis object. + std::unique_ptr<Sema> TheSema; + + /// \brief The frontend timer + std::unique_ptr<llvm::Timer> FrontendTimer; + + /// \brief Non-owning reference to the ASTReader, if one exists. + ASTReader *ModuleManager; + + /// \brief The set of top-level modules that has already been loaded, + /// along with the module map + llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules; + + /// \brief The location of the module-import keyword for the last module + /// import. + SourceLocation LastModuleImportLoc; + + /// \brief Whether we should (re)build the global module index once we + /// have finished with this translation unit. + bool BuildGlobalModuleIndex; + + /// \brief One or more modules failed to build. + bool ModuleBuildFailed; + + /// \brief Holds information about the output file. + /// + /// If TempFilename is not empty we must rename it to Filename at the end. + /// TempFilename may be empty and Filename non empty if creating the temporary + /// failed. + struct OutputFile { + std::string Filename; + std::string TempFilename; + raw_ostream *OS; + + OutputFile(const std::string &filename, const std::string &tempFilename, + raw_ostream *os) + : Filename(filename), TempFilename(tempFilename), OS(os) { } + }; + + /// The list of active output files. + std::list<OutputFile> OutputFiles; + + CompilerInstance(const CompilerInstance &) LLVM_DELETED_FUNCTION; + void operator=(const CompilerInstance &) LLVM_DELETED_FUNCTION; +public: + CompilerInstance(); + ~CompilerInstance(); + + /// @name High-Level Operations + /// { + + /// ExecuteAction - Execute the provided action against the compiler's + /// CompilerInvocation object. + /// + /// This function makes the following assumptions: + /// + /// - The invocation options should be initialized. This function does not + /// handle the '-help' or '-version' options, clients should handle those + /// directly. + /// + /// - The diagnostics engine should have already been created by the client. + /// + /// - No other CompilerInstance state should have been initialized (this is + /// an unchecked error). + /// + /// - Clients should have initialized any LLVM target features that may be + /// required. + /// + /// - Clients should eventually call llvm_shutdown() upon the completion of + /// this routine to ensure that any managed objects are properly destroyed. + /// + /// Note that this routine may write output to 'stderr'. + /// + /// \param Act - The action to execute. + /// \return - True on success. + // + // FIXME: This function should take the stream to write any debugging / + // verbose output to as an argument. + // + // FIXME: Eliminate the llvm_shutdown requirement, that should either be part + // of the context or else not CompilerInstance specific. + bool ExecuteAction(FrontendAction &Act); + + /// } + /// @name Compiler Invocation and Options + /// { + + bool hasInvocation() const { return Invocation != 0; } + + CompilerInvocation &getInvocation() { + assert(Invocation && "Compiler instance has no invocation!"); + return *Invocation; + } + + /// setInvocation - Replace the current invocation. + void setInvocation(CompilerInvocation *Value); + + /// \brief Indicates whether we should (re)build the global module index. + bool shouldBuildGlobalModuleIndex() const; + + /// \brief Set the flag indicating whether we should (re)build the global + /// module index. + void setBuildGlobalModuleIndex(bool Build) { + BuildGlobalModuleIndex = Build; + } + + /// } + /// @name Forwarding Methods + /// { + + CodeGenOptions &getCodeGenOpts() { + return Invocation->getCodeGenOpts(); + } + const CodeGenOptions &getCodeGenOpts() const { + return Invocation->getCodeGenOpts(); + } + + FrontendOptions &getFrontendOpts() { + return Invocation->getFrontendOpts(); + } + const FrontendOptions &getFrontendOpts() const { + return Invocation->getFrontendOpts(); + } + + LangOptions &getLangOpts() { + return *Invocation->getLangOpts(); + } + const LangOptions &getLangOpts() const { + return *Invocation->getLangOpts(); + } + + TargetOptions &getTargetOpts() { + return Invocation->getTargetOpts(); + } + const TargetOptions &getTargetOpts() const { + return Invocation->getTargetOpts(); + } + + /// } + /// @name Diagnostics Engine + /// { + + bool hasDiagnostics() const { return Diagnostics != 0; } + + /// Get the current diagnostics engine. + DiagnosticsEngine &getDiagnostics() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return *Diagnostics; + } + + /// setDiagnostics - Replace the current diagnostics engine. + void setDiagnostics(DiagnosticsEngine *Value); + + DiagnosticClient &getDiagnosticConsumer() const { + assert(Diagnostics && Diagnostics->getClient() && + "Compiler instance has no diagnostic client!"); + return *Diagnostics->getClient(); + } + + /// } + /// @name Target Info + /// { + + bool hasTarget() const { return Target != 0; } + + TargetInfo &getTarget() const { + assert(Target && "Compiler instance has no target!"); + return *Target; + } + + /// Replace the current diagnostics engine. + void setTarget(TargetInfo *Value); + + /// } + /// @name Source Manager + /// { + + bool hasSourceManager() const { return SourceMgr != 0; } + + /// Return the current source manager. + llvm::SourceMgr &getSourceManager() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return *SourceMgr; + } + + void resetAndLeakSourceManager() { + SourceMgr.resetWithoutRelease(); + } + + /// setSourceManager - Replace the current source manager. + void setSourceManager(llvm::SourceMgr *Value); + + /// } + /// @name Preprocessor + /// { + + bool hasPreprocessor() const { return PP != 0; } + + /// Return the current preprocessor. + Preprocessor &getPreprocessor() const { + assert(PP && "Compiler instance has no preprocessor!"); + return *PP; + } + + void resetAndLeakPreprocessor() { + PP.resetWithoutRelease(); + } + + /// Replace the current preprocessor. + void setPreprocessor(Preprocessor *Value); + + /// } + /// @name ASTContext + /// { + + bool hasASTContext() const { return Context != 0; } + + ASTContext &getASTContext() const { + assert(Context && "Compiler instance has no AST context!"); + return *Context; + } + + void resetAndLeakASTContext() { + Context.resetWithoutRelease(); + } + + /// setASTContext - Replace the current AST context. + void setASTContext(ASTContext *Value); + + /// \brief Replace the current Sema; the compiler instance takes ownership + /// of S. + void setSema(Sema *S); + + /// } + /// @name ASTConsumer + /// { + + bool hasASTConsumer() const { return Consumer.get() != nullptr; } + + ASTConsumer &getASTConsumer() const { + assert(Consumer && "Compiler instance has no AST consumer!"); + return *Consumer; + } + + /// takeASTConsumer - Remove the current AST consumer and give ownership to + /// the caller. + ASTConsumer *takeASTConsumer() { return Consumer.release(); } + + /// setASTConsumer - Replace the current AST consumer; the compiler instance + /// takes ownership of \p Value. + void setASTConsumer(ASTConsumer *Value); + + /// } + /// @name Semantic analysis + /// { + bool hasSema() const { return TheSema.get() != nullptr; } + + Sema &getSema() const { + assert(TheSema && "Compiler instance has no Sema object!"); + return *TheSema; + } + + Sema *takeSema() { return TheSema.release(); } + + /// } + /// @name Module Management + /// { + + ASTReader *getModuleManager() const { return ModuleManager; } + void setModuleManager(ASTReader *Reader) { ModuleManager = Reader; } + + /// } + /// @name Frontend timer + /// { + + bool hasFrontendTimer() const { return FrontendTimer.get() != nullptr; } + + llvm::Timer &getFrontendTimer() const { + assert(FrontendTimer && "Compiler instance has no frontend timer!"); + return *FrontendTimer; + } + + /// } + /// @name Output Files + /// { + + /// addOutputFile - Add an output file onto the list of tracked output files. + /// + /// \param OutFile - The output file info. + void addOutputFile(const OutputFile &OutFile); + + /// clearOutputFiles - Clear the output file list, destroying the contained + /// output streams. + /// + /// \param EraseFiles - If true, attempt to erase the files from disk. + void clearOutputFiles(bool EraseFiles); + + /// } + /// @name Construction Utility Methods + /// { + + /// Create the diagnostics engine using the invocation's diagnostic options + /// and replace any existing one with it. + /// + /// Note that this routine also replaces the diagnostic client, + /// allocating one if one is not provided. + /// + /// \param Client If non-NULL, a diagnostic client that will be + /// attached to (and, then, owned by) the DiagnosticsEngine inside this AST + /// unit. + /// + /// \param ShouldOwnClient If Client is non-NULL, specifies whether + /// the diagnostic object should take ownership of the client. + void createDiagnostics(DiagnosticClient *Client = 0, + bool ShouldOwnClient = true); + + /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. + /// + /// If no diagnostic client is provided, this creates a + /// DiagnosticConsumer that is owned by the returned diagnostic + /// object, if using directly the caller is responsible for + /// releasing the returned DiagnosticsEngine's client eventually. + /// + /// \param Opts - The diagnostic options; note that the created text + /// diagnostic object contains a reference to these options. + /// + /// \param Client If non-NULL, a diagnostic client that will be + /// attached to (and, then, owned by) the returned DiagnosticsEngine + /// object. + /// + /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be + /// used by some diagnostics printers (for logging purposes only). + /// + /// \return The new object on success, or null on failure. + static llvm::IntrusiveRefCntPtr<DiagnosticsEngine> + createDiagnostics(DiagnosticOptions *Opts, + DiagnosticClient *Client = 0, + bool ShouldOwnClient = true, + const CodeGenOptions *CodeGenOpts = 0); + + /// Create the source manager and replace any existing one with it. + void createSourceManager(); + + /// Create the preprocessor, using the invocation, file, and source managers, + /// and replace any existing one with it. + void createPreprocessor(); + + /// Create the AST context. + void createASTContext(); + + /// \brief Create the Sema object to be used for parsing. + void createSema(); + + /// Create the frontend timer and replace any existing one with it. + void createFrontendTimer(); + + /// Create the default output file (from the invocation's options) and add it + /// to the list of tracked output files. + /// + /// The files created by this function always use temporary files to write to + /// their result (that is, the data is written to a temporary file which will + /// atomically replace the target output on success). + /// + /// \return - Null on error. + llvm::raw_fd_ostream * + 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); + + /// Create a new output file, optionally deriving the output path name. + /// + /// If \p OutputPath is empty, then createOutputFile will derive an output + /// path location as \p BaseInput, with any suffix removed, and \p Extension + /// appended. If \p OutputPath is not stdout and \p UseTemporary + /// is true, createOutputFile will create a new temporary file that must be + /// renamed to \p OutputPath in the end. + /// + /// \param OutputPath - If given, the path to the output file. + /// \param Error [out] - On failure, the error message. + /// \param BaseInput - If \p OutputPath is empty, the input path name to use + /// for deriving the output path. + /// \param Extension - The extension to use for derived output names. + /// \param Binary - The mode to open the file in. + /// \param RemoveFileOnSignal - Whether the file should be registered with + /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for + /// multithreaded use, as the underlying signal mechanism is not reentrant + /// \param UseTemporary - Create a new temporary file that must be renamed to + /// OutputPath in the end. + /// \param CreateMissingDirectories - When \p UseTemporary is true, create + /// missing directories in the output path. + /// \param ResultPathName [out] - If given, the result path name will be + /// stored here on success. + /// \param TempPathName [out] - If given, the temporary file path name + /// will be stored here on success. + static llvm::raw_fd_ostream * + createOutputFile(StringRef OutputPath, std::string &Error, + bool Binary, bool RemoveFileOnSignal, + StringRef BaseInput, + StringRef Extension, + bool UseTemporary, + bool CreateMissingDirectories, + std::string *ResultPathName, + std::string *TempPathName); + + /// } + /// @name Initialization Utility Methods + /// { + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + bool InitializeSourceManager(const FrontendInputFile &Input); + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + static bool InitializeSourceManager(const FrontendInputFile &Input, + DiagnosticsEngine &Diags, + llvm::SourceMgr &SrcMgr, + const FrontendOptions &Opts); + + /// } + +}; + +} // end namespace flang + +#endif diff --git a/include/flang/Frontend/CompilerInvocation.h b/include/flang/Frontend/CompilerInvocation.h new file mode 100644 index 0000000000..56a028da36 --- /dev/null +++ b/include/flang/Frontend/CompilerInvocation.h @@ -0,0 +1,131 @@ +//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_COMPILERINVOCATION_H_ +#define LLVM_FLANG_FRONTEND_COMPILERINVOCATION_H_ + +#include "flang/Basic/LangOptions.h" +#include "flang/Basic/TargetOptions.h" +#include "flang/Frontend/CodeGenOptions.h" +#include "flang/Frontend/FrontendOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace llvm { +namespace opt { +class ArgList; +} +} + +namespace flang { +class CompilerInvocation; +class DiagnosticsEngine; +struct DiagnosticOptions {}; + +/// \brief Fill out Opts based on the options given in Args. +/// +/// Args must have been created from the OptTable returned by +/// createCC1OptTable(). +/// +/// When errors are encountered, return false and, if Diags is non-null, +/// report the error(s). +bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, + DiagnosticsEngine *Diags = 0); + +class CompilerInvocationBase : public llvm::RefCountedBase<CompilerInvocation> { +protected: + /// Options controlling the language variant. + llvm::IntrusiveRefCntPtr<LangOptions> LangOpts; + + /// Options controlling the target. + llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts; + +public: + CompilerInvocationBase(); + + CompilerInvocationBase(const CompilerInvocationBase &X); + + LangOptions *getLangOpts() { return LangOpts.get(); } + const LangOptions *getLangOpts() const { return LangOpts.get(); } + + TargetOptions &getTargetOpts() { return *TargetOpts.get(); } + const TargetOptions &getTargetOpts() const { + return *TargetOpts.get(); + } + +}; + +/// \brief Helper class for holding the data necessary to invoke the compiler. +/// +/// This class is designed to represent an abstract "invocation" of the +/// compiler, including data such as the include paths, the code generation +/// options, the warning flags, and so on. +class CompilerInvocation : public CompilerInvocationBase { + + /// Options controlling IRgen and the backend. + CodeGenOptions CodeGenOpts; + + /// Options controlling the frontend itself. + FrontendOptions FrontendOpts; + +public: + CompilerInvocation() {} + + /// @name Utility Methods + /// @{ + + /// \brief Create a compiler invocation from a list of input options. + /// \returns true on success. + /// + /// \param [out] Res - The resulting invocation. + /// \param ArgBegin - The first element in the argument vector. + /// \param ArgEnd - The last element in the argument vector. + /// \param Diags - The diagnostic engine to use for errors. + static bool CreateFromArgs(CompilerInvocation &Res, + const char* const *ArgBegin, + const char* const *ArgEnd, + DiagnosticsEngine &Diags); + + /// \brief Get the directory where the compiler headers + /// reside, relative to the compiler binary (found by the passed in + /// arguments). + /// + /// \param Argv0 - The program path (from argv[0]), for finding the builtin + /// compiler path. + /// \param MainAddr - The address of main (or some other function in the main + /// executable), for finding the builtin compiler path. + static std::string GetResourcesPath(const char *Argv0, void *MainAddr); + + /// \brief Retrieve a module hash string that is suitable for uniquely + /// identifying the conditions under which the module was built. + std::string getModuleHash() const; + + /// @} + /// @name Option Subgroups + /// @{ + + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } + const CodeGenOptions &getCodeGenOpts() const { + return CodeGenOpts; + } + + FrontendOptions &getFrontendOpts() { return FrontendOpts; } + const FrontendOptions &getFrontendOpts() const { + return FrontendOpts; + } + + /// @} +}; + +} // end namespace flang + +#endif diff --git a/include/flang/Frontend/FrontendAction.h b/include/flang/Frontend/FrontendAction.h new file mode 100644 index 0000000000..da23e6ddcf --- /dev/null +++ b/include/flang/Frontend/FrontendAction.h @@ -0,0 +1,191 @@ +//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the flang::FrontendAction interface and various convenience +/// abstract classes (flang::ASTFrontendAction, flang::PluginASTAction, +/// flang::PreprocessorFrontendAction, and flang::WrapperFrontendAction) +/// derived from it. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_FRONTENDACTION_H +#define LLVM_FLANG_FRONTEND_FRONTENDACTION_H + +#include "flang/Basic/LLVM.h" +#include "flang/Basic/LangOptions.h" +#include "flang/Frontend/ASTUnit.h" +#include "flang/Frontend/FrontendOptions.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace flang { +class ASTConsumer; +class CompilerInstance; + +/// Abstract base class for actions which can be performed by the frontend. +class FrontendAction { + std::unique_ptr<ASTUnit> CurrentASTUnit; + CompilerInstance *Instance; + +private: + ASTConsumer* CreateWrappedASTConsumer(CompilerInstance &CI, + StringRef InFile); + +protected: + /// @name Implementation Action Interface + /// @{ + + /// \brief Create the AST consumer object for this action, if supported. + /// + /// This routine is called as part of BeginSourceFile(), which will + /// fail if the AST consumer cannot be created. This will not be called if the + /// action has indicated that it only uses the preprocessor. + /// + /// \param CI - The current compiler instance, provided as a convenience, see + /// getCompilerInstance(). + /// + /// \param InFile - The current input file, provided as a convenience, see + /// getCurrentFile(). + /// + /// \return The new AST consumer, or null on failure. + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) = 0; + + /// \brief Callback before starting processing a single input, giving the + /// opportunity to modify the CompilerInvocation or do some other action + /// before BeginSourceFileAction is called. + /// + /// \return True on success; on failure BeginSourceFileAction(), + /// ExecuteAction() and EndSourceFileAction() will not be called. + virtual bool BeginInvocation(CompilerInstance &CI) { return true; } + + /// \brief Callback at the start of processing a single input. + /// + /// \return True on success; on failure ExecutionAction() and + /// EndSourceFileAction() will not be called. + virtual bool BeginSourceFileAction(CompilerInstance &CI, + StringRef Filename) { + return true; + } + + /// \brief Callback to run the program action, using the initialized + /// compiler instance. + /// + /// This is guaranteed to only be called between BeginSourceFileAction() + /// and EndSourceFileAction(). + virtual void ExecuteAction() = 0; + + /// \brief Callback at the end of processing a single input. + /// + /// This is guaranteed to only be called following a successful call to + /// BeginSourceFileAction (and BeginSourceFile). + virtual void EndSourceFileAction() {} + + /// \brief Callback at the end of processing a single input, to determine + /// if the output files should be erased or not. + /// + /// By default it returns true if a compiler error occurred. + /// This is guaranteed to only be called following a successful call to + /// BeginSourceFileAction (and BeginSourceFile). + virtual bool shouldEraseOutputFiles(); + + /// @} + +public: + FrontendAction(); + virtual ~FrontendAction(); + + /// @name Compiler Instance Access + /// @{ + + CompilerInstance &getCompilerInstance() const { + assert(Instance && "Compiler instance not registered!"); + return *Instance; + } + + void setCompilerInstance(CompilerInstance *Value) { Instance = Value; } + + /// @} + /// @name Current File Information + /// @{ + + bool isCurrentFileAST() const { + assert(CurrentASTUnit && "No current AST unit!"); + return CurrentASTUnit.get() != nullptr; + } + + const StringRef getCurrentFile() const { + CurrentASTUnit.get()->getOriginalSourceFileName(); + } + + InputKind getCurrentFileKind() const { + return IK_None; + } + + ASTUnit &getCurrentASTUnit() const { + assert(CurrentASTUnit && "No current AST unit!"); + return *CurrentASTUnit; + } + + ASTUnit *takeCurrentASTUnit() { + return CurrentASTUnit.release(); + } + + /// @} + /// @name Public Action Interface + /// @{ + + /// \brief Prepare the action for processing the input file \p Input. + /// + /// This is run after the options and frontend have been initialized, + /// but prior to executing any per-file processing. + /// + /// \param CI - The compiler instance this action is being run from. The + /// action may store and use this object up until the matching EndSourceFile + /// action. + /// + /// \param Input - The input filename and kind. Some input kinds are handled + /// specially, for example AST inputs, since the AST file itself contains + /// several objects which would normally be owned by the + /// CompilerInstance. When processing AST input files, these objects should + /// generally not be initialized in the CompilerInstance -- they will + /// automatically be shared with the AST file in between + /// BeginSourceFile() and EndSourceFile(). + /// + /// \return True on success; on failure the compilation of this file should + /// be aborted and neither Execute() nor EndSourceFile() should be called. + bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); + + /// \brief Set the source manager's main input file, and run the action. + bool Execute(); + + /// \brief Perform any per-file post processing, deallocate per-file + /// objects, and run statistics and output file cleanup code. + void EndSourceFile(); + + /// @} +}; + +/// \brief Abstract base class to use for AST consumer-based frontend actions. +class ASTFrontendAction : public FrontendAction { +protected: + /// \brief Implement the ExecuteAction interface by running Sema on + /// the already-initialized AST consumer. + /// + /// This will also take care of instantiating a code completion consumer if + /// the user requested it and the action supports it. + virtual void ExecuteAction(); + +}; + +} // end namespace flang + +#endif diff --git a/include/flang/Frontend/FrontendOptions.h b/include/flang/Frontend/FrontendOptions.h new file mode 100644 index 0000000000..81e3d69b62 --- /dev/null +++ b/include/flang/Frontend/FrontendOptions.h @@ -0,0 +1,234 @@ +//===--- FrontendOptions.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLANG_FRONTEND_FRONTENDOPTIONS_H +#define LLVM_FLANG_FRONTEND_FRONTENDOPTIONS_H + +#include "flang/Frontend/CommandLineSourceLoc.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace llvm { +class MemoryBuffer; +} + +namespace flang { + +namespace frontend { + enum ActionKind { + ASTDeclList, ///< Parse ASTs and list Decl nodes. + ASTDump, ///< Parse ASTs and dump them. + ASTDumpXML, ///< Parse ASTs and dump them in XML. + ASTPrint, ///< Parse ASTs and print them. + ASTView, ///< Parse ASTs and view them in Graphviz. + DumpRawTokens, ///< Dump out raw tokens. + DumpTokens, ///< Dump out preprocessed tokens. + EmitAssembly, ///< Emit a .s file. + EmitBC, ///< Emit a .bc file. + EmitHTML, ///< Translate input source into HTML. + EmitLLVM, ///< Emit a .ll file. + EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything. + EmitCodeGenOnly, ///< Generate machine code, but don't emit anything. + EmitObj, ///< Emit a .o file. + FixIt, ///< Parse and apply any fixits to the source. + GenerateModule, ///< Generate pre-compiled module. + GeneratePCH, ///< Generate pre-compiled header. + GeneratePTH, ///< Generate pre-tokenized header. + InitOnly, ///< Only execute frontend initialization. + ModuleFileInfo, ///< Dump information about a module file. + ParseSyntaxOnly, ///< Parse and perform semantic analysis. + PluginAction, ///< Run a plugin action, \see ActionName. + PrintDeclContext, ///< Print DeclContext and their Decls. + PrintPreamble, ///< Print the "preamble" of the input file + PrintPreprocessedInput, ///< -E mode. + RewriteMacros, ///< Expand macros but not \#includes. + RewriteObjC, ///< ObjC->C Rewriter. + RewriteTest, ///< Rewriter playground + RunAnalysis, ///< Run one or more source code analyses. + MigrateSource, ///< Run migrator. + RunPreprocessorOnly ///< Just lex, no output. + }; +} + +enum InputKind { + IK_None, + IK_Asm, + IK_C, + IK_CXX, + IK_ObjC, + IK_ObjCXX, + IK_PreprocessedC, + IK_PreprocessedCXX, + IK_PreprocessedObjC, + IK_PreprocessedObjCXX, + IK_OpenCL, + IK_CUDA, + IK_AST, + IK_LLVM_IR +}; + + +/// \brief An input file for the front end. +class FrontendInputFile { + /// \brief The file name, or "-" to read from standard input. + std::string File; + + llvm::MemoryBuffer *Buffer; + + /// \brief The kind of input, e.g., C source, AST file, LLVM IR. + InputKind Kind; + + /// \brief Whether we're dealing with a 'system' input (vs. a 'user' input). + bool IsSystem; + +public: + FrontendInputFile() : Buffer(0), Kind(IK_None) { } + FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) + : File(File.str()), Buffer(0), Kind(Kind), IsSystem(IsSystem) { } + FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind, + bool IsSystem = false) + : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { } + + InputKind getKind() const { return Kind; } + bool isSystem() const { return IsSystem; } + + bool isEmpty() const { return File.empty() && Buffer == 0; } + bool isFile() const { return !isBuffer(); } + bool isBuffer() const { return Buffer != 0; } + + StringRef getFile() const { + assert(isFile()); + return File; + } + llvm::MemoryBuffer *getBuffer() const { + assert(isBuffer()); + return Buffer; + } +}; + +/// FrontendOptions - Options for controlling the behavior of the frontend. +class FrontendOptions { +public: + unsigned DisableFree : 1; ///< Disable memory freeing on exit. + unsigned RelocatablePCH : 1; ///< When generating PCH files, + /// instruct the AST writer to create + /// relocatable PCH files. + unsigned ShowHelp : 1; ///< Show the -help text. + unsigned ShowStats : 1; ///< Show frontend performance + /// metrics and statistics. + unsigned ShowTimers : 1; ///< Show timers for individual + /// actions. + unsigned ShowVersion : 1; ///< Show the -version text. + unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are + /// unfixable errors. + unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings. + unsigned FixAndRecompile : 1; ///< Apply fixes and recompile. + unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files. + unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the + /// migrator can fix them + unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to + /// speed up parsing in cases you do + /// not need them (e.g. with code + /// completion). + unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the + ///< global module index if available. + unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the + ///< global module index if needed. + unsigned ASTDumpLookups : 1; ///< Whether we include lookup table + ///< dumps in AST dumps. + + enum { + ARCMT_None, + ARCMT_Check, + ARCMT_Modify, + ARCMT_Migrate + } ARCMTAction; + + enum { + ObjCMT_None = 0, + /// \brief Enable migration to modern ObjC literals. + ObjCMT_Literals = 0x1, + /// \brief Enable migration to modern ObjC subscripting. + ObjCMT_Subscripting = 0x2, + /// \brief Enable migration to modern ObjC property. + ObjCMT_Property = 0x4 + }; + unsigned ObjCMTAction; + + std::string MTMigrateDir; + std::string ARCMTMigrateReportOut; + + /// The input files and their types. + std::vector<FrontendInputFile> Inputs; + + /// The output file, if any. + std::string OutputFile; + + /// If given, the new suffix for fix-it rewritten files. + std::string FixItSuffix; + + /// If given, filter dumped AST Decl nodes by this substring. + std::string ASTDumpFilter; + + /// If given, enable code completion at the provided location. + ParsedSourceLocation CodeCompletionAt; + + /// The frontend action to perform. + frontend::ActionKind ProgramAction; + + /// The name of the action to run when using a plugin action. + std::string ActionName; + + /// Args to pass to the plugin + std::vector<std::string> PluginArgs; + + /// The list of plugin actions to run in addition to the normal action. + std::vector<std::string> AddPluginActions; + + /// Args to pass to the additional plugins + std::vector<std::vector<std::string> > AddPluginArgs; + + /// The list of plugins to load. + std::vector<std::string> Plugins; + + /// \brief The list of AST files to merge. + std::vector<std::string> ASTMergeFiles; + + /// \brief A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector<std::string> LLVMArgs; + + /// \brief File name of the file that will provide record layouts + /// (in the format produced by -fdump-record-layouts). + std::string OverrideRecordLayoutsFile; + +public: + FrontendOptions() : + DisableFree(false), RelocatablePCH(false), ShowHelp(false), + ShowStats(false), ShowTimers(false), ShowVersion(false), + FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), + FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), + SkipFunctionBodies(false), UseGlobalModuleIndex(true), + GenerateGlobalModuleIndex(true), ASTDumpLookups(false), + ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None), + ProgramAction(frontend::ParseSyntaxOnly) + {} + + /// getInputKindForExtension - Return the appropriate input kind for a file + /// extension. For example, "c" would return IK_C. + /// + /// \return The input kind for the extension, or IK_None if the extension is + /// not recognized. + static InputKind getInputKindForExtension(StringRef Extension); +}; + +} // end namespace flang + +#endif diff --git a/include/flang/Frontend/VerifyDiagnosticConsumer.h b/include/flang/Frontend/VerifyDiagnosticConsumer.h index e669198c8b..ec062870d2 100644 --- a/include/flang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/flang/Frontend/VerifyDiagnosticConsumer.h @@ -13,7 +13,6 @@ #include "flang/Basic/Diagnostic.h" #include "flang/Parse/Lexer.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include <climits> @@ -203,7 +202,7 @@ private: DiagnosticsEngine &Diags; DiagnosticClient *PrimaryClient; bool OwnsPrimaryClient; - llvm::OwningPtr<TextDiagnosticBuffer> Buffer; + std::unique_ptr<TextDiagnosticBuffer> Buffer; const Lexer *CurrentPreprocessor; const LangOptions *LangOpts; const llvm::SourceMgr *SrcManager; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 19c79ccd56..c21da7c4d0 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -19,7 +19,7 @@ namespace flang { void APNumericStorage::setIntValue(ASTContext &C, const APInt &Val) { if (hasAllocation()) - C.Deallocate(pVal); + C.Deallocate(pVal, sizeof(uint64_t[llvm::APInt::getNumWords(BitWidth)])); BitWidth = Val.getBitWidth(); unsigned NumWords = Val.getNumWords(); diff --git a/lib/Basic/Token.cpp b/lib/Basic/Token.cpp index 1ed0d0012c..104be84f0a 100644 --- a/lib/Basic/Token.cpp +++ b/lib/Basic/Token.cpp @@ -66,8 +66,8 @@ llvm::Twine Token::CleanCharContext() { if (*CurPtr != '\n' && *CurPtr != '\r') continue; - CharContext = CharContext + - llvm::Twine(llvm::StringRef(Start, Amp - Start)); + CharContext.concat( + llvm::Twine(llvm::StringRef(Start, Amp - Start))); while (true) { while (isHorizontalWhitespace(*CurPtr) || diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp new file mode 100644 index 0000000000..37569cf43e --- /dev/null +++ b/lib/CodeGen/BackendUtil.cpp @@ -0,0 +1,488 @@ +//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "flang/CodeGen/BackendUtil.h" +#include "flang/Basic/Diagnostic.h" +#include "flang/Basic/LangOptions.h" +#include "flang/Basic/TargetOptions.h" +#include "flang/Frontend/CodeGenOptions.h" +#include "flang/Frontend/FrontendDiagnostic.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/PassManager.h" +#include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/ObjCARC.h" +#include "llvm/Transforms/Scalar.h" +using namespace flang; +using namespace llvm; + +namespace { + +class EmitAssemblyHelper { + DiagnosticsEngine &Diags; + const CodeGenOptions &CodeGenOpts; + const flang::TargetOptions &TargetOpts; + const LangOptions &LangOpts; + Module *TheModule; + + Timer CodeGenerationTime; + + mutable PassManager *CodeGenPasses; + mutable PassManager *PerModulePasses; + mutable FunctionPassManager *PerFunctionPasses; + +private: + PassManager *getCodeGenPasses() const { + if (!CodeGenPasses) { + CodeGenPasses = new PassManager(); + CodeGenPasses->add(new DataLayoutPass()); + if (TM) + TM->addAnalysisPasses(*CodeGenPasses); + } + return CodeGenPasses; + } + + PassManager *getPerModulePasses() const { + if (!PerModulePasses) { + PerModulePasses = new PassManager(); + PerModulePasses->add(new DataLayoutPass()); + if (TM) + TM->addAnalysisPasses(*PerModulePasses); + } + return PerModulePasses; + } + + FunctionPassManager *getPerFunctionPasses() const { + if (!PerFunctionPasses) { + PerFunctionPasses = new FunctionPassManager(TheModule); + PerFunctionPasses->add(new DataLayoutPass()); + if (TM) + TM->addAnalysisPasses(*PerFunctionPasses); + } + return PerFunctionPasses; + } + + + void CreatePasses(); + + /// CreateTargetMachine - 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 + /// IR, and they require DataLayout which depends on the triple. + /// In this case, we allow this method to fail and not report an error. + /// When MustCreateTM is used, we print an error if we are unable to load + /// the requested target. + TargetMachine *CreateTargetMachine(bool MustCreateTM); + + /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR. + /// + /// \return True on success. + bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS); + +public: + EmitAssemblyHelper(DiagnosticsEngine &_Diags, + const CodeGenOptions &CGOpts, + const flang::TargetOptions &TOpts, + const LangOptions &LOpts, + Module *M) + : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), + TheModule(M), CodeGenerationTime("Code Generation Time"), + CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {} + + ~EmitAssemblyHelper() { + delete CodeGenPasses; + delete PerModulePasses; + delete PerFunctionPasses; + } + + std::unique_ptr<TargetMachine> TM; + + void EmitAssembly(BackendAction Action, raw_ostream *OS); +}; + +// We need this wrapper to access LangOpts and CGOpts from extension functions +// that we add to the PassManagerBuilder. +class PassManagerBuilderWrapper : public PassManagerBuilder { +public: + PassManagerBuilderWrapper(const CodeGenOptions &CGOpts, + const LangOptions &LangOpts) + : PassManagerBuilder(), CGOpts(CGOpts), LangOpts(LangOpts) {} + const CodeGenOptions &getCGOpts() const { return CGOpts; } + const LangOptions &getLangOpts() const { return LangOpts; } +private: + const CodeGenOptions &CGOpts; + const LangOptions &LangOpts; +}; + +} + +static void addBoundsCheckingPass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { + PM.add(createBoundsCheckingPass()); +} + +void EmitAssemblyHelper::CreatePasses() { + unsigned OptLevel = CodeGenOpts.OptimizationLevel; + CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining(); + + // Handle disabling of LLVM optimization, where we want to preserve the + // internal module before any optimization. + if (CodeGenOpts.DisableLLVMOpts) { + OptLevel = 0; + Inlining = CodeGenOpts.NoInlining; + } + + PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts); + PMBuilder.OptLevel = OptLevel; + PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize; + PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB; + PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP; + PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop; + + PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime; + PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; + + // Figure out TargetLibraryInfo. + Triple TargetTriple(TheModule->getTargetTriple()); + PMBuilder.LibraryInfo = new TargetLibraryInfo(TargetTriple); + if (!CodeGenOpts.SimplifyLibCalls) + PMBuilder.LibraryInfo->disableAllFunctions(); + + switch (Inlining) { + case CodeGenOptions::NoInlining: break; + case CodeGenOptions::NormalInlining: { + // FIXME: Derive these constants in a principled fashion. + unsigned Threshold = 225; + if (CodeGenOpts.OptimizeSize == 1) // -Os + Threshold = 75; + else if (CodeGenOpts.OptimizeSize == 2) // -Oz + Threshold = 25; + else if (OptLevel > 2) + Threshold = 275; + PMBuilder.Inliner = createFunctionInliningPass(Threshold); + break; + } + case CodeGenOptions::OnlyAlwaysInlining: + // Respect always_inline. + if (OptLevel == 0) + // Do not insert lifetime intrinsics at -O0. + PMBuilder.Inliner = createAlwaysInlinerPass(false); + else + PMBuilder.Inliner = createAlwaysInlinerPass(); + break; + } + + // Set up the per-function pass manager. + FunctionPassManager *FPM = getPerFunctionPasses(); + if (CodeGenOpts.VerifyModule) + FPM->add(createVerifierPass()); + PMBuilder.populateFunctionPassManager(*FPM); + + // Set up the per-module pass manager. + PassManager *MPM = getPerModulePasses(); + + if (!CodeGenOpts.DisableGCov && + (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) { + // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if + // LLVM's -default-gcov-version flag is set to something invalid. + GCOVOptions Options; + Options.EmitNotes = CodeGenOpts.EmitGcovNotes; + Options.EmitData = CodeGenOpts.EmitGcovArcs; + memcpy(Options.Version, CodeGenOpts.CoverageVersion, 4); + Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum; + Options.NoRedZone = CodeGenOpts.DisableRedZone; + Options.FunctionNamesInData = + !CodeGenOpts.CoverageNoFunctionNamesInData; + MPM->add(createGCOVProfilerPass(Options)); + if (CodeGenOpts.getDebugInfo() == CodeGenOptions::NoDebugInfo) + MPM->add(createStripSymbolsPass(true)); + } + + PMBuilder.populateModulePassManager(*MPM); +} + +TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { + // Create the TargetMachine for generating code. + std::string Error; + std::string Triple = TheModule->getTargetTriple(); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) { + if (MustCreateTM) + Diags.Report(diag::err_fe_unable_to_create_target) << Error; + return 0; + } + + // FIXME: Expose these capabilities via actual APIs!!!! Aside from just + // being gross, this is also totally broken if we ever care about + // concurrency. + + //TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose); + + //TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections); + //TargetMachine::setDataSections (CodeGenOpts.DataSections); + + // FIXME: Parse this earlier. + llvm::CodeModel::Model CM; + if (CodeGenOpts.CodeModel == "small") { + CM = llvm::CodeModel::Small; + } else if (CodeGenOpts.CodeModel == "kernel") { + CM = llvm::CodeModel::Kernel; + } else if (CodeGenOpts.CodeModel == "medium") { + CM = llvm::CodeModel::Medium; + } else if (CodeGenOpts.CodeModel == "large") { + CM = llvm::CodeModel::Large; + } else { + assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!"); + CM = llvm::CodeModel::Default; + } + + SmallVector<const char *, 16> BackendArgs; + BackendArgs.push_back("clang"); // Fake program name. + if (!CodeGenOpts.DebugPass.empty()) { + BackendArgs.push_back("-debug-pass"); + BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); + } + if (!CodeGenOpts.LimitFloatPrecision.empty()) { + BackendArgs.push_back("-limit-float-precision"); + BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); + } + if (llvm::TimePassesIsEnabled) + BackendArgs.push_back("-time-passes"); + for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i) + BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str()); + if (CodeGenOpts.NoGlobalMerge) + BackendArgs.push_back("-global-merge=false"); + BackendArgs.push_back(0); + llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, + BackendArgs.data()); + + std::string FeaturesStr; + if (TargetOpts.Features.size()) { + SubtargetFeatures Features; + for (std::vector<std::string>::const_iterator + it = TargetOpts.Features.begin(), + ie = TargetOpts.Features.end(); it != ie; ++it) + Features.AddFeature(*it); + FeaturesStr = Features.getString(); + } + + llvm::Reloc::Model RM = llvm::Reloc::Default; + if (CodeGenOpts.RelocationModel == "static") { + RM = llvm::Reloc::Static; + } else if (CodeGenOpts.RelocationModel == "pic") { + RM = llvm::Reloc::PIC_; + } else { + assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && + "Invalid PIC model!"); + RM = llvm::Reloc::DynamicNoPIC; + } + + CodeGenOpt::Level OptLevel = CodeGenOpt::Default; + switch (CodeGenOpts.OptimizationLevel) { + default: break; + case 0: OptLevel = CodeGenOpt::None; break; + case 3: OptLevel = CodeGenOpt::Aggressive; break; + } + + llvm::TargetOptions Options; + + // Set frame pointer elimination mode. + if (!CodeGenOpts.DisableFPElim) { + Options.NoFramePointerElim = false; + //Options.NoFramePointerElimNonLeaf = false; + } else if (CodeGenOpts.OmitLeafFramePointer) { + Options.NoFramePointerElim = false; + //Options.NoFramePointerElimNonLeaf = true; + } else { + Options.NoFramePointerElim = true; + //Options.NoFramePointerElimNonLeaf = true; + } + + if (CodeGenOpts.UseInitArray) + Options.UseInitArray = true; + + // Set float ABI type. + if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp") + Options.FloatABIType = llvm::FloatABI::Soft; + else if (CodeGenOpts.FloatABI == "hard") + Options.FloatABIType = llvm::FloatABI::Hard; + else { + assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!"); + Options.FloatABIType = llvm::FloatABI::Default; + } + + // Set FP fusion mode. + switch (CodeGenOpts.getFPContractMode()) { + case CodeGenOptions::FPC_Off: + Options.AllowFPOpFusion = llvm::FPOpFusion::Strict; + break; + case CodeGenOptions::FPC_On: + Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; + break; + case CodeGenOptions::FPC_Fast: + Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; + break; + } + + Options.LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD; + Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; + Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; + Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; + Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; + Options.UseSoftFloat = CodeGenOpts.SoftFloat; + Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; + //Options.RealignStack = CodeGenOpts.StackRealignment; + Options.DisableTailCalls = CodeGenOpts.DisableTailCalls; + Options.TrapFuncName = CodeGenOpts.TrapFuncName; + //Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; + //Options.EnableSegmentedStacks = CodeGenOpts.EnableSegmentedStacks; + + TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU, + FeaturesStr, Options, + RM, CM, OptLevel); + + //if (CodeGenOpts.RelaxAll) + // TM->setMCRelaxAll(true); + //if (CodeGenOpts.SaveTempLabels) + // TM->setMCSaveTempLabels(true); + //if (CodeGenOpts.NoDwarf2CFIAsm) + // TM->setMCUseCFI(false); + //if (!CodeGenOpts.NoDwarfDirectoryAsm) + // TM->setMCUseDwarfDirectory(true); + //if (CodeGenOpts.NoExecStack) + // TM->setMCNoExecStack(true); + + return TM; +} + +bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, + formatted_raw_ostream &OS) { + + // Create the code generator passes. + PassManager *PM = getCodeGenPasses(); + + // Add LibraryInfo. + llvm::Triple TargetTriple(TheModule->getTargetTriple()); + TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple); + if (!CodeGenOpts.SimplifyLibCalls) + TLI->disableAllFunctions(); + PM->add(TLI); + + // Add Target specific analysis passes. + TM->addAnalysisPasses(*PM); + + // Normal mode, emit a .s or .o file by running the code generator. Note, + // this also adds codegenerator level optimization passes. + TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; + if (Action == Backend_EmitObj) + CGFT = TargetMachine::CGFT_ObjectFile; + else if (Action == Backend_EmitMCNull) + CGFT = TargetMachine::CGFT_Null; + else + assert(Action == Backend_EmitAssembly && "Invalid action!"); + + if (TM->addPassesToEmitFile(*PM, OS, CGFT, + /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { + Diags.Report(diag::err_fe_unable_to_interface_with_target); + return false; + } + + return true; +} + +void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) { + TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0); + llvm::formatted_raw_ostream FormattedOS; + + bool UsesCodeGen = (Action != Backend_EmitNothing && + Action != Backend_EmitBC && + Action != Backend_EmitLL); + + if (!TM) + TM.reset(CreateTargetMachine(UsesCodeGen)); + + if (UsesCodeGen && !TM) return; + CreatePasses(); + + switch (Action) { + case Backend_EmitNothing: + break; + + case Backend_EmitBC: + getPerModulePasses()->add(createBitcodeWriterPass(*OS)); + break; + + case Backend_EmitLL: + FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); + getPerModulePasses()->add(createPrintModulePass(FormattedOS)); + break; + + default: + FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); + if (!AddEmitPasses(Action, FormattedOS)) + return; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + // Run passes. For now we do all passes at once, but eventually we + // would like to have the option of streaming code generation. + + if (PerFunctionPasses) { + PrettyStackTraceString CrashInfo("Per-function optimization"); + + PerFunctionPasses->doInitialization(); + for (Module::iterator I = TheModule->begin(), + E = TheModule->end(); I != E; ++I) + if (!I->isDeclaration()) + PerFunctionPasses->run(*I); + PerFunctionPasses->doFinalization(); + } + + if (PerModulePasses) { + PrettyStackTraceString CrashInfo("Per-module optimization passes"); + PerModulePasses->run(*TheModule); + } + + if (CodeGenPasses) { + PrettyStackTraceString CrashInfo("Code generation"); + CodeGenPasses->run(*TheModule); + } +} + +void flang::EmitBackendOutput(DiagnosticsEngine &Diags, + const CodeGenOptions &CGOpts, + const flang::TargetOptions &TOpts, + const LangOptions &LOpts, + Module *M, + BackendAction Action, raw_ostream *OS) { + EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); + + AsmHelper.EmitAssembly(Action, OS); +} diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index bbef51ec3b..d35a48bad0 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -24,7 +24,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include "llvm/Transforms/Utils/Local.h" namespace flang { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index a6c7464788..6ddcc2b592 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -22,7 +22,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" namespace flang { namespace CodeGen { diff --git a/lib/CodeGen/CGIntrinsic.cpp b/lib/CodeGen/CGIntrinsic.cpp index cbdb6c043a..1c9dba11e9 100644 --- a/lib/CodeGen/CGIntrinsic.cpp +++ b/lib/CodeGen/CGIntrinsic.cpp @@ -24,7 +24,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" namespace flang { namespace CodeGen { diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 5af6b01215..150df60999 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -19,7 +19,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" namespace flang { namespace CodeGen { diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp new file mode 100644 index 0000000000..53ee5aafd3 --- /dev/null +++ b/lib/CodeGen/CodeGenAction.cpp @@ -0,0 +1,245 @@ +//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "flang/CodeGen/CodeGenAction.h" +#include "flang/CodeGen/BackendUtil.h" +#include "flang/AST/ASTConsumer.h" +#include "flang/AST/ASTContext.h" +#include "flang/AST/DeclGroup.h" +#include "flang/CodeGen/BackendUtil.h" +#include "flang/CodeGen/ModuleBuilder.h" +#include "flang/Frontend/CompilerInstance.h" +#include "flang/Frontend/FrontendDiagnostic.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Pass.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Timer.h" + +using namespace flang; +using namespace llvm; + +namespace flang { + class BackendConsumer : public ASTConsumer { + virtual void anchor(); + DiagnosticsEngine &Diags; + BackendAction Action; + const CodeGenOptions &CodeGenOpts; + const TargetOptions &TargetOpts; + const LangOptions &LangOpts; + raw_ostream *AsmOutStream; + ASTContext *Context; + + Timer LLVMIRGeneration; + + std::unique_ptr<CodeGenerator> Gen; + + std::unique_ptr<llvm::Module> TheModule, LinkModule; + + public: + BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags, + const CodeGenOptions &compopts, + const TargetOptions &targetopts, + const LangOptions &langopts, + bool TimePasses, + const std::string &infile, + llvm::Module *LinkModule, + raw_ostream *OS, + LLVMContext &C) : + Diags(_Diags), + Action(action), + CodeGenOpts(compopts), + TargetOpts(targetopts), + LangOpts(langopts), + AsmOutStream(OS), + Context(), + LLVMIRGeneration("LLVM IR Generation Time"), + Gen(CreateLLVMCodeGen(Diags, infile, compopts, targetopts, C)), + LinkModule(LinkModule) + { + llvm::TimePassesIsEnabled = TimePasses; + } + + llvm::Module *takeModule() { return TheModule.release(); } + llvm::Module *takeLinkModule() { return LinkModule.release(); } + + virtual void Initialize(ASTContext &Ctx) { + Context = &Ctx; + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.startTimer(); + + Gen->Initialize(Ctx); + + TheModule.reset(Gen->GetModule()); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.stopTimer(); + } + + virtual void HandleTranslationUnit(ASTContext &C) { + { + PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.startTimer(); + + Gen->HandleTranslationUnit(C); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.stopTimer(); + } + + // Silently ignore if we weren't initialized for some reason. + if (!TheModule) + return; + + // Make sure IR generation is happy with the module. This is released by + // the module provider. + llvm::Module *M = Gen->ReleaseModule(); + if (!M) { + // The module has been released by IR gen on failures, do not double + // free. + TheModule.release(); + return; + } + + assert(TheModule.get() == M && + "Unexpected module change during IR generation"); + + // Link LinkModule into this module if present, preserving its validity. + if (LinkModule) { + std::string ErrorMsg; + if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource, + &ErrorMsg)) { + Diags.Report(diag::err_fe_cannot_link_module) + << LinkModule->getModuleIdentifier() << ErrorMsg; + return; + } + } + + EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, + TheModule.get(), Action, AsmOutStream); + + } + + }; + + void BackendConsumer::anchor() {} +} + +// + +CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) + : Act(_Act), LinkModule(0), + VMContext(_VMContext ? _VMContext : new LLVMContext), + OwnsVMContext(!_VMContext) {} + +CodeGenAction::~CodeGenAction() { + TheModule.reset(); + if (OwnsVMContext) + delete VMContext; +} + +bool CodeGenAction::hasIRSupport() const { return true; } + +void CodeGenAction::EndSourceFileAction() { + // If the consumer creation failed, do nothing. + if (!getCompilerInstance().hasASTConsumer()) + return; + + // If we were given a link module, release consumer's ownership of it. + if (LinkModule) + BEConsumer->takeLinkModule(); + + // Steal the module from the consumer. + TheModule.reset(BEConsumer->takeModule()); +} + +llvm::Module *CodeGenAction::takeModule() { + return TheModule.release(); +} + +llvm::LLVMContext *CodeGenAction::takeLLVMContext() { + OwnsVMContext = false; + return VMContext; +} + +static raw_ostream *GetOutputStream(CompilerInstance &CI, + StringRef InFile, + BackendAction Action) { + switch (Action) { + case Backend_EmitAssembly: + return CI.createDefaultOutputFile(false, InFile, "s"); + case Backend_EmitLL: + return CI.createDefaultOutputFile(false, InFile, "ll"); + case Backend_EmitBC: + return CI.createDefaultOutputFile(true, InFile, "bc"); + case Backend_EmitNothing: + return 0; + case Backend_EmitMCNull: + case Backend_EmitObj: + return CI.createDefaultOutputFile(true, InFile, "o"); + } + + llvm_unreachable("Invalid action!"); +} + +ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + BackendAction BA = static_cast<BackendAction>(Act); + std::unique_ptr<raw_ostream> OS(GetOutputStream(CI, InFile, BA)); + if (BA != Backend_EmitNothing && !OS) + return 0; + + llvm::Module *LinkModuleToUse = LinkModule; + + BEConsumer = + new BackendConsumer(BA, CI.getDiagnostics(), + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getLangOpts(), + CI.getFrontendOpts().ShowTimers, InFile, + LinkModuleToUse, OS.release(), *VMContext); + return BEConsumer; +} + +void CodeGenAction::ExecuteAction() { + // Otherwise follow the normal AST path. + this->ASTFrontendAction::ExecuteAction(); +} + +// + +void EmitAssemblyAction::anchor() { } +EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitAssembly, _VMContext) {} + +void EmitBCAction::anchor() { } +EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitBC, _VMContext) {} + +void EmitLLVMAction::anchor() { } +EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitLL, _VMContext) {} + +void EmitLLVMOnlyAction::anchor() { } +EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitNothing, _VMContext) {} + +void EmitCodeGenOnlyAction::anchor() { } +EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitMCNull, _VMContext) {} + +void EmitObjAction::anchor() { } +EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) + : CodeGenAction(Backend_EmitObj, _VMContext) {} diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 867a314aa9..3326cc2b4d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -26,7 +26,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" namespace llvm { class BasicBlock; diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 74536bbd05..c96a47d1bf 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -28,10 +28,10 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/Mangler.h" +#include "llvm/IR/Mangler.h" namespace flang { namespace CodeGen { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index dfa1a31080..abafbfaa07 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -24,8 +24,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Module.h" -#include "llvm/Support/ValueHandle.h" -#include "llvm/Transforms/Utils/BlackList.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/SpecialCaseList.h" namespace llvm { class Module; diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 8cd6ad3ef1..ba87058e91 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -18,7 +18,6 @@ #include "flang/AST/Expr.h" #include "flang/Basic/Diagnostic.h" #include "flang/Frontend/CodeGenOptions.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" @@ -27,17 +26,17 @@ using namespace flang; namespace { - using llvm::OwningPtr; + using std::unique_ptr; class CodeGeneratorImpl : public CodeGenerator { DiagnosticsEngine &Diags; - OwningPtr<const llvm::DataLayout> TD; + std::unique_ptr<const llvm::DataLayout> TD; ASTContext *Ctx; const CodeGenOptions CodeGenOpts; // Intentionally copied in. const TargetOptions Target; protected: - OwningPtr<llvm::Module> M; - OwningPtr<CodeGen::CodeGenModule> Builder; + std::unique_ptr<llvm::Module> M; + std::unique_ptr<CodeGen::CodeGenModule> Builder; public: CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName, const CodeGenOptions &CGO, @@ -54,7 +53,7 @@ namespace { } virtual llvm::Module* ReleaseModule() { - return M.take(); + return M.release(); } virtual void Initialize(ASTContext &Context) { diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 160c465914..388822da8d 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -141,7 +141,7 @@ void Sema::PopExecutableProgramUnit(SourceLocation Loc) { // was already reported as undeclared label use. ReportUnterminatedStmt(CurExecutableStmts->LastEntered(), Loc, false); } - auto Body = CurExecutableStmts->LeaveOuterBody(Context, cast<Decl>(CurContext)->getLocation()); + auto Body = CurExecutableStmts->LeaveOuterBody(Context, Decl::castFromDeclContext(CurContext)->getLocation()); if(auto FD = dyn_cast<FunctionDecl>(CurContext)) FD->setBody(Body); else @@ -172,7 +172,7 @@ Stmt *BlockStmtBuilder::CreateBody(ASTContext &C, void BlockStmtBuilder::LeaveIfThen(ASTContext &C) { auto Last = ControlFlowStack.back(); - assert(isa<IfStmt>(Last)); + assert(isa<IfStmt>(Last.Statement)); auto Body = CreateBody(C, Last); cast<IfStmt>(Last.Statement)->setThenStmt(Body); @@ -181,7 +181,7 @@ void BlockStmtBuilder::LeaveIfThen(ASTContext &C) { void BlockStmtBuilder::LeaveWhereThen(ASTContext &C) { auto Last = ControlFlowStack.back(); - assert(isa<WhereStmt>(Last)); + assert(isa<WhereStmt>(Last.Statement)); auto Body = CreateBody(C, Last); cast<WhereStmt>(Last.Statement)->setThenStmt(Body); diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index a0e2375b99..c0ba3e4c62 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -6,7 +6,6 @@ set( LLVM_LINK_COMPONENTS codegen ipo selectiondag - jit interpreter linker ) diff --git a/tools/driver/Main.cpp b/tools/driver/Main.cpp index 744f3441f4..327b22de5e 100644 --- a/tools/driver/Main.cpp +++ b/tools/driver/Main.cpp @@ -23,12 +23,12 @@ #include "llvm/IR/Module.h" #include "llvm/IR/DataLayout.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" +//#include "llvm/ExecutionEngine/JIT.h" #include "llvm/PassManager.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" -#include "llvm/Analysis/Verifier.h" +#include "llvm/IR/Verifier.h" #include "llvm/Analysis/Passes.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetMachine.h" @@ -47,8 +47,6 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/Timer.h" -#include "llvm/Support/system_error.h" -#include "llvm/ADT/OwningPtr.h" using namespace llvm; using namespace flang; @@ -128,6 +126,7 @@ namespace { } // end anonymous namespace +/* extern "C" void jit_write_start(void *) { } extern "C" void jit_write_character(void *,const char *Ptr, size_t Length) { @@ -158,7 +157,7 @@ extern "C" void jit_init() {} static int Execute(llvm::Module *Module, const char * const *envp) { std::string Error; - OwningPtr<llvm::ExecutionEngine> EE( + std::unique_ptr<llvm::ExecutionEngine> EE( llvm::ExecutionEngine::createJIT(Module, &Error)); if (!EE) { llvm::errs() << "unable to make execution engine: " << Error << "\n"; @@ -204,6 +203,7 @@ static int Execute(llvm::Module *Module, const char * const *envp) { return EE->runFunctionAsMain(EntryFn, Args, envp); } +*/ std::string GetOutputName(StringRef Filename, BackendAction Action) { @@ -237,10 +237,10 @@ static bool EmitFile(llvm::raw_ostream &Out, Action == Backend_EmitObj ? llvm::TargetMachine::CGFT_ObjectFile : llvm::TargetMachine::CGFT_AssemblyFile; - llvm::PassManager PM; + PassManager PM; Target.setAsmVerbosityDefault(true); - Target.setMCRelaxAll(true); + //Target.setMCRelaxAll(true); llvm::formatted_raw_ostream FOS(Out); // Ask the target to add backend passes as necessary. @@ -262,11 +262,11 @@ static bool EmitOutputFile(const std::string &Input, llvm::Module *Module, llvm::TargetMachine* TM, BackendAction Action) { - std::string err; - llvm::raw_fd_ostream Out(Input.c_str(), err, llvm::raw_fd_ostream::F_Binary);//FIXME: llvm 3.4: llvm::sys::fs::F_Binary); - if (!err.empty()){ + std::error_code err; + llvm::raw_fd_ostream Out(Input.c_str(), err, llvm::sys::fs::F_None); + if (!err){ llvm::errs() << "Could not open output file '" << Input << "': " - << err <<"\n"; + << err.message() <<"\n"; return true; } return EmitFile(Out, Module, TM, Action); @@ -295,13 +295,14 @@ static bool LinkFiles(ArrayRef<std::string> OutputFiles) { static bool ParseFile(const std::string &Filename, const std::vector<std::string> &IncludeDirs, SmallVectorImpl<std::string> &OutputFiles) { - llvm::OwningPtr<llvm::MemoryBuffer> MB; - if (llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(Filename.c_str(), - MB)) { + ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = MBOrErr.getError()) { llvm::errs() << "Could not open input file '" << Filename << "': " - << ec.message() <<"\n"; + << EC.message() <<"\n"; return true; } + std::unique_ptr<llvm::MemoryBuffer> MB = std::move(MBOrErr.get()); // Record the location of the include directory so that the lexer can find it // later. @@ -309,7 +310,7 @@ static bool ParseFile(const std::string &Filename, SrcMgr.setIncludeDirs(IncludeDirs); // Tell SrcMgr about this buffer, which is what Parser will pick up. - SrcMgr.AddNewSourceBuffer(MB.take(), llvm::SMLoc()); + SrcMgr.AddNewSourceBuffer(std::move(MB), llvm::SMLoc()); LangOptions Opts; Opts.DefaultReal8 = DefaultReal8; @@ -382,7 +383,7 @@ static bool ParseFile(const std::string &Filename, if(!(EmitLLVM && OptLevel == 0)) { auto TheModule = CG->GetModule(); auto PM = new PassManager(); - PM->add(new DataLayout(TheModule)); + PM->add(new DataLayoutPass()); TM->addAnalysisPasses(*PM); PM->add(createPromoteMemoryToRegisterPass()); @@ -404,8 +405,8 @@ static bool ParseFile(const std::string &Filename, } if(Interpret) { - const char *Env[] = { "", nullptr }; - Execute(CG->ReleaseModule(), Env); + //const char *Env[] = { "", nullptr }; + //Execute(CG->ReleaseModule(), Env); } else if(OutputFile == "-") EmitFile(llvm::outs(), CG->GetModule(), TM, BA); else { |