Index: head/contrib/llvm/include/llvm/Support/TargetRegistry.h =================================================================== --- head/contrib/llvm/include/llvm/Support/TargetRegistry.h (revision 241429) +++ head/contrib/llvm/include/llvm/Support/TargetRegistry.h (revision 241430) @@ -1,1158 +1,1161 @@ //===-- Support/TargetRegistry.h - Target Registration ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file exposes the TargetRegistry interface, which tools can use to access // the appropriate target specific classes (TargetMachine, AsmPrinter, etc.) // which have been registered. // // Target specific class implementations should register themselves using the // appropriate TargetRegistry interfaces. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H #include "llvm/Support/CodeGen.h" #include "llvm/ADT/Triple.h" #include #include namespace llvm { class AsmPrinter; class Module; class MCAssembler; class MCAsmBackend; class MCAsmInfo; class MCAsmParser; class MCCodeEmitter; class MCCodeGenInfo; class MCContext; class MCDisassembler; class MCInstrAnalysis; class MCInstPrinter; class MCInstrInfo; class MCRegisterInfo; class MCStreamer; class MCSubtargetInfo; class MCTargetAsmLexer; class MCTargetAsmParser; class TargetMachine; class TargetOptions; class raw_ostream; class formatted_raw_ostream; MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); /// Target - Wrapper for Target specific information. /// /// For registration purposes, this is a POD type so that targets can be /// registered without the use of static constructors. /// /// Targets should implement a single global instance of this class (which /// will be zero initialized), and pass that instance to the TargetRegistry as /// part of their initialization. class Target { public: friend struct TargetRegistry; typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const Target &T, StringRef TT); typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info); typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, StringRef CPU, StringRef Features); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); - typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, StringRef TT); + typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, + StringRef TT, + StringRef CPU); typedef MCTargetAsmLexer *(*MCAsmLexerCtorTy)(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI); typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, MCAsmParser &P); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, const MCSubtargetInfo &STI); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI); typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, bool RelaxAll, bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); private: /// Next - The next registered target in the linked list, maintained by the /// TargetRegistry. Target *Next; /// TripleMatchQualityFn - The target function for rating the match quality /// of a triple. TripleMatchQualityFnTy TripleMatchQualityFn; /// Name - The target name. const char *Name; /// ShortDesc - A short description of the target. const char *ShortDesc; /// HasJIT - Whether this target supports the JIT. bool HasJIT; /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if /// registered. MCAsmInfoCtorFnTy MCAsmInfoCtorFn; /// MCCodeGenInfoCtorFn - Constructor function for this target's /// MCCodeGenInfo, if registered. MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, /// if registered. MCInstrInfoCtorFnTy MCInstrInfoCtorFn; /// MCInstrAnalysisCtorFn - Constructor function for this target's /// MCInstrAnalysis, if registered. MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, /// if registered. MCRegInfoCtorFnTy MCRegInfoCtorFn; /// MCSubtargetInfoCtorFn - Constructor function for this target's /// MCSubtargetInfo, if registered. MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn; /// TargetMachineCtorFn - Construction function for this target's /// TargetMachine, if registered. TargetMachineCtorTy TargetMachineCtorFn; /// MCAsmBackendCtorFn - Construction function for this target's /// MCAsmBackend, if registered. MCAsmBackendCtorTy MCAsmBackendCtorFn; /// MCAsmLexerCtorFn - Construction function for this target's /// MCTargetAsmLexer, if registered. MCAsmLexerCtorTy MCAsmLexerCtorFn; /// MCAsmParserCtorFn - Construction function for this target's /// MCTargetAsmParser, if registered. MCAsmParserCtorTy MCAsmParserCtorFn; /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, /// if registered. AsmPrinterCtorTy AsmPrinterCtorFn; /// MCDisassemblerCtorFn - Construction function for this target's /// MCDisassembler, if registered. MCDisassemblerCtorTy MCDisassemblerCtorFn; /// MCInstPrinterCtorFn - Construction function for this target's /// MCInstPrinter, if registered. MCInstPrinterCtorTy MCInstPrinterCtorFn; /// MCCodeEmitterCtorFn - Construction function for this target's /// CodeEmitter, if registered. MCCodeEmitterCtorTy MCCodeEmitterCtorFn; /// MCObjectStreamerCtorFn - Construction function for this target's /// MCObjectStreamer, if registered. MCObjectStreamerCtorTy MCObjectStreamerCtorFn; /// AsmStreamerCtorFn - Construction function for this target's /// AsmStreamer, if registered (default = llvm::createAsmStreamer). AsmStreamerCtorTy AsmStreamerCtorFn; public: Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {} /// @name Target Information /// @{ // getNext - Return the next registered target. const Target *getNext() const { return Next; } /// getName - Get the target name. const char *getName() const { return Name; } /// getShortDescription - Get a short description of the target. const char *getShortDescription() const { return ShortDesc; } /// @} /// @name Feature Predicates /// @{ /// hasJIT - Check if this targets supports the just-in-time compilation. bool hasJIT() const { return HasJIT; } /// hasTargetMachine - Check if this target supports code generation. bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } /// hasMCAsmBackend - Check if this target supports .o generation. bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } /// hasMCAsmLexer - Check if this target supports .s lexing. bool hasMCAsmLexer() const { return MCAsmLexerCtorFn != 0; } /// hasAsmParser - Check if this target supports .s parsing. bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; } /// hasAsmPrinter - Check if this target supports .s printing. bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; } /// hasMCDisassembler - Check if this target has a disassembler. bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; } /// hasMCInstPrinter - Check if this target has an instruction printer. bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; } /// hasMCCodeEmitter - Check if this target supports instruction encoding. bool hasMCCodeEmitter() const { return MCCodeEmitterCtorFn != 0; } /// hasMCObjectStreamer - Check if this target supports streaming to files. bool hasMCObjectStreamer() const { return MCObjectStreamerCtorFn != 0; } /// hasAsmStreamer - Check if this target supports streaming to files. bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; } /// @} /// @name Feature Constructors /// @{ /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified /// target triple. /// /// \arg Triple - This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. MCAsmInfo *createMCAsmInfo(StringRef Triple) const { if (!MCAsmInfoCtorFn) return 0; return MCAsmInfoCtorFn(*this, Triple); } /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. /// MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) const { if (!MCCodeGenInfoCtorFn) return 0; return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); } /// createMCInstrInfo - Create a MCInstrInfo implementation. /// MCInstrInfo *createMCInstrInfo() const { if (!MCInstrInfoCtorFn) return 0; return MCInstrInfoCtorFn(); } /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. /// MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { if (!MCInstrAnalysisCtorFn) return 0; return MCInstrAnalysisCtorFn(Info); } /// createMCRegInfo - Create a MCRegisterInfo implementation. /// MCRegisterInfo *createMCRegInfo(StringRef Triple) const { if (!MCRegInfoCtorFn) return 0; return MCRegInfoCtorFn(Triple); } /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. /// /// \arg Triple - This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. /// \arg CPU - This specifies the name of the target CPU. /// \arg Features - This specifies the string representation of the /// additional target features. MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, StringRef Features) const { if (!MCSubtargetInfoCtorFn) return 0; return MCSubtargetInfoCtorFn(Triple, CPU, Features); } /// createTargetMachine - Create a target specific machine implementation /// for the specified \arg Triple. /// /// \arg Triple - This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU, StringRef Features, const TargetOptions &Options, Reloc::Model RM = Reloc::Default, CodeModel::Model CM = CodeModel::Default, CodeGenOpt::Level OL = CodeGenOpt::Default) const { if (!TargetMachineCtorFn) return 0; return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, OL); } /// createMCAsmBackend - Create a target specific assembly parser. /// /// \arg Triple - The target triple string. /// \arg Backend - The target independent assembler object. - MCAsmBackend *createMCAsmBackend(StringRef Triple) const { + MCAsmBackend *createMCAsmBackend(StringRef Triple, StringRef CPU) const { if (!MCAsmBackendCtorFn) return 0; - return MCAsmBackendCtorFn(*this, Triple); + return MCAsmBackendCtorFn(*this, Triple, CPU); } /// createMCAsmLexer - Create a target specific assembly lexer. /// MCTargetAsmLexer *createMCAsmLexer(const MCRegisterInfo &MRI, const MCAsmInfo &MAI) const { if (!MCAsmLexerCtorFn) return 0; return MCAsmLexerCtorFn(*this, MRI, MAI); } /// createMCAsmParser - Create a target specific assembly parser. /// /// \arg Parser - The target independent parser implementation to use for /// parsing and lexing. MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, MCAsmParser &Parser) const { if (!MCAsmParserCtorFn) return 0; return MCAsmParserCtorFn(STI, Parser); } /// createAsmPrinter - Create a target specific assembly printer pass. This /// takes ownership of the MCStreamer object. AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ if (!AsmPrinterCtorFn) return 0; return AsmPrinterCtorFn(TM, Streamer); } MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI) const { if (!MCDisassemblerCtorFn) return 0; return MCDisassemblerCtorFn(*this, STI); } MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) const { if (!MCInstPrinterCtorFn) return 0; return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); } /// createMCCodeEmitter - Create a target specific code emitter. MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) const { if (!MCCodeEmitterCtorFn) return 0; return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); } /// createMCObjectStreamer - Create a target specific MCStreamer. /// /// \arg TT - The target triple. /// \arg Ctx - The target context. /// \arg TAB - The target assembler backend object. Takes ownership. /// \arg _OS - The stream object. /// \arg _Emitter - The target independent assembler object.Takes ownership. /// \arg RelaxAll - Relax all fixups? /// \arg NoExecStack - Mark file as not needing a executable stack. MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, bool RelaxAll, bool NoExecStack) const { if (!MCObjectStreamerCtorFn) return 0; return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack); } /// createAsmStreamer - Create a target specific MCStreamer. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { // AsmStreamerCtorFn is default to llvm::createAsmStreamer return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); } /// @} }; /// TargetRegistry - Generic interface to target specific features. struct TargetRegistry { class iterator { const Target *Current; explicit iterator(Target *T) : Current(T) {} friend struct TargetRegistry; public: iterator(const iterator &I) : Current(I.Current) {} iterator() : Current(0) {} bool operator==(const iterator &x) const { return Current == x.Current; } bool operator!=(const iterator &x) const { return !operator==(x); } // Iterator traversal: forward iteration only iterator &operator++() { // Preincrement assert(Current && "Cannot increment end iterator!"); Current = Current->getNext(); return *this; } iterator operator++(int) { // Postincrement iterator tmp = *this; ++*this; return tmp; } const Target &operator*() const { assert(Current && "Cannot dereference end iterator!"); return *Current; } const Target *operator->() const { return &operator*(); } }; /// printRegisteredTargetsForVersion - Print the registered targets /// appropriately for inclusion in a tool's version output. static void printRegisteredTargetsForVersion(); /// @name Registry Access /// @{ static iterator begin(); static iterator end() { return iterator(); } /// lookupTarget - Lookup a target based on a target triple. /// /// \param Triple - The triple to use for finding a target. /// \param Error - On failure, an error string describing why no target was /// found. static const Target *lookupTarget(const std::string &Triple, std::string &Error); /// lookupTarget - Lookup a target based on an architecture name /// and a target triple. If the architecture name is non-empty, /// then the lookup is done by architecture. Otherwise, the target /// triple is used. /// /// \param ArchName - The architecture to use for finding a target. /// \param TheTriple - The triple to use for finding a target. The /// triple is updated with canonical architecture name if a lookup /// by architecture is done. /// \param Error - On failure, an error string describing why no target was /// found. static const Target *lookupTarget(const std::string &ArchName, Triple &TheTriple, std::string &Error); /// getClosestTargetForJIT - Pick the best target that is compatible with /// the current host. If no close target can be found, this returns null /// and sets the Error string to a reason. /// /// Maintained for compatibility through 2.6. static const Target *getClosestTargetForJIT(std::string &Error); /// @} /// @name Target Registration /// @{ /// RegisterTarget - Register the given target. Attempts to register a /// target which has already been registered will be ignored. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Name - The target name. This should be a static string. /// @param ShortDesc - A short target description. This should be a static /// string. /// @param TQualityFn - The triple match quality computation function for /// this target. /// @param HasJIT - Whether the target supports JIT code /// generation. static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc, Target::TripleMatchQualityFnTy TQualityFn, bool HasJIT = false); /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCAsmInfo for the target. static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCAsmInfoCtorFn) T.MCAsmInfoCtorFn = Fn; } /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCCodeGenInfo for the target. static void RegisterMCCodeGenInfo(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCCodeGenInfoCtorFn) T.MCCodeGenInfoCtorFn = Fn; } /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCInstrInfo for the target. static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCInstrInfoCtorFn) T.MCInstrInfoCtorFn = Fn; } /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for /// the given target. static void RegisterMCInstrAnalysis(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCInstrAnalysisCtorFn) T.MCInstrAnalysisCtorFn = Fn; } /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCRegisterInfo for the target. static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCRegInfoCtorFn) T.MCRegInfoCtorFn = Fn; } /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for /// the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCSubtargetInfo for the target. static void RegisterMCSubtargetInfo(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { // Ignore duplicate registration. if (!T.MCSubtargetInfoCtorFn) T.MCSubtargetInfoCtorFn = Fn; } /// RegisterTargetMachine - Register a TargetMachine implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct a TargetMachine for the target. static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) { // Ignore duplicate registration. if (!T.TargetMachineCtorFn) T.TargetMachineCtorFn = Fn; } /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an AsmBackend for the target. static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { if (!T.MCAsmBackendCtorFn) T.MCAsmBackendCtorFn = Fn; } /// RegisterMCAsmLexer - Register a MCTargetAsmLexer implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCAsmLexer for the target. static void RegisterMCAsmLexer(Target &T, Target::MCAsmLexerCtorTy Fn) { if (!T.MCAsmLexerCtorFn) T.MCAsmLexerCtorFn = Fn; } /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for /// the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCTargetAsmParser for the target. static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { if (!T.MCAsmParserCtorFn) T.MCAsmParserCtorFn = Fn; } /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given /// target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an AsmPrinter for the target. static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { // Ignore duplicate registration. if (!T.AsmPrinterCtorFn) T.AsmPrinterCtorFn = Fn; } /// RegisterMCDisassembler - Register a MCDisassembler implementation for /// the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCDisassembler for the target. static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn) { if (!T.MCDisassemblerCtorFn) T.MCDisassemblerCtorFn = Fn; } /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCInstPrinter for the target. static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) { if (!T.MCInstPrinterCtorFn) T.MCInstPrinterCtorFn = Fn; } /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCCodeEmitter for the target. static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) { if (!T.MCCodeEmitterCtorFn) T.MCCodeEmitterCtorFn = Fn; } /// RegisterMCObjectStreamer - Register a object code MCStreamer /// implementation for the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCStreamer for the target. static void RegisterMCObjectStreamer(Target &T, Target::MCObjectStreamerCtorTy Fn) { if (!T.MCObjectStreamerCtorFn) T.MCObjectStreamerCtorFn = Fn; } /// RegisterAsmStreamer - Register an assembly MCStreamer implementation /// for the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCStreamer for the target. static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { if (T.AsmStreamerCtorFn == createAsmStreamer) T.AsmStreamerCtorFn = Fn; } /// @} }; //===--------------------------------------------------------------------===// /// RegisterTarget - Helper template for registering a target, for use in the /// target's initialization function. Usage: /// /// /// Target TheFooTarget; // The global target instance. /// /// extern "C" void LLVMInitializeFooTargetInfo() { /// RegisterTarget X(TheFooTarget, "foo", "Foo description"); /// } template struct RegisterTarget { RegisterTarget(Target &T, const char *Name, const char *Desc) { TargetRegistry::RegisterTarget(T, Name, Desc, &getTripleMatchQuality, HasJIT); } static unsigned getTripleMatchQuality(const std::string &TT) { if (Triple(TT).getArch() == TargetArchType) return 20; return 0; } }; /// RegisterMCAsmInfo - Helper template for registering a target assembly info /// implementation. This invokes the static "Create" method on the class to /// actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCAsmInfo X(TheFooTarget); /// } template struct RegisterMCAsmInfo { RegisterMCAsmInfo(Target &T) { TargetRegistry::RegisterMCAsmInfo(T, &Allocator); } private: static MCAsmInfo *Allocator(const Target &T, StringRef TT) { return new MCAsmInfoImpl(T, TT); } }; /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info /// implementation. This invokes the specified function to do the /// construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction); /// } struct RegisterMCAsmInfoFn { RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) { TargetRegistry::RegisterMCAsmInfo(T, Fn); } }; /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info /// implementation. This invokes the static "Create" method on the class /// to actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCCodeGenInfo X(TheFooTarget); /// } template struct RegisterMCCodeGenInfo { RegisterMCCodeGenInfo(Target &T) { TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); } private: static MCCodeGenInfo *Allocator(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) { return new MCCodeGenInfoImpl(); } }; /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen /// info implementation. This invokes the specified function to do the /// construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); /// } struct RegisterMCCodeGenInfoFn { RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { TargetRegistry::RegisterMCCodeGenInfo(T, Fn); } }; /// RegisterMCInstrInfo - Helper template for registering a target instruction /// info implementation. This invokes the static "Create" method on the class /// to actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCInstrInfo X(TheFooTarget); /// } template struct RegisterMCInstrInfo { RegisterMCInstrInfo(Target &T) { TargetRegistry::RegisterMCInstrInfo(T, &Allocator); } private: static MCInstrInfo *Allocator() { return new MCInstrInfoImpl(); } }; /// RegisterMCInstrInfoFn - Helper template for registering a target /// instruction info implementation. This invokes the specified function to /// do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); /// } struct RegisterMCInstrInfoFn { RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { TargetRegistry::RegisterMCInstrInfo(T, Fn); } }; /// RegisterMCInstrAnalysis - Helper template for registering a target /// instruction analyzer implementation. This invokes the static "Create" /// method on the class to actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCInstrAnalysis X(TheFooTarget); /// } template struct RegisterMCInstrAnalysis { RegisterMCInstrAnalysis(Target &T) { TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); } private: static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { return new MCInstrAnalysisImpl(Info); } }; /// RegisterMCInstrAnalysisFn - Helper template for registering a target /// instruction analyzer implementation. This invokes the specified function /// to do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); /// } struct RegisterMCInstrAnalysisFn { RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { TargetRegistry::RegisterMCInstrAnalysis(T, Fn); } }; /// RegisterMCRegInfo - Helper template for registering a target register info /// implementation. This invokes the static "Create" method on the class to /// actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCRegInfo X(TheFooTarget); /// } template struct RegisterMCRegInfo { RegisterMCRegInfo(Target &T) { TargetRegistry::RegisterMCRegInfo(T, &Allocator); } private: static MCRegisterInfo *Allocator(StringRef TT) { return new MCRegisterInfoImpl(); } }; /// RegisterMCRegInfoFn - Helper template for registering a target register /// info implementation. This invokes the specified function to do the /// construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); /// } struct RegisterMCRegInfoFn { RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { TargetRegistry::RegisterMCRegInfo(T, Fn); } }; /// RegisterMCSubtargetInfo - Helper template for registering a target /// subtarget info implementation. This invokes the static "Create" method /// on the class to actually do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCSubtargetInfo X(TheFooTarget); /// } template struct RegisterMCSubtargetInfo { RegisterMCSubtargetInfo(Target &T) { TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator); } private: static MCSubtargetInfo *Allocator(StringRef TT, StringRef CPU, StringRef FS) { return new MCSubtargetInfoImpl(); } }; /// RegisterMCSubtargetInfoFn - Helper template for registering a target /// subtarget info implementation. This invokes the specified function to /// do the construction. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction); /// } struct RegisterMCSubtargetInfoFn { RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { TargetRegistry::RegisterMCSubtargetInfo(T, Fn); } }; /// RegisterTargetMachine - Helper template for registering a target machine /// implementation, for use in the target machine initialization /// function. Usage: /// /// extern "C" void LLVMInitializeFooTarget() { /// extern Target TheFooTarget; /// RegisterTargetMachine X(TheFooTarget); /// } template struct RegisterTargetMachine { RegisterTargetMachine(Target &T) { TargetRegistry::RegisterTargetMachine(T, &Allocator); } private: static TargetMachine *Allocator(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) { return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); } }; /// RegisterMCAsmBackend - Helper template for registering a target specific /// assembler backend. Usage: /// /// extern "C" void LLVMInitializeFooMCAsmBackend() { /// extern Target TheFooTarget; /// RegisterMCAsmBackend X(TheFooTarget); /// } template struct RegisterMCAsmBackend { RegisterMCAsmBackend(Target &T) { TargetRegistry::RegisterMCAsmBackend(T, &Allocator); } private: - static MCAsmBackend *Allocator(const Target &T, StringRef Triple) { - return new MCAsmBackendImpl(T, Triple); + static MCAsmBackend *Allocator(const Target &T, StringRef Triple, + StringRef CPU) { + return new MCAsmBackendImpl(T, Triple, CPU); } }; /// RegisterMCAsmLexer - Helper template for registering a target specific /// assembly lexer, for use in the target machine initialization /// function. Usage: /// /// extern "C" void LLVMInitializeFooMCAsmLexer() { /// extern Target TheFooTarget; /// RegisterMCAsmLexer X(TheFooTarget); /// } template struct RegisterMCAsmLexer { RegisterMCAsmLexer(Target &T) { TargetRegistry::RegisterMCAsmLexer(T, &Allocator); } private: static MCTargetAsmLexer *Allocator(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI) { return new MCAsmLexerImpl(T, MRI, MAI); } }; /// RegisterMCAsmParser - Helper template for registering a target specific /// assembly parser, for use in the target machine initialization /// function. Usage: /// /// extern "C" void LLVMInitializeFooMCAsmParser() { /// extern Target TheFooTarget; /// RegisterMCAsmParser X(TheFooTarget); /// } template struct RegisterMCAsmParser { RegisterMCAsmParser(Target &T) { TargetRegistry::RegisterMCAsmParser(T, &Allocator); } private: static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) { return new MCAsmParserImpl(STI, P); } }; /// RegisterAsmPrinter - Helper template for registering a target specific /// assembly printer, for use in the target machine initialization /// function. Usage: /// /// extern "C" void LLVMInitializeFooAsmPrinter() { /// extern Target TheFooTarget; /// RegisterAsmPrinter X(TheFooTarget); /// } template struct RegisterAsmPrinter { RegisterAsmPrinter(Target &T) { TargetRegistry::RegisterAsmPrinter(T, &Allocator); } private: static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) { return new AsmPrinterImpl(TM, Streamer); } }; /// RegisterMCCodeEmitter - Helper template for registering a target specific /// machine code emitter, for use in the target initialization /// function. Usage: /// /// extern "C" void LLVMInitializeFooMCCodeEmitter() { /// extern Target TheFooTarget; /// RegisterMCCodeEmitter X(TheFooTarget); /// } template struct RegisterMCCodeEmitter { RegisterMCCodeEmitter(Target &T) { TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); } private: static MCCodeEmitter *Allocator(const MCInstrInfo &II, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { return new MCCodeEmitterImpl(); } }; } #endif Index: head/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- head/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp (revision 241429) +++ head/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp (revision 241430) @@ -1,291 +1,291 @@ //===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the LLVMTargetMachine class. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar.h" #include "llvm/PassManager.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; // Enable or disable FastISel. Both options are needed, because // FastISel is enabled by default with -fast, and we wish to be // able to enable or disable fast-isel independently from -O0. static cl::opt EnableFastISelOption("fast-isel", cl::Hidden, cl::desc("Enable the \"fast\" instruction selector")); static cl::opt ShowMCEncoding("show-mc-encoding", cl::Hidden, cl::desc("Show encoding in .s output")); static cl::opt ShowMCInst("show-mc-inst", cl::Hidden, cl::desc("Show instruction structure in .s output")); static cl::opt AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(cl::BOU_UNSET)); static bool getVerboseAsm() { switch (AsmVerbose) { case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault(); case cl::BOU_TRUE: return true; case cl::BOU_FALSE: return false; } llvm_unreachable("Invalid verbose asm state"); } LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple, StringRef CPU, StringRef FS, TargetOptions Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) : TargetMachine(T, Triple, CPU, FS, Options) { CodeGenInfo = T.createMCCodeGenInfo(Triple, RM, CM, OL); AsmInfo = T.createMCAsmInfo(Triple); // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0, // and if the old one gets included then MCAsmInfo will be NULL and // we'll crash later. // Provide the user with a useful error message about what's wrong. assert(AsmInfo && "MCAsmInfo not initialized." "Make sure you include the correct TargetSelect.h" "and that InitializeAllTargetMCs() is being invoked!"); } /// addPassesToX helper drives creation and initialization of TargetPassConfig. static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM, bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) { // Targets may override createPassConfig to provide a target-specific sublass. TargetPassConfig *PassConfig = TM->createPassConfig(PM); PassConfig->setStartStopPasses(StartAfter, StopAfter); // Set PassConfig options provided by TargetMachine. PassConfig->setDisableVerify(DisableVerify); PM.add(PassConfig); PassConfig->addIRPasses(); PassConfig->addPassesToHandleExceptions(); PassConfig->addISelPrepare(); // Install a MachineModuleInfo class, which is an immutable pass that holds // all the per-module stuff we're generating, including MCContext. MachineModuleInfo *MMI = new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(), &TM->getTargetLowering()->getObjFileLowering()); PM.add(MMI); MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref. // Set up a MachineFunction for the rest of CodeGen to work on. PM.add(new MachineFunctionAnalysis(*TM)); // Enable FastISel with -fast, but allow that to be overridden. if (EnableFastISelOption == cl::BOU_TRUE || (TM->getOptLevel() == CodeGenOpt::None && EnableFastISelOption != cl::BOU_FALSE)) TM->setFastISel(true); // Ask the target for an isel. if (PassConfig->addInstSelector()) return NULL; PassConfig->addMachinePasses(); PassConfig->setInitialized(); return Context; } bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) { // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, StartAfter, StopAfter); if (!Context) return true; if (StopAfter) { // FIXME: The intent is that this should eventually write out a YAML file, // containing the LLVM IR, the machine-level IR (when stopping after a // machine-level pass), and whatever other information is needed to // deserialize the code and resume compilation. For now, just write the // LLVM IR. PM.add(createPrintModulePass(&Out)); return false; } if (hasMCSaveTempLabels()) Context->setAllowTemporaryLabels(false); const MCAsmInfo &MAI = *getMCAsmInfo(); const MCRegisterInfo &MRI = *getRegisterInfo(); const MCSubtargetInfo &STI = getSubtarget(); OwningPtr AsmStreamer; switch (FileType) { case CGFT_AssemblyFile: { MCInstPrinter *InstPrinter = getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, *getInstrInfo(), Context->getRegisterInfo(), STI); // Create a code emitter if asked to show the encoding. MCCodeEmitter *MCE = 0; MCAsmBackend *MAB = 0; if (ShowMCEncoding) { const MCSubtargetInfo &STI = getSubtarget(); MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI, STI, *Context); - MAB = getTarget().createMCAsmBackend(getTargetTriple()); + MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU); } MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, getVerboseAsm(), hasMCUseLoc(), hasMCUseCFI(), hasMCUseDwarfDirectory(), InstPrinter, MCE, MAB, ShowMCInst); AsmStreamer.reset(S); break; } case CGFT_ObjectFile: { // Create the code emitter for the target if it exists. If not, .o file // emission fails. MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI, STI, *Context); - MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple()); + MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU); if (MCE == 0 || MAB == 0) return true; AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Context, *MAB, Out, MCE, hasMCRelaxAll(), hasMCNoExecStack())); AsmStreamer.get()->InitSections(); break; } case CGFT_Null: // The Null output is intended for use for performance analysis and testing, // not real users. AsmStreamer.reset(createNullStreamer(*Context)); break; } // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); if (Printer == 0) return true; // If successful, createAsmPrinter took ownership of AsmStreamer. AsmStreamer.take(); PM.add(Printer); PM.add(createGCInfoDeleter()); return false; } /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a JITCodeEmitter object to handle /// actually outputting the machine code and resolving things like the address /// of functions. This method should returns true if machine code emission is /// not supported. /// bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &JCE, bool DisableVerify) { // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0); if (!Context) return true; addCodeEmitter(PM, JCE); PM.add(createGCInfoDeleter()); return false; // success! } /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be /// used to build custom MCStreamer. /// bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, raw_ostream &Out, bool DisableVerify) { // Add common CodeGen passes. Ctx = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0); if (!Ctx) return true; if (hasMCSaveTempLabels()) Ctx->setAllowTemporaryLabels(false); // Create the code emitter for the target if it exists. If not, .o file // emission fails. const MCRegisterInfo &MRI = *getRegisterInfo(); const MCSubtargetInfo &STI = getSubtarget(); MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI, STI, *Ctx); - MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple()); + MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU); if (MCE == 0 || MAB == 0) return true; OwningPtr AsmStreamer; AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Ctx, *MAB, Out, MCE, hasMCRelaxAll(), hasMCNoExecStack())); AsmStreamer.get()->InitSections(); // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); if (Printer == 0) return true; // If successful, createAsmPrinter took ownership of AsmStreamer. AsmStreamer.take(); PM.add(Printer); return false; // success! } Index: head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp =================================================================== --- head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (revision 241429) +++ head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (revision 241430) @@ -1,698 +1,698 @@ //===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/ARMMCTargetDesc.h" #include "MCTargetDesc/ARMBaseInfo.h" #include "MCTargetDesc/ARMFixupKinds.h" #include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class ARMELFObjectWriter : public MCELFObjectTargetWriter { public: ARMELFObjectWriter(uint8_t OSABI) : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, /*HasRelocationAddend*/ false) {} }; class ARMAsmBackend : public MCAsmBackend { const MCSubtargetInfo* STI; bool isThumbMode; // Currently emitting Thumb code. public: ARMAsmBackend(const Target &T, const StringRef TT) : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), isThumbMode(TT.startswith("thumb")) {} ~ARMAsmBackend() { delete STI; } unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } bool hasNOP() const { return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { // This table *must* be in the order that the fixup_* kinds are defined in // ARMFixupKinds.h. // // Name Offset (bits) Size (bits) Flags { "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. { "fixup_arm_movt_hi16", 0, 20, 0 }, { "fixup_arm_movw_lo16", 0, 20, 0 }, { "fixup_t2_movt_hi16", 0, 20, 0 }, { "fixup_t2_movw_lo16", 0, 20, 0 }, { "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, }; if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } /// processFixupValue - Target hook to process the literal value of a fixup /// if necessary. void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value, bool &IsResolved); bool mayNeedRelaxation(const MCInst &Inst) const; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const; void relaxInstruction(const MCInst &Inst, MCInst &Res) const; bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; void handleAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { default: break; case MCAF_Code16: setIsThumb(true); break; case MCAF_Code32: setIsThumb(false); break; } } unsigned getPointerSize() const { return 4; } bool isThumb() const { return isThumbMode; } void setIsThumb(bool it) { isThumbMode = it; } }; } // end anonymous namespace static unsigned getRelaxedOpcode(unsigned Op) { switch (Op) { default: return Op; case ARM::tBcc: return ARM::t2Bcc; case ARM::tLDRpciASM: return ARM::t2LDRpci; case ARM::tADR: return ARM::t2ADR; case ARM::tB: return ARM::t2B; } } bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) return true; return false; } bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { switch ((unsigned)Fixup.getKind()) { case ARM::fixup_arm_thumb_br: { // Relaxing tB to t2B. tB has a signed 12-bit displacement with the // low bit being an implied zero. There's an implied +4 offset for the // branch, so we adjust the other way here to determine what's // encodable. // // Relax if the value is too big for a (signed) i8. int64_t Offset = int64_t(Value) - 4; return Offset > 2046 || Offset < -2048; } case ARM::fixup_arm_thumb_bcc: { // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the // low bit being an implied zero. There's an implied +4 offset for the // branch, so we adjust the other way here to determine what's // encodable. // // Relax if the value is too big for a (signed) i8. int64_t Offset = int64_t(Value) - 4; return Offset > 254 || Offset < -256; } case ARM::fixup_thumb_adr_pcrel_10: case ARM::fixup_arm_thumb_cp: { // If the immediate is negative, greater than 1020, or not a multiple // of four, the wide version of the instruction must be used. int64_t Offset = int64_t(Value) - 4; return Offset > 1020 || Offset < 0 || Offset & 3; } } llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!"); } void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); // Sanity check w/ diagnostic if we get here w/ a bogus instruction. if (RelaxedOp == Inst.getOpcode()) { SmallString<256> Tmp; raw_svector_ostream OS(Tmp); Inst.dump_pretty(OS); OS << "\n"; report_fatal_error("unexpected instruction to relax: " + OS.str()); } // The instructions we're relaxing have (so far) the same operands. // We just need to update to the proper opcode. Res = Inst; Res.setOpcode(RelaxedOp); } bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0 const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP if (isThumb()) { const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; uint64_t NumNops = Count / 2; for (uint64_t i = 0; i != NumNops; ++i) OW->Write16(nopEncoding); if (Count & 1) OW->Write8(0); return true; } // ARM mode const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) OW->Write32(nopEncoding); // FIXME: should this function return false when unable to write exactly // 'Count' bytes with NOP encodings? switch (Count % 4) { default: break; // No leftover bytes to write case 1: OW->Write8(0); break; case 2: OW->Write16(0); break; case 3: OW->Write16(0); OW->Write8(0xa0); break; } return true; } static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, MCContext *Ctx = NULL) { unsigned Kind = Fixup.getKind(); switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); case FK_Data_1: case FK_Data_2: case FK_Data_4: return Value; case ARM::fixup_arm_movt_hi16: Value >>= 16; // Fallthrough case ARM::fixup_arm_movw_lo16: case ARM::fixup_arm_movt_hi16_pcrel: case ARM::fixup_arm_movw_lo16_pcrel: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned Lo12 = Value & 0x0FFF; // inst{19-16} = Hi4; // inst{11-0} = Lo12; Value = (Hi4 << 16) | (Lo12); return Value; } case ARM::fixup_t2_movt_hi16: Value >>= 16; // Fallthrough case ARM::fixup_t2_movw_lo16: case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like // the other hi16 fixup? case ARM::fixup_t2_movw_lo16_pcrel: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned i = (Value & 0x800) >> 11; unsigned Mid3 = (Value & 0x700) >> 8; unsigned Lo8 = Value & 0x0FF; // inst{19-16} = Hi4; // inst{26} = i; // inst{14-12} = Mid3; // inst{7-0} = Lo8; Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); uint64_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; return swapped; } case ARM::fixup_arm_ldst_pcrel_12: // ARM PC-relative values are offset by 8. Value -= 4; // FALLTHROUGH case ARM::fixup_t2_ldst_pcrel_12: { // Offset by 4, adjusted by two due to the half-word ordering of thumb. Value -= 4; bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; isAdd = false; } if (Ctx && Value >= 4096) Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); Value |= isAdd << 23; // Same addressing mode as fixup_arm_pcrel_10, // but with 16-bit halfwords swapped. if (Kind == ARM::fixup_t2_ldst_pcrel_12) { uint64_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; return swapped; } return Value; } case ARM::fixup_thumb_adr_pcrel_10: return ((Value - 4) >> 2) & 0xff; case ARM::fixup_arm_adr_pcrel_12: { // ARM PC-relative values are offset by 8. Value -= 8; unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 if ((int64_t)Value < 0) { Value = -Value; opc = 2; // 0b0010 } if (Ctx && ARM_AM::getSOImmVal(Value) == -1) Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); // Encode the immediate and shift the opcode into place. return ARM_AM::getSOImmVal(Value) | (opc << 21); } case ARM::fixup_t2_adr_pcrel_12: { Value -= 4; unsigned opc = 0; if ((int64_t)Value < 0) { Value = -Value; opc = 5; } uint32_t out = (opc << 21); out |= (Value & 0x800) << 15; out |= (Value & 0x700) << 4; out |= (Value & 0x0FF); uint64_t swapped = (out & 0xFFFF0000) >> 16; swapped |= (out & 0x0000FFFF) << 16; return swapped; } case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: case ARM::fixup_arm_uncondbl: case ARM::fixup_arm_condbl: case ARM::fixup_arm_blx: // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. return 0xffffff & ((Value - 8) >> 2); case ARM::fixup_t2_uncondbranch: { Value = Value - 4; Value >>= 1; // Low bit is not encoded. uint32_t out = 0; bool I = Value & 0x800000; bool J1 = Value & 0x400000; bool J2 = Value & 0x200000; J1 ^= I; J2 ^= I; out |= I << 26; // S bit out |= !J1 << 13; // J1 bit out |= !J2 << 11; // J2 bit out |= (Value & 0x1FF800) << 5; // imm6 field out |= (Value & 0x0007FF); // imm11 field uint64_t swapped = (out & 0xFFFF0000) >> 16; swapped |= (out & 0x0000FFFF) << 16; return swapped; } case ARM::fixup_t2_condbranch: { Value = Value - 4; Value >>= 1; // Low bit is not encoded. uint64_t out = 0; out |= (Value & 0x80000) << 7; // S bit out |= (Value & 0x40000) >> 7; // J2 bit out |= (Value & 0x20000) >> 4; // J1 bit out |= (Value & 0x1F800) << 5; // imm6 field out |= (Value & 0x007FF); // imm11 field uint32_t swapped = (out & 0xFFFF0000) >> 16; swapped |= (out & 0x0000FFFF) << 16; return swapped; } case ARM::fixup_arm_thumb_bl: { // The value doesn't encode the low bit (always zero) and is offset by // four. The 32-bit immediate value is encoded as // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). // The value is encoded into disjoint bit positions in the destination // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, // J = either J1 or J2 bit // // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII // // Note that the halfwords are stored high first, low second; so we need // to transpose the fixup value here to map properly. uint32_t offset = (Value - 4) >> 1; uint32_t signBit = (offset & 0x800000) >> 23; uint32_t I1Bit = (offset & 0x400000) >> 22; uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; uint32_t I2Bit = (offset & 0x200000) >> 21; uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; uint32_t imm10Bits = (offset & 0x1FF800) >> 11; uint32_t imm11Bits = (offset & 0x000007FF); uint32_t Binary = 0; uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | (uint16_t)imm11Bits); Binary |= secondHalf << 16; Binary |= firstHalf; return Binary; } case ARM::fixup_arm_thumb_blx: { // The value doesn't encode the low two bits (always zero) and is offset by // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00) // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). // The value is encoded into disjoint bit positions in the destination // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, // J = either J1 or J2 bit, 0 = zero. // // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0 // // Note that the halfwords are stored high first, low second; so we need // to transpose the fixup value here to map properly. uint32_t offset = (Value - 2) >> 2; uint32_t signBit = (offset & 0x400000) >> 22; uint32_t I1Bit = (offset & 0x200000) >> 21; uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; uint32_t I2Bit = (offset & 0x100000) >> 20; uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; uint32_t imm10HBits = (offset & 0xFFC00) >> 10; uint32_t imm10LBits = (offset & 0x3FF); uint32_t Binary = 0; uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | ((uint16_t)imm10LBits) << 1); Binary |= secondHalf << 16; Binary |= firstHalf; return Binary; } case ARM::fixup_arm_thumb_cp: // Offset by 4, and don't encode the low two bits. Two bytes of that // 'off by 4' is implicitly handled by the half-word ordering of the // Thumb encoding, so we only need to adjust by 2 here. return ((Value - 2) >> 2) & 0xff; case ARM::fixup_arm_thumb_cb: { // Offset by 4 and don't encode the lower bit, which is always 0. uint32_t Binary = (Value - 4) >> 1; return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); } case ARM::fixup_arm_thumb_br: // Offset by 4 and don't encode the lower bit, which is always 0. return ((Value - 4) >> 1) & 0x7ff; case ARM::fixup_arm_thumb_bcc: // Offset by 4 and don't encode the lower bit, which is always 0. return ((Value - 4) >> 1) & 0xff; case ARM::fixup_arm_pcrel_10_unscaled: { Value = Value - 8; // ARM fixups offset by an additional word and don't // need to adjust for the half-word ordering. bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; isAdd = false; } // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8]. if (Ctx && Value >= 256) Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); Value = (Value & 0xf) | ((Value & 0xf0) << 4); return Value | (isAdd << 23); } case ARM::fixup_arm_pcrel_10: Value = Value - 4; // ARM fixups offset by an additional word and don't // need to adjust for the half-word ordering. // Fall through. case ARM::fixup_t2_pcrel_10: { // Offset by 4, adjusted by two due to the half-word ordering of thumb. Value = Value - 4; bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; isAdd = false; } // These values don't encode the low two bits since they're always zero. Value >>= 2; if (Ctx && Value >= 256) Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); Value |= isAdd << 23; // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords // swapped. if (Kind == ARM::fixup_t2_pcrel_10) { uint32_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; return swapped; } return Value; } } } void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value, bool &IsResolved) { const MCSymbolRefExpr *A = Target.getSymA(); // Some fixups to thumb function symbols need the low bit (thumb bit) // twiddled. if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_arm_adr_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 && (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { if (A) { const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); if (Asm.isThumbFunc(&Sym)) Value |= 1; } } // We must always generate a relocation for BL/BLX instructions if we have // a symbol to reference, as the linker relies on knowing the destination // symbol's thumb-ness to get interworking right. if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl || (unsigned)Fixup.getKind() == ARM::fixup_arm_blx || (unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl || (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl)) IsResolved = false; // Try to get the encoded value for the fixup as-if we're mapping it into // the instruction. This allows adjustFixupValue() to issue a diagnostic // if the value aren't invalid. (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); } namespace { // FIXME: This should be in a separate file. // ELF is an ELF of course... class ELFARMAsmBackend : public ARMAsmBackend { public: uint8_t OSABI; ELFARMAsmBackend(const Target &T, const StringRef TT, uint8_t _OSABI) : ARMAsmBackend(T, TT), OSABI(_OSABI) { } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createARMELFObjectWriter(OS, OSABI); } }; // FIXME: Raise this to share code between Darwin and ELF. void ELFARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = 4; // FIXME: 2 for Thumb Value = adjustFixupValue(Fixup, Value); if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); // For each byte of the fragment that the fixup touches, mask in the bits from // the fixup value. The Value has been "split up" into the appropriate // bitfields above. for (unsigned i = 0; i != NumBytes; ++i) Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); } // FIXME: This should be in a separate file. class DarwinARMAsmBackend : public ARMAsmBackend { public: const object::mach::CPUSubtypeARM Subtype; DarwinARMAsmBackend(const Target &T, const StringRef TT, object::mach::CPUSubtypeARM st) : ARMAsmBackend(T, TT), Subtype(st) { } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createARMMachObjectWriter(OS, /*Is64Bit=*/false, object::mach::CTM_ARM, Subtype); } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; virtual bool doesSectionRequireSymbols(const MCSection &Section) const { return false; } }; /// getFixupKindNumBytes - The number of bytes the fixup may change. static unsigned getFixupKindNumBytes(unsigned Kind) { switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); case FK_Data_1: case ARM::fixup_arm_thumb_bcc: case ARM::fixup_arm_thumb_cp: case ARM::fixup_thumb_adr_pcrel_10: return 1; case FK_Data_2: case ARM::fixup_arm_thumb_br: case ARM::fixup_arm_thumb_cb: return 2; case ARM::fixup_arm_pcrel_10_unscaled: case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: case ARM::fixup_arm_uncondbl: case ARM::fixup_arm_condbl: case ARM::fixup_arm_blx: case ARM::fixup_arm_condbranch: case ARM::fixup_arm_uncondbranch: return 3; case FK_Data_4: case ARM::fixup_t2_ldst_pcrel_12: case ARM::fixup_t2_condbranch: case ARM::fixup_t2_uncondbranch: case ARM::fixup_t2_pcrel_10: case ARM::fixup_t2_adr_pcrel_12: case ARM::fixup_arm_thumb_bl: case ARM::fixup_arm_thumb_blx: case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movw_lo16: case ARM::fixup_arm_movt_hi16_pcrel: case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movt_hi16: case ARM::fixup_t2_movw_lo16: case ARM::fixup_t2_movt_hi16_pcrel: case ARM::fixup_t2_movw_lo16_pcrel: return 4; } } void DarwinARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); Value = adjustFixupValue(Fixup, Value); if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); // For each byte of the fragment that the fixup touches, mask in the // bits from the fixup value. for (unsigned i = 0; i != NumBytes; ++i) Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); } } // end anonymous namespace -MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT, StringRef CPU) { Triple TheTriple(TT); if (TheTriple.isOSDarwin()) { if (TheTriple.getArchName() == "armv4t" || TheTriple.getArchName() == "thumbv4t") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); else if (TheTriple.getArchName() == "armv5e" || TheTriple.getArchName() == "thumbv5e") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); else if (TheTriple.getArchName() == "armv6" || TheTriple.getArchName() == "thumbv6") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); } if (TheTriple.isOSWindows()) assert(0 && "Windows not supported on ARM"); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); return new ELFARMAsmBackend(T, TT, OSABI); } Index: head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h =================================================================== --- head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h (revision 241429) +++ head/contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h (revision 241430) @@ -1,77 +1,77 @@ //===-- ARMMCTargetDesc.h - ARM Target Descriptions -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides ARM specific target descriptions. // //===----------------------------------------------------------------------===// #ifndef ARMMCTARGETDESC_H #define ARMMCTARGETDESC_H #include "llvm/Support/DataTypes.h" #include namespace llvm { class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; class StringRef; class Target; class raw_ostream; extern Target TheARMTarget, TheThumbTarget; namespace ARM_MC { std::string ParseARMTriple(StringRef TT, StringRef CPU); /// createARMMCSubtargetInfo - Create a ARM MCSubtargetInfo instance. /// This is exposed so Asm parser, etc. do not need to go through /// TargetRegistry. MCSubtargetInfo *createARMMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS); } MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createARMAsmBackend(const Target &T, StringRef TT); +MCAsmBackend *createARMAsmBackend(const Target &T, StringRef TT, StringRef CPU); /// createARMELFObjectWriter - Construct an ELF Mach-O object writer. MCObjectWriter *createARMELFObjectWriter(raw_ostream &OS, uint8_t OSABI); /// createARMMachObjectWriter - Construct an ARM Mach-O object writer. MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype); } // End llvm namespace // Defines symbolic names for ARM registers. This defines a mapping from // register name to register number. // #define GET_REGINFO_ENUM #include "ARMGenRegisterInfo.inc" // Defines symbolic names for the ARM instructions. // #define GET_INSTRINFO_ENUM #include "ARMGenInstrInfo.inc" #define GET_SUBTARGETINFO_ENUM #include "ARMGenSubtargetInfo.inc" #endif Index: head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp =================================================================== --- head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp (revision 241429) +++ head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp (revision 241430) @@ -1,170 +1,171 @@ //===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/MBlazeMCTargetDesc.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCValue.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; static unsigned getFixupKindSize(unsigned Kind) { switch (Kind) { default: llvm_unreachable("invalid fixup kind!"); case FK_Data_1: return 1; case FK_PCRel_2: case FK_Data_2: return 2; case FK_PCRel_4: case FK_Data_4: return 4; case FK_Data_8: return 8; } } namespace { class MBlazeAsmBackend : public MCAsmBackend { public: MBlazeAsmBackend(const Target &T) : MCAsmBackend() { } unsigned getNumFixupKinds() const { return 2; } bool mayNeedRelaxation(const MCInst &Inst) const; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const; void relaxInstruction(const MCInst &Inst, MCInst &Res) const; bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; unsigned getPointerSize() const { return 4; } }; static unsigned getRelaxedOpcode(unsigned Op) { switch (Op) { default: return Op; case MBlaze::ADDIK: return MBlaze::ADDIK32; case MBlaze::ORI: return MBlaze::ORI32; case MBlaze::BRLID: return MBlaze::BRLID32; } } bool MBlazeAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode()) return false; bool hasExprOrImm = false; for (unsigned i = 0; i < Inst.getNumOperands(); ++i) hasExprOrImm |= Inst.getOperand(i).isExpr(); return hasExprOrImm; } bool MBlazeAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { // FIXME: Is this right? It's what the "generic" code was doing before, // but is X86 specific. Is it actually true for MBlaze also, or was it // just close enough to not be a big deal? // // Relax if the value is too big for a (signed) i8. return int64_t(Value) != int64_t(int8_t(Value)); } void MBlazeAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { Res = Inst; Res.setOpcode(getRelaxedOpcode(Inst.getOpcode())); } bool MBlazeAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { if ((Count % 4) != 0) return false; for (uint64_t i = 0; i < Count; i += 4) OW->Write32(0x00000000); return true; } } // end anonymous namespace namespace { class ELFMBlazeAsmBackend : public MBlazeAsmBackend { public: uint8_t OSABI; ELFMBlazeAsmBackend(const Target &T, uint8_t _OSABI) : MBlazeAsmBackend(T), OSABI(_OSABI) { } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createMBlazeELFObjectWriter(OS, OSABI); } }; void ELFMBlazeAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned Size = getFixupKindSize(Fixup.getKind()); assert(Fixup.getOffset() + Size <= DataSize && "Invalid fixup offset!"); char *data = Data + Fixup.getOffset(); switch (Size) { default: llvm_unreachable("Cannot fixup unknown value."); case 1: llvm_unreachable("Cannot fixup 1 byte value."); case 8: llvm_unreachable("Cannot fixup 8 byte value."); case 4: *(data+7) = uint8_t(Value); *(data+6) = uint8_t(Value >> 8); *(data+3) = uint8_t(Value >> 16); *(data+2) = uint8_t(Value >> 24); break; case 2: *(data+3) = uint8_t(Value >> 0); *(data+2) = uint8_t(Value >> 8); } } } // end anonymous namespace -MCAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, StringRef TT, + StringRef CPU) { Triple TheTriple(TT); if (TheTriple.isOSDarwin()) assert(0 && "Mac not supported on MBlaze"); if (TheTriple.isOSWindows()) assert(0 && "Windows not supported on MBlaze"); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); return new ELFMBlazeAsmBackend(T, OSABI); } Index: head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h =================================================================== --- head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h (revision 241429) +++ head/contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h (revision 241430) @@ -1,55 +1,56 @@ //===-- MBlazeMCTargetDesc.h - MBlaze Target Descriptions -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides MBlaze specific target descriptions. // //===----------------------------------------------------------------------===// #ifndef MBLAZEMCTARGETDESC_H #define MBLAZEMCTARGETDESC_H #include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmBackend; class MCContext; class MCCodeEmitter; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; class Target; class StringRef; class raw_ostream; extern Target TheMBlazeTarget; MCCodeEmitter *createMBlazeMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createMBlazeAsmBackend(const Target &T, StringRef TT); +MCAsmBackend *createMBlazeAsmBackend(const Target &T, StringRef TT, + StringRef CPU); MCObjectWriter *createMBlazeELFObjectWriter(raw_ostream &OS, uint8_t OSABI); } // End llvm namespace // Defines symbolic names for MBlaze registers. This defines a mapping from // register name to register number. #define GET_REGINFO_ENUM #include "MBlazeGenRegisterInfo.inc" // Defines symbolic names for the MBlaze instructions. #define GET_INSTRINFO_ENUM #include "MBlazeGenInstrInfo.inc" #define GET_SUBTARGETINFO_ENUM #include "MBlazeGenSubtargetInfo.inc" #endif Index: head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp =================================================================== --- head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp (revision 241429) +++ head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp (revision 241430) @@ -1,266 +1,270 @@ //===-- MipsASMBackend.cpp - Mips Asm Backend ----------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the MipsAsmBackend and MipsELFObjectWriter classes. // //===----------------------------------------------------------------------===// // #include "MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; // Prepare value for the target space for it static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // Add/subtract and shift switch (Kind) { default: return 0; case FK_GPRel_4: case FK_Data_4: case FK_Data_8: case Mips::fixup_Mips_LO16: case Mips::fixup_Mips_GPOFF_HI: case Mips::fixup_Mips_GPOFF_LO: case Mips::fixup_Mips_GOT_PAGE: case Mips::fixup_Mips_GOT_OFST: case Mips::fixup_Mips_GOT_DISP: break; case Mips::fixup_Mips_PC16: // So far we are only using this type for branches. // For branches we start 1 instruction after the branch // so the displacement will be one instruction size less. Value -= 4; // The displacement is then divided by 4 to give us an 18 bit // address range. Value >>= 2; break; case Mips::fixup_Mips_26: // So far we are only using this type for jumps. // The displacement is then divided by 4 to give us an 28 bit // address range. Value >>= 2; break; case Mips::fixup_Mips_HI16: case Mips::fixup_Mips_GOT_Local: // Get the 2nd 16-bits. Also add 1 if bit 15 is 1. Value = ((Value + 0x8000) >> 16) & 0xffff; break; case Mips::fixup_Mips_HIGHER: // Get the 3rd 16-bits. Value = ((Value + 0x80008000LL) >> 32) & 0xffff; break; case Mips::fixup_Mips_HIGHEST: // Get the 4th 16-bits. Value = ((Value + 0x800080008000LL) >> 48) & 0xffff; break; } return Value; } namespace { class MipsAsmBackend : public MCAsmBackend { Triple::OSType OSType; bool IsLittle; // Big or little endian bool Is64Bit; // 32 or 64 bit words public: MipsAsmBackend(const Target &T, Triple::OSType _OSType, bool _isLittle, bool _is64Bit) :MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), Is64Bit(_is64Bit) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createMipsELFObjectWriter(OS, MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit); } /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { MCFixupKind Kind = Fixup.getKind(); Value = adjustFixupValue((unsigned)Kind, Value); if (!Value) return; // Doesn't change encoding. // Where do we start in the object unsigned Offset = Fixup.getOffset(); // Number of bytes we need to fixup unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; // Used to point to big endian bytes unsigned FullSize; switch ((unsigned)Kind) { case Mips::fixup_Mips_16: FullSize = 2; break; case Mips::fixup_Mips_64: FullSize = 8; break; default: FullSize = 4; break; } // Grab current value, if any, from bits. uint64_t CurVal = 0; for (unsigned i = 0; i != NumBytes; ++i) { unsigned Idx = IsLittle ? i : (FullSize - 1 - i); CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); } uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize)); CurVal |= Value & Mask; // Write out the fixed up bytes back to the code/data bits. for (unsigned i = 0; i != NumBytes; ++i) { unsigned Idx = IsLittle ? i : (FullSize - 1 - i); Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); } } unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { // This table *must* be in same the order of fixup_* kinds in // MipsFixupKinds.h. // // name offset bits flags { "fixup_Mips_16", 0, 16, 0 }, { "fixup_Mips_32", 0, 32, 0 }, { "fixup_Mips_REL32", 0, 32, 0 }, { "fixup_Mips_26", 0, 26, 0 }, { "fixup_Mips_HI16", 0, 16, 0 }, { "fixup_Mips_LO16", 0, 16, 0 }, { "fixup_Mips_GPREL16", 0, 16, 0 }, { "fixup_Mips_LITERAL", 0, 16, 0 }, { "fixup_Mips_GOT_Global", 0, 16, 0 }, { "fixup_Mips_GOT_Local", 0, 16, 0 }, { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_CALL16", 0, 16, 0 }, { "fixup_Mips_GPREL32", 0, 32, 0 }, { "fixup_Mips_SHIFT5", 6, 5, 0 }, { "fixup_Mips_SHIFT6", 6, 5, 0 }, { "fixup_Mips_64", 0, 64, 0 }, { "fixup_Mips_TLSGD", 0, 16, 0 }, { "fixup_Mips_GOTTPREL", 0, 16, 0 }, { "fixup_Mips_TPREL_HI", 0, 16, 0 }, { "fixup_Mips_TPREL_LO", 0, 16, 0 }, { "fixup_Mips_TLSLDM", 0, 16, 0 }, { "fixup_Mips_DTPREL_HI", 0, 16, 0 }, { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_GPOFF_HI", 0, 16, 0 }, { "fixup_Mips_GPOFF_LO", 0, 16, 0 }, { "fixup_Mips_GOT_PAGE", 0, 16, 0 }, { "fixup_Mips_GOT_OFST", 0, 16, 0 }, { "fixup_Mips_GOT_DISP", 0, 16, 0 }, { "fixup_Mips_HIGHER", 0, 16, 0 }, { "fixup_Mips_HIGHEST", 0, 16, 0 } }; if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } /// @name Target Relaxation Interfaces /// @{ /// MayNeedRelaxation - Check whether the given instruction may need /// relaxation. /// /// \param Inst - The instruction to test. bool mayNeedRelaxation(const MCInst &Inst) const { return false; } /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { // FIXME. assert(0 && "RelaxInstruction() unimplemented"); return false; } /// RelaxInstruction - Relax the instruction in the given fragment /// to the next wider instruction. /// /// \param Inst - The instruction to relax, which may be the same /// as the output. /// \parm Res [output] - On return, the relaxed instruction. void relaxInstruction(const MCInst &Inst, MCInst &Res) const { } /// @} /// WriteNopData - Write an (optimal) nop sequence of Count bytes /// to the given output. If the target cannot generate such a sequence, /// it should return an error. /// /// \return - True on success. bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { // Check for a less than instruction size number of bytes // FIXME: 16 bit instructions are not handled yet here. // We shouldn't be using a hard coded number for instruction size. if (Count % 4) return false; uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) OW->Write32(0); return true; } }; // class MipsAsmBackend } // namespace // MCAsmBackend -MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T, StringRef TT, + StringRef CPU) { return new MipsAsmBackend(T, Triple(TT).getOS(), /*IsLittle*/true, /*Is64Bit*/false); } -MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T, StringRef TT, + StringRef CPU) { return new MipsAsmBackend(T, Triple(TT).getOS(), /*IsLittle*/false, /*Is64Bit*/false); } -MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T, StringRef TT, + StringRef CPU) { return new MipsAsmBackend(T, Triple(TT).getOS(), /*IsLittle*/true, /*Is64Bit*/true); } -MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T, StringRef TT, + StringRef CPU) { return new MipsAsmBackend(T, Triple(TT).getOS(), /*IsLittle*/false, /*Is64Bit*/true); } Index: head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h =================================================================== --- head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h (revision 241429) +++ head/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h (revision 241430) @@ -1,68 +1,72 @@ //===-- MipsMCTargetDesc.h - Mips Target Descriptions -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides Mips specific target descriptions. // //===----------------------------------------------------------------------===// #ifndef MIPSMCTARGETDESC_H #define MIPSMCTARGETDESC_H #include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; class StringRef; class Target; class raw_ostream; extern Target TheMipsTarget; extern Target TheMipselTarget; extern Target TheMips64Target; extern Target TheMips64elTarget; MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createMipsAsmBackendEB32(const Target &T, StringRef TT); -MCAsmBackend *createMipsAsmBackendEL32(const Target &T, StringRef TT); -MCAsmBackend *createMipsAsmBackendEB64(const Target &T, StringRef TT); -MCAsmBackend *createMipsAsmBackendEL64(const Target &T, StringRef TT); +MCAsmBackend *createMipsAsmBackendEB32(const Target &T, StringRef TT, + StringRef CPU); +MCAsmBackend *createMipsAsmBackendEL32(const Target &T, StringRef TT, + StringRef CPU); +MCAsmBackend *createMipsAsmBackendEB64(const Target &T, StringRef TT, + StringRef CPU); +MCAsmBackend *createMipsAsmBackendEL64(const Target &T, StringRef TT, + StringRef CPU); MCObjectWriter *createMipsELFObjectWriter(raw_ostream &OS, uint8_t OSABI, bool IsLittleEndian, bool Is64Bit); } // End llvm namespace // Defines symbolic names for Mips registers. This defines a mapping from // register name to register number. #define GET_REGINFO_ENUM #include "MipsGenRegisterInfo.inc" // Defines symbolic names for the Mips instructions. #define GET_INSTRINFO_ENUM #include "MipsGenInstrInfo.inc" #define GET_SUBTARGETINFO_ENUM #include "MipsGenSubtargetInfo.inc" #endif Index: head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp =================================================================== --- head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp (revision 241429) +++ head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp (revision 241430) @@ -1,190 +1,190 @@ //===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/PPCMCTargetDesc.h" #include "MCTargetDesc/PPCFixupKinds.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); case FK_Data_1: case FK_Data_2: case FK_Data_4: return Value; case PPC::fixup_ppc_brcond14: return Value & 0x3ffc; case PPC::fixup_ppc_br24: return Value & 0x3fffffc; #if 0 case PPC::fixup_ppc_hi16: return (Value >> 16) & 0xffff; #endif case PPC::fixup_ppc_ha16: return ((Value >> 16) + ((Value & 0x8000) ? 1 : 0)) & 0xffff; case PPC::fixup_ppc_lo16: return Value & 0xffff; } } namespace { class PPCMachObjectWriter : public MCMachObjectTargetWriter { public: PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) {} }; class PPCAsmBackend : public MCAsmBackend { const Target &TheTarget; public: PPCAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} unsigned getNumFixupKinds() const { return PPC::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[PPC::NumTargetFixupKinds] = { // name offset bits flags { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_lo16", 16, 16, 0 }, { "fixup_ppc_ha16", 16, 16, 0 }, { "fixup_ppc_lo14", 16, 14, 0 } }; if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } bool mayNeedRelaxation(const MCInst &Inst) const { // FIXME. return false; } bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { // FIXME. llvm_unreachable("relaxInstruction() unimplemented"); } void relaxInstruction(const MCInst &Inst, MCInst &Res) const { // FIXME. llvm_unreachable("relaxInstruction() unimplemented"); } bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { // FIXME: Zero fill for now. That's not right, but at least will get the // section size right. for (uint64_t i = 0; i != Count; ++i) OW->Write8(0); return true; } unsigned getPointerSize() const { StringRef Name = TheTarget.getName(); if (Name == "ppc64") return 8; assert(Name == "ppc32" && "Unknown target name!"); return 4; } }; } // end anonymous namespace // FIXME: This should be in a separate file. namespace { class DarwinPPCAsmBackend : public PPCAsmBackend { public: DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T) { } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { llvm_unreachable("UNIMP"); } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { bool is64 = getPointerSize() == 8; return createMachObjectWriter(new PPCMachObjectWriter( /*Is64Bit=*/is64, (is64 ? object::mach::CTM_PowerPC64 : object::mach::CTM_PowerPC), object::mach::CSPPC_ALL), OS, /*IsLittleEndian=*/false); } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { return false; } }; class ELFPPCAsmBackend : public PPCAsmBackend { uint8_t OSABI; public: ELFPPCAsmBackend(const Target &T, uint8_t OSABI) : PPCAsmBackend(T), OSABI(OSABI) { } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); // For each byte of the fragment that the fixup touches, mask in the bits from // the fixup value. The Value has been "split up" into the appropriate // bitfields above. for (unsigned i = 0; i != 4; ++i) Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { bool is64 = getPointerSize() == 8; return createPPCELFObjectWriter(OS, is64, OSABI); } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { return false; } }; } // end anonymous namespace -MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU) { if (Triple(TT).isOSDarwin()) return new DarwinPPCAsmBackend(T); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); return new ELFPPCAsmBackend(T, OSABI); } Index: head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h =================================================================== --- head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h (revision 241429) +++ head/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h (revision 241430) @@ -1,61 +1,61 @@ //===-- PPCMCTargetDesc.h - PowerPC Target Descriptions ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides PowerPC specific target descriptions. // //===----------------------------------------------------------------------===// #ifndef PPCMCTARGETDESC_H #define PPCMCTARGETDESC_H #include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; class Target; class StringRef; class raw_ostream; extern Target ThePPC32Target; extern Target ThePPC64Target; MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT); +MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU); /// createPPCELFObjectWriter - Construct an PPC ELF object writer. MCObjectWriter *createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI); } // End llvm namespace // Defines symbolic names for PowerPC registers. This defines a mapping from // register name to register number. // #define GET_REGINFO_ENUM #include "PPCGenRegisterInfo.inc" // Defines symbolic names for the PowerPC instructions. // #define GET_INSTRINFO_ENUM #include "PPCGenInstrInfo.inc" #define GET_SUBTARGETINFO_ENUM #include "PPCGenSubtargetInfo.inc" #endif Index: head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp =================================================================== --- head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (revision 241429) +++ head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (revision 241430) @@ -1,466 +1,474 @@ //===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/X86BaseInfo.h" #include "MCTargetDesc/X86FixupKinds.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; // Option to allow disabling arithmetic relaxation to workaround PR9807, which // is useful when running bitwise comparison experiments on Darwin. We should be // able to remove this once PR9807 is resolved. static cl::opt MCDisableArithRelaxation("mc-x86-disable-arith-relaxation", cl::desc("Disable relaxation of arithmetic instruction for X86")); static unsigned getFixupKindLog2Size(unsigned Kind) { switch (Kind) { default: llvm_unreachable("invalid fixup kind!"); case FK_PCRel_1: case FK_SecRel_1: case FK_Data_1: return 0; case FK_PCRel_2: case FK_SecRel_2: case FK_Data_2: return 1; case FK_PCRel_4: case X86::reloc_riprel_4byte: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: case X86::reloc_global_offset_table: case FK_SecRel_4: case FK_Data_4: return 2; case FK_PCRel_8: case FK_SecRel_8: case FK_Data_8: return 3; } } namespace { class X86ELFObjectWriter : public MCELFObjectTargetWriter { public: X86ELFObjectWriter(bool is64Bit, uint8_t OSABI, uint16_t EMachine, bool HasRelocationAddend, bool foobar) : MCELFObjectTargetWriter(is64Bit, OSABI, EMachine, HasRelocationAddend) {} }; class X86AsmBackend : public MCAsmBackend { + StringRef CPU; public: - X86AsmBackend(const Target &T) - : MCAsmBackend() {} + X86AsmBackend(const Target &T, StringRef _CPU) + : MCAsmBackend(), CPU(_CPU) {} unsigned getNumFixupKinds() const { return X86::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel}, { "reloc_signed_4byte", 0, 4 * 8, 0}, { "reloc_global_offset_table", 0, 4 * 8, 0} }; if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind()); assert(Fixup.getOffset() + Size <= DataSize && "Invalid fixup offset!"); // Check that uppper bits are either all zeros or all ones. // Specifically ignore overflow/underflow as long as the leakage is // limited to the lower bits. This is to remain compatible with // other assemblers. assert(isIntN(Size * 8 + 1, Value) && "Value does not fit in the Fixup field"); for (unsigned i = 0; i != Size; ++i) Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8)); } bool mayNeedRelaxation(const MCInst &Inst) const; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const; void relaxInstruction(const MCInst &Inst, MCInst &Res) const; bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; }; } // end anonymous namespace static unsigned getRelaxedOpcodeBranch(unsigned Op) { switch (Op) { default: return Op; case X86::JAE_1: return X86::JAE_4; case X86::JA_1: return X86::JA_4; case X86::JBE_1: return X86::JBE_4; case X86::JB_1: return X86::JB_4; case X86::JE_1: return X86::JE_4; case X86::JGE_1: return X86::JGE_4; case X86::JG_1: return X86::JG_4; case X86::JLE_1: return X86::JLE_4; case X86::JL_1: return X86::JL_4; case X86::JMP_1: return X86::JMP_4; case X86::JNE_1: return X86::JNE_4; case X86::JNO_1: return X86::JNO_4; case X86::JNP_1: return X86::JNP_4; case X86::JNS_1: return X86::JNS_4; case X86::JO_1: return X86::JO_4; case X86::JP_1: return X86::JP_4; case X86::JS_1: return X86::JS_4; } } static unsigned getRelaxedOpcodeArith(unsigned Op) { switch (Op) { default: return Op; // IMUL case X86::IMUL16rri8: return X86::IMUL16rri; case X86::IMUL16rmi8: return X86::IMUL16rmi; case X86::IMUL32rri8: return X86::IMUL32rri; case X86::IMUL32rmi8: return X86::IMUL32rmi; case X86::IMUL64rri8: return X86::IMUL64rri32; case X86::IMUL64rmi8: return X86::IMUL64rmi32; // AND case X86::AND16ri8: return X86::AND16ri; case X86::AND16mi8: return X86::AND16mi; case X86::AND32ri8: return X86::AND32ri; case X86::AND32mi8: return X86::AND32mi; case X86::AND64ri8: return X86::AND64ri32; case X86::AND64mi8: return X86::AND64mi32; // OR case X86::OR16ri8: return X86::OR16ri; case X86::OR16mi8: return X86::OR16mi; case X86::OR32ri8: return X86::OR32ri; case X86::OR32mi8: return X86::OR32mi; case X86::OR64ri8: return X86::OR64ri32; case X86::OR64mi8: return X86::OR64mi32; // XOR case X86::XOR16ri8: return X86::XOR16ri; case X86::XOR16mi8: return X86::XOR16mi; case X86::XOR32ri8: return X86::XOR32ri; case X86::XOR32mi8: return X86::XOR32mi; case X86::XOR64ri8: return X86::XOR64ri32; case X86::XOR64mi8: return X86::XOR64mi32; // ADD case X86::ADD16ri8: return X86::ADD16ri; case X86::ADD16mi8: return X86::ADD16mi; case X86::ADD32ri8: return X86::ADD32ri; case X86::ADD32mi8: return X86::ADD32mi; case X86::ADD64ri8: return X86::ADD64ri32; case X86::ADD64mi8: return X86::ADD64mi32; // SUB case X86::SUB16ri8: return X86::SUB16ri; case X86::SUB16mi8: return X86::SUB16mi; case X86::SUB32ri8: return X86::SUB32ri; case X86::SUB32mi8: return X86::SUB32mi; case X86::SUB64ri8: return X86::SUB64ri32; case X86::SUB64mi8: return X86::SUB64mi32; // CMP case X86::CMP16ri8: return X86::CMP16ri; case X86::CMP16mi8: return X86::CMP16mi; case X86::CMP32ri8: return X86::CMP32ri; case X86::CMP32mi8: return X86::CMP32mi; case X86::CMP64ri8: return X86::CMP64ri32; case X86::CMP64mi8: return X86::CMP64mi32; // PUSH case X86::PUSHi8: return X86::PUSHi32; case X86::PUSHi16: return X86::PUSHi32; case X86::PUSH64i8: return X86::PUSH64i32; case X86::PUSH64i16: return X86::PUSH64i32; } } static unsigned getRelaxedOpcode(unsigned Op) { unsigned R = getRelaxedOpcodeArith(Op); if (R != Op) return R; return getRelaxedOpcodeBranch(Op); } bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { // Branches can always be relaxed. if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode()) return true; if (MCDisableArithRelaxation) return false; // Check if this instruction is ever relaxable. if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode()) return false; // Check if it has an expression and is not RIP relative. bool hasExp = false; bool hasRIP = false; for (unsigned i = 0; i < Inst.getNumOperands(); ++i) { const MCOperand &Op = Inst.getOperand(i); if (Op.isExpr()) hasExp = true; if (Op.isReg() && Op.getReg() == X86::RIP) hasRIP = true; } // FIXME: Why exactly do we need the !hasRIP? Is it just a limitation on // how we do relaxations? return hasExp && !hasRIP; } bool X86AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCInstFragment *DF, const MCAsmLayout &Layout) const { // Relax if the value is too big for a (signed) i8. return int64_t(Value) != int64_t(int8_t(Value)); } // FIXME: Can tblgen help at all here to verify there aren't other instructions // we can relax? void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { // The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel. unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); if (RelaxedOp == Inst.getOpcode()) { SmallString<256> Tmp; raw_svector_ostream OS(Tmp); Inst.dump_pretty(OS); OS << "\n"; report_fatal_error("unexpected instruction to relax: " + OS.str()); } Res = Inst; Res.setOpcode(RelaxedOp); } /// writeNopData - Write optimal nops to the output file for the \arg Count /// bytes. This returns the number of bytes written. It may return 0 if /// the \arg Count is more than the maximum optimal nops. bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { static const uint8_t Nops[10][10] = { // nop {0x90}, // xchg %ax,%ax {0x66, 0x90}, // nopl (%[re]ax) {0x0f, 0x1f, 0x00}, // nopl 0(%[re]ax) {0x0f, 0x1f, 0x40, 0x00}, // nopl 0(%[re]ax,%[re]ax,1) {0x0f, 0x1f, 0x44, 0x00, 0x00}, // nopw 0(%[re]ax,%[re]ax,1) {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, // nopl 0L(%[re]ax) {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, // nopl 0L(%[re]ax,%[re]ax,1) {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, // nopw 0L(%[re]ax,%[re]ax,1) {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, // nopw %cs:0L(%[re]ax,%[re]ax,1) {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, }; + // This CPU doesnt support long nops. If needed add more. + if (CPU == "geode") { + for (uint64_t i = 0; i < Count; ++i) + OW->Write8(0x90); + return true; + } + // Write an optimal sequence for the first 15 bytes. const uint64_t OptimalCount = (Count < 16) ? Count : 15; const uint64_t Prefixes = OptimalCount <= 10 ? 0 : OptimalCount - 10; for (uint64_t i = 0, e = Prefixes; i != e; i++) OW->Write8(0x66); const uint64_t Rest = OptimalCount - Prefixes; for (uint64_t i = 0, e = Rest; i != e; i++) OW->Write8(Nops[Rest - 1][i]); // Finish with single byte nops. for (uint64_t i = OptimalCount, e = Count; i != e; ++i) OW->Write8(0x90); return true; } /* *** */ namespace { class ELFX86AsmBackend : public X86AsmBackend { public: uint8_t OSABI; - ELFX86AsmBackend(const Target &T, uint8_t _OSABI) - : X86AsmBackend(T), OSABI(_OSABI) { + ELFX86AsmBackend(const Target &T, uint8_t _OSABI, StringRef CPU) + : X86AsmBackend(T, CPU), OSABI(_OSABI) { HasReliableSymbolDifference = true; } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { const MCSectionELF &ES = static_cast(Section); return ES.getFlags() & ELF::SHF_MERGE; } }; class ELFX86_32AsmBackend : public ELFX86AsmBackend { public: - ELFX86_32AsmBackend(const Target &T, uint8_t OSABI) - : ELFX86AsmBackend(T, OSABI) {} + ELFX86_32AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) + : ELFX86AsmBackend(T, OSABI, CPU) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createX86ELFObjectWriter(OS, /*Is64Bit*/ false, OSABI); } }; class ELFX86_64AsmBackend : public ELFX86AsmBackend { public: - ELFX86_64AsmBackend(const Target &T, uint8_t OSABI) - : ELFX86AsmBackend(T, OSABI) {} + ELFX86_64AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) + : ELFX86AsmBackend(T, OSABI, CPU) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createX86ELFObjectWriter(OS, /*Is64Bit*/ true, OSABI); } }; class WindowsX86AsmBackend : public X86AsmBackend { bool Is64Bit; public: - WindowsX86AsmBackend(const Target &T, bool is64Bit) - : X86AsmBackend(T) + WindowsX86AsmBackend(const Target &T, bool is64Bit, StringRef CPU) + : X86AsmBackend(T, CPU) , Is64Bit(is64Bit) { } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createX86WinCOFFObjectWriter(OS, Is64Bit); } }; class DarwinX86AsmBackend : public X86AsmBackend { public: - DarwinX86AsmBackend(const Target &T) - : X86AsmBackend(T) { } + DarwinX86AsmBackend(const Target &T, StringRef CPU) + : X86AsmBackend(T, CPU) { } }; class DarwinX86_32AsmBackend : public DarwinX86AsmBackend { public: - DarwinX86_32AsmBackend(const Target &T) - : DarwinX86AsmBackend(T) {} + DarwinX86_32AsmBackend(const Target &T, StringRef CPU) + : DarwinX86AsmBackend(T, CPU) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createX86MachObjectWriter(OS, /*Is64Bit=*/false, object::mach::CTM_i386, object::mach::CSX86_ALL); } }; class DarwinX86_64AsmBackend : public DarwinX86AsmBackend { public: - DarwinX86_64AsmBackend(const Target &T) - : DarwinX86AsmBackend(T) { + DarwinX86_64AsmBackend(const Target &T, StringRef CPU) + : DarwinX86AsmBackend(T, CPU) { HasReliableSymbolDifference = true; } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createX86MachObjectWriter(OS, /*Is64Bit=*/true, object::mach::CTM_x86_64, object::mach::CSX86_ALL); } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { // Temporary labels in the string literals sections require symbols. The // issue is that the x86_64 relocation format does not allow symbol + // offset, and so the linker does not have enough information to resolve the // access to the appropriate atom unless an external relocation is used. For // non-cstring sections, we expect the compiler to use a non-temporary label // for anything that could have an addend pointing outside the symbol. // // See . const MCSectionMachO &SMO = static_cast(Section); return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS; } virtual bool isSectionAtomizable(const MCSection &Section) const { const MCSectionMachO &SMO = static_cast(Section); // Fixed sized data sections are uniqued, they cannot be diced into atoms. switch (SMO.getType()) { default: return true; case MCSectionMachO::S_4BYTE_LITERALS: case MCSectionMachO::S_8BYTE_LITERALS: case MCSectionMachO::S_16BYTE_LITERALS: case MCSectionMachO::S_LITERAL_POINTERS: case MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS: case MCSectionMachO::S_LAZY_SYMBOL_POINTERS: case MCSectionMachO::S_MOD_INIT_FUNC_POINTERS: case MCSectionMachO::S_MOD_TERM_FUNC_POINTERS: case MCSectionMachO::S_INTERPOSING: return false; } } }; } // end anonymous namespace -MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, StringRef TT, StringRef CPU) { Triple TheTriple(TT); if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) - return new DarwinX86_32AsmBackend(T); + return new DarwinX86_32AsmBackend(T, CPU); if (TheTriple.isOSWindows()) - return new WindowsX86AsmBackend(T, false); + return new WindowsX86AsmBackend(T, false, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); - return new ELFX86_32AsmBackend(T, OSABI); + return new ELFX86_32AsmBackend(T, OSABI, CPU); } -MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, StringRef TT) { +MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, StringRef TT, StringRef CPU) { Triple TheTriple(TT); if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) - return new DarwinX86_64AsmBackend(T); + return new DarwinX86_64AsmBackend(T, CPU); if (TheTriple.isOSWindows()) - return new WindowsX86AsmBackend(T, true); + return new WindowsX86AsmBackend(T, true, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); - return new ELFX86_64AsmBackend(T, OSABI); + return new ELFX86_64AsmBackend(T, OSABI, CPU); } Index: head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h =================================================================== --- head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h (revision 241429) +++ head/contrib/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h (revision 241430) @@ -1,115 +1,115 @@ //===-- X86MCTargetDesc.h - X86 Target Descriptions -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides X86 specific target descriptions. // //===----------------------------------------------------------------------===// #ifndef X86MCTARGETDESC_H #define X86MCTARGETDESC_H #include "llvm/Support/DataTypes.h" #include namespace llvm { class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; class Target; class StringRef; class raw_ostream; extern Target TheX86_32Target, TheX86_64Target; /// DWARFFlavour - Flavour of dwarf regnumbers /// namespace DWARFFlavour { enum { X86_64 = 0, X86_32_DarwinEH = 1, X86_32_Generic = 2 }; } /// N86 namespace - Native X86 register numbers /// namespace N86 { enum { EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7 }; } namespace X86_MC { std::string ParseX86Triple(StringRef TT); /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in /// the specified arguments. If we can't run cpuid on the host, return true. bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX); /// GetCpuIDAndInfoEx - Execute the specified cpuid with subleaf and return /// the 4 values in the specified arguments. If we can't run cpuid on the /// host, return true. bool GetCpuIDAndInfoEx(unsigned value, unsigned subleaf, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX); void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model); unsigned getDwarfRegFlavour(StringRef TT, bool isEH); unsigned getX86RegNum(unsigned RegNo); void InitLLVM2SEHRegisterMapping(MCRegisterInfo *MRI); /// createX86MCSubtargetInfo - Create a X86 MCSubtargetInfo instance. /// This is exposed so Asm parser, etc. do not need to go through /// TargetRegistry. MCSubtargetInfo *createX86MCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS); } MCCodeEmitter *createX86MCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createX86_32AsmBackend(const Target &T, StringRef TT); -MCAsmBackend *createX86_64AsmBackend(const Target &T, StringRef TT); +MCAsmBackend *createX86_32AsmBackend(const Target &T, StringRef TT, StringRef CPU); +MCAsmBackend *createX86_64AsmBackend(const Target &T, StringRef TT, StringRef CPU); /// createX86MachObjectWriter - Construct an X86 Mach-O object writer. MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS, bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype); /// createX86ELFObjectWriter - Construct an X86 ELF object writer. MCObjectWriter *createX86ELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI); /// createX86WinCOFFObjectWriter - Construct an X86 Win COFF object writer. MCObjectWriter *createX86WinCOFFObjectWriter(raw_ostream &OS, bool Is64Bit); } // End llvm namespace // Defines symbolic names for X86 registers. This defines a mapping from // register name to register number. // #define GET_REGINFO_ENUM #include "X86GenRegisterInfo.inc" // Defines symbolic names for the X86 instructions. // #define GET_INSTRINFO_ENUM #include "X86GenInstrInfo.inc" #define GET_SUBTARGETINFO_ENUM #include "X86GenSubtargetInfo.inc" #endif Index: head/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp =================================================================== --- head/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp (revision 241429) +++ head/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp (revision 241430) @@ -1,451 +1,451 @@ //===-- cc1as_main.cpp - Clang Assembler ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This is the entry point to the clang -cc1as functionality, which implements // the direct interface to the LLVM MC based assembler. // //===----------------------------------------------------------------------===// #include "clang/Basic/Diagnostic.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/CC1AsOptions.h" #include "clang/Driver/OptTable.h" #include "clang/Driver/Options.h" #include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include "llvm/Target/TargetData.h" using namespace clang; using namespace clang::driver; using namespace llvm; namespace { /// \brief Helper class for representing a single invocation of the assembler. struct AssemblerInvocation { /// @name Target Options /// @{ /// The name of the target triple to assemble for. std::string Triple; /// If given, the name of the target CPU to determine which instructions /// are legal. std::string CPU; /// The list of target specific features to enable or disable -- this should /// be a list of strings starting with '+' or '-'. std::vector Features; /// @} /// @name Language Options /// @{ std::vector IncludePaths; unsigned NoInitialTextSection : 1; unsigned SaveTemporaryLabels : 1; unsigned GenDwarfForAssembly : 1; std::string DwarfDebugFlags; /// @} /// @name Frontend Options /// @{ std::string InputFile; std::vector LLVMArgs; std::string OutputPath; enum FileType { FT_Asm, ///< Assembly (.s) output, transliterate mode. FT_Null, ///< No output, for timing purposes. FT_Obj ///< Object file output. }; FileType OutputType; unsigned ShowHelp : 1; unsigned ShowVersion : 1; /// @} /// @name Transliterate Options /// @{ unsigned OutputAsmVariant; unsigned ShowEncoding : 1; unsigned ShowInst : 1; /// @} /// @name Assembler Options /// @{ unsigned RelaxAll : 1; unsigned NoExecStack : 1; /// @} public: AssemblerInvocation() { Triple = ""; NoInitialTextSection = 0; InputFile = "-"; OutputPath = "-"; OutputType = FT_Asm; OutputAsmVariant = 0; ShowInst = 0; ShowEncoding = 0; RelaxAll = 0; NoExecStack = 0; } static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin, const char **ArgEnd, DiagnosticsEngine &Diags); }; } bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, const char **ArgBegin, const char **ArgEnd, DiagnosticsEngine &Diags) { using namespace clang::driver::cc1asoptions; bool Success = true; // Parse the arguments. OwningPtr OptTbl(createCC1AsOptTable()); unsigned MissingArgIndex, MissingArgCount; OwningPtr Args( OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount)); // Check for missing argument error. if (MissingArgCount) { Diags.Report(diag::err_drv_missing_argument) << Args->getArgString(MissingArgIndex) << MissingArgCount; Success = false; } // Issue errors on unknown arguments. for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN), ie = Args->filtered_end(); it != ie; ++it) { Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args); Success = false; } // Construct the invocation. // Target Options Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple)); Opts.CPU = Args->getLastArgValue(OPT_target_cpu); Opts.Features = Args->getAllArgValues(OPT_target_feature); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); // Language Options Opts.IncludePaths = Args->getAllArgValues(OPT_I); Opts.NoInitialTextSection = Args->hasArg(OPT_n); Opts.SaveTemporaryLabels = Args->hasArg(OPT_L); Opts.GenDwarfForAssembly = Args->hasArg(OPT_g); Opts.DwarfDebugFlags = Args->getLastArgValue(OPT_dwarf_debug_flags); // Frontend Options if (Args->hasArg(OPT_INPUT)) { bool First = true; for (arg_iterator it = Args->filtered_begin(OPT_INPUT), ie = Args->filtered_end(); it != ie; ++it, First=false) { const Arg *A = it; if (First) Opts.InputFile = A->getValue(*Args); else { Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args); Success = false; } } } Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm); if (Args->hasArg(OPT_fatal_warnings)) Opts.LLVMArgs.push_back("-fatal-assembler-warnings"); Opts.OutputPath = Args->getLastArgValue(OPT_o); if (Arg *A = Args->getLastArg(OPT_filetype)) { StringRef Name = A->getValue(*Args); unsigned OutputType = StringSwitch(Name) .Case("asm", FT_Asm) .Case("null", FT_Null) .Case("obj", FT_Obj) .Default(~0U); if (OutputType == ~0U) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(*Args) << Name; Success = false; } else Opts.OutputType = FileType(OutputType); } Opts.ShowHelp = Args->hasArg(OPT_help); Opts.ShowVersion = Args->hasArg(OPT_version); // Transliterate Options Opts.OutputAsmVariant = Args->getLastArgIntValue(OPT_output_asm_variant, 0, Diags); Opts.ShowEncoding = Args->hasArg(OPT_show_encoding); Opts.ShowInst = Args->hasArg(OPT_show_inst); // Assemble Options Opts.RelaxAll = Args->hasArg(OPT_relax_all); Opts.NoExecStack = Args->hasArg(OPT_no_exec_stack); return Success; } static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts, DiagnosticsEngine &Diags, bool Binary) { if (Opts.OutputPath.empty()) Opts.OutputPath = "-"; // Make sure that the Out file gets unlinked from the disk if we get a // SIGINT. if (Opts.OutputPath != "-") sys::RemoveFileOnSignal(sys::Path(Opts.OutputPath)); std::string Error; raw_fd_ostream *Out = new raw_fd_ostream(Opts.OutputPath.c_str(), Error, (Binary ? raw_fd_ostream::F_Binary : 0)); if (!Error.empty()) { Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath << Error; return 0; } return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM); } static bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { // Get the target specific parser. std::string Error; const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error)); if (!TheTarget) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } OwningPtr BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) { Error = ec.message(); Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; return false; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); OwningPtr MAI(TheTarget->createMCAsmInfo(Opts.Triple)); assert(MAI && "Unable to create target asm info!"); OwningPtr MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary); if (!Out) return false; // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. OwningPtr MOFI(new MCObjectFileInfo()); MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); // FIXME: Assembler behavior can change with -static. MOFI->InitMCObjectFileInfo(Opts.Triple, Reloc::Default, CodeModel::Default, Ctx); if (Opts.SaveTemporaryLabels) Ctx.setAllowTemporaryLabels(false); if (Opts.GenDwarfForAssembly) Ctx.setGenDwarfForAssembly(true); if (!Opts.DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags)); // Build up the feature string from the target feature list. std::string FS; if (!Opts.Features.empty()) { FS = Opts.Features[0]; for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i) FS += "," + Opts.Features[i]; } OwningPtr Str; OwningPtr MCII(TheTarget->createMCInstrInfo()); OwningPtr STI(TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS)); // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (Opts.ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MAB = TheTarget->createMCAsmBackend(Opts.Triple); + MAB = TheTarget->createMCAsmBackend(Opts.Triple, Opts.CPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, /*useLoc*/ true, /*useCFI*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MCAsmBackend *MAB = TheTarget->createMCAsmBackend(Opts.Triple); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(Opts.Triple, Opts.CPU); Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, CE, Opts.RelaxAll, Opts.NoExecStack)); Str.get()->InitSections(); } OwningPtr Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr TAP(TheTarget->createMCAsmParser(*STI, *Parser)); if (!TAP) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } Parser->setTargetParser(*TAP.get()); bool Success = !Parser->Run(Opts.NoInitialTextSection); // Close the output. delete Out; // Delete output on errors. if (!Success && Opts.OutputPath != "-") sys::Path(Opts.OutputPath).eraseFromDisk(); return Success; } static void LLVMErrorHandler(void *UserData, const std::string &Message) { DiagnosticsEngine &Diags = *static_cast(UserData); Diags.Report(diag::err_fe_error_backend) << Message; // We cannot recover from llvm errors. exit(1); } int cc1as_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. InitializeAllTargetInfos(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); // Construct our diagnostic client. TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(errs(), DiagnosticOptions()); DiagClient->setPrefix("clang -cc1as"); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, DiagClient); // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. ScopedFatalErrorHandler FatalErrorHandler (LLVMErrorHandler, static_cast(&Diags)); // Parse the arguments. AssemblerInvocation Asm; if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags)) return 1; // Honor -help. if (Asm.ShowHelp) { OwningPtr Opts(driver::createCC1AsOptTable()); Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler"); return 0; } // Honor -version. // // FIXME: Use a better -version message? if (Asm.ShowVersion) { llvm::cl::PrintVersionMessage(); return 0; } // Honor -mllvm. // // FIXME: Remove this, one day. if (!Asm.LLVMArgs.empty()) { unsigned NumArgs = Asm.LLVMArgs.size(); const char **Args = new const char*[NumArgs + 2]; Args[0] = "clang (LLVM option parsing)"; for (unsigned i = 0; i != NumArgs; ++i) Args[i + 1] = Asm.LLVMArgs[i].c_str(); Args[NumArgs + 1] = 0; llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args); } // Execute the invocation, unless there were parsing errors. bool Success = false; if (!Diags.hasErrorOccurred()) Success = ExecuteAssembler(Asm, Diags); // If any timers were active but haven't been destroyed yet, print their // results now. TimerGroup::printAll(errs()); return !Success; } Index: head/contrib/llvm/tools/llvm-mc/llvm-mc.cpp =================================================================== --- head/contrib/llvm/tools/llvm-mc/llvm-mc.cpp (revision 241429) +++ head/contrib/llvm/tools/llvm-mc/llvm-mc.cpp (revision 241430) @@ -1,451 +1,451 @@ //===-- llvm-mc.cpp - Machine Code Hacking Driver -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This utility is a simple driver that allows command line hacking on machine // code. // //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/system_error.h" #include "Disassembler.h" using namespace llvm; static cl::opt InputFilename(cl::Positional, cl::desc(""), cl::init("-")); static cl::opt OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); static cl::opt ShowEncoding("show-encoding", cl::desc("Show instruction encodings")); static cl::opt ShowInst("show-inst", cl::desc("Show internal instruction representation")); static cl::opt ShowInstOperands("show-inst-operands", cl::desc("Show instructions operands as parsed")); static cl::opt OutputAsmVariant("output-asm-variant", cl::desc("Syntax variant to use for output printing")); static cl::opt RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); static cl::opt NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); enum OutputFileType { OFT_Null, OFT_AssemblyFile, OFT_ObjectFile }; static cl::opt FileType("filetype", cl::init(OFT_AssemblyFile), cl::desc("Choose an output file type:"), cl::values( clEnumValN(OFT_AssemblyFile, "asm", "Emit an assembly ('.s') file"), clEnumValN(OFT_Null, "null", "Don't emit anything (for timing purposes)"), clEnumValN(OFT_ObjectFile, "obj", "Emit a native object ('.o') file"), clEnumValEnd)); static cl::list IncludeDirs("I", cl::desc("Directory of include files"), cl::value_desc("directory"), cl::Prefix); static cl::opt ArchName("arch", cl::desc("Target arch to assemble for, " "see -version for available targets")); static cl::opt TripleName("triple", cl::desc("Target triple to assemble for, " "see -version for available targets")); static cl::opt MCPU("mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"), cl::value_desc("cpu-name"), cl::init("")); static cl::list MAttrs("mattr", cl::CommaSeparated, cl::desc("Target specific attributes (-mattr=help for details)"), cl::value_desc("a1,+a2,-a3,...")); static cl::opt RelocModel("relocation-model", cl::desc("Choose relocation model"), cl::init(Reloc::Default), cl::values( clEnumValN(Reloc::Default, "default", "Target default relocation model"), clEnumValN(Reloc::Static, "static", "Non-relocatable code"), clEnumValN(Reloc::PIC_, "pic", "Fully relocatable, position independent code"), clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", "Relocatable external references, non-relocatable code"), clEnumValEnd)); static cl::opt CMModel("code-model", cl::desc("Choose code model"), cl::init(CodeModel::Default), cl::values(clEnumValN(CodeModel::Default, "default", "Target default code model"), clEnumValN(CodeModel::Small, "small", "Small code model"), clEnumValN(CodeModel::Kernel, "kernel", "Kernel code model"), clEnumValN(CodeModel::Medium, "medium", "Medium code model"), clEnumValN(CodeModel::Large, "large", "Large code model"), clEnumValEnd)); static cl::opt NoInitialTextSection("n", cl::desc("Don't assume assembly file starts " "in the text section")); static cl::opt SaveTempLabels("L", cl::desc("Don't discard temporary labels")); static cl::opt GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " "source files")); enum ActionType { AC_AsLex, AC_Assemble, AC_Disassemble, AC_EDisassemble }; static cl::opt Action(cl::desc("Action to perform:"), cl::init(AC_Assemble), cl::values(clEnumValN(AC_AsLex, "as-lex", "Lex tokens from a .s file"), clEnumValN(AC_Assemble, "assemble", "Assemble a .s file (default)"), clEnumValN(AC_Disassemble, "disassemble", "Disassemble strings of hex bytes"), clEnumValN(AC_EDisassemble, "edis", "Enhanced disassembly of strings of hex bytes"), clEnumValEnd)); static const Target *GetTarget(const char *ProgName) { // Figure out the target triple. if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple, Error); if (!TheTarget) { errs() << ProgName << ": " << Error; return 0; } // Update the triple name and return the found target. TripleName = TheTriple.getTriple(); return TheTarget; } static tool_output_file *GetOutputStream() { if (OutputFilename == "") OutputFilename = "-"; std::string Err; tool_output_file *Out = new tool_output_file(OutputFilename.c_str(), Err, raw_fd_ostream::F_Binary); if (!Err.empty()) { errs() << Err << '\n'; delete Out; return 0; } return Out; } static std::string DwarfDebugFlags; static void setDwarfDebugFlags(int argc, char **argv) { if (!getenv("RC_DEBUG_OPTIONS")) return; for (int i = 0; i < argc; i++) { DwarfDebugFlags += argv[i]; if (i + 1 < argc) DwarfDebugFlags += " "; } } static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { AsmToken Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: Out->os() << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: Out->os() << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: Out->os() << "real: " << Lexer.getTok().getString(); break; case AsmToken::Register: Out->os() << "register: " << Lexer.getTok().getRegVal(); break; case AsmToken::String: Out->os() << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: Out->os() << "Amp"; break; case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break; case AsmToken::At: Out->os() << "At"; break; case AsmToken::Caret: Out->os() << "Caret"; break; case AsmToken::Colon: Out->os() << "Colon"; break; case AsmToken::Comma: Out->os() << "Comma"; break; case AsmToken::Dollar: Out->os() << "Dollar"; break; case AsmToken::Dot: Out->os() << "Dot"; break; case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break; case AsmToken::Eof: Out->os() << "Eof"; break; case AsmToken::Equal: Out->os() << "Equal"; break; case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break; case AsmToken::Exclaim: Out->os() << "Exclaim"; break; case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break; case AsmToken::Greater: Out->os() << "Greater"; break; case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break; case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break; case AsmToken::Hash: Out->os() << "Hash"; break; case AsmToken::LBrac: Out->os() << "LBrac"; break; case AsmToken::LCurly: Out->os() << "LCurly"; break; case AsmToken::LParen: Out->os() << "LParen"; break; case AsmToken::Less: Out->os() << "Less"; break; case AsmToken::LessEqual: Out->os() << "LessEqual"; break; case AsmToken::LessGreater: Out->os() << "LessGreater"; break; case AsmToken::LessLess: Out->os() << "LessLess"; break; case AsmToken::Minus: Out->os() << "Minus"; break; case AsmToken::Percent: Out->os() << "Percent"; break; case AsmToken::Pipe: Out->os() << "Pipe"; break; case AsmToken::PipePipe: Out->os() << "PipePipe"; break; case AsmToken::Plus: Out->os() << "Plus"; break; case AsmToken::RBrac: Out->os() << "RBrac"; break; case AsmToken::RCurly: Out->os() << "RCurly"; break; case AsmToken::RParen: Out->os() << "RParen"; break; case AsmToken::Slash: Out->os() << "Slash"; break; case AsmToken::Star: Out->os() << "Star"; break; case AsmToken::Tilde: Out->os() << "Tilde"; break; } // Print the token string. Out->os() << " (\""; Out->os().write_escaped(Tok.getString()); Out->os() << "\")\n"; } return Error; } static int AssembleInput(const char *ProgName, const Target *TheTarget, SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str, MCAsmInfo &MAI, MCSubtargetInfo &STI) { OwningPtr Parser(createMCAsmParser(SrcMgr, Ctx, Str, MAI)); OwningPtr TAP(TheTarget->createMCAsmParser(STI, *Parser)); if (!TAP) { errs() << ProgName << ": error: this target does not support assembly parsing.\n"; return 1; } Parser->setShowParsedOperands(ShowInstOperands); Parser->setTargetParser(*TAP.get()); int Res = Parser->Run(NoInitialTextSection); return Res; } int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); TripleName = Triple::normalize(TripleName); setDwarfDebugFlags(argc, argv); const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; OwningPtr BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { errs() << ProgName << ": " << ec.message() << '\n'; return 1; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); llvm::OwningPtr MAI(TheTarget->createMCAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); llvm::OwningPtr MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. OwningPtr MOFI(new MCObjectFileInfo()); MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } OwningPtr Out(GetOutputStream()); if (!Out) return 1; formatted_raw_ostream FOS(Out->os()); OwningPtr Str; OwningPtr MCII(TheTarget->createMCInstrInfo()); OwningPtr STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MAB = TheTarget->createMCAsmBackend(TripleName); + MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, /*useLoc*/ true, /*useCFI*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, FOS, CE, RelaxAll, NoExecStack)); } int Res = 1; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out.get()); break; case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI); break; case AC_Disassemble: Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); break; case AC_EDisassemble: Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, SrcMgr, Out->os()); break; } // Keep output if no errors. if (Res == 0) Out->keep(); return Res; }