[llvm-commits] [PATCH] MC abstraction and stub patches

Daniel Dunbar daniel at zuster.org
Thu May 20 18:27:18 PDT 2010


Hi Matt,

On Sun, May 16, 2010 at 10:55 AM, Matt Fleming <matt at console-pimps.org> wrote:
> Hi,
>
> attached are some patches to try and de-MachO-ify some of the MC code
> and put in some stubs to help with adding ELF support. These general
> cleanups will make adding ELF support easier. I've tried to arrange them
> to take into account the feedback that Daniel gave to the last set of
> patches.
>
> I ran the DejaGNU tests and they still pass with these patches applied.
>
> 0001-type-asm-directive.patch:
> This patch adds support for the ELF .type directive.

Looks good, please apply.

> 0002-split-elfx86-asmbackend.patch:
> This splits the ELF X86 AsmBackend classes into 64Bit and 32Bit which
> will help when ELF support gets merged as the createObjectWriter
> implementations will differ for 64Bit and 32Bit.

Looks good, please apply.

> 0003-target-streamer.patch:
> Currently createMachOStreamer is invoked directly in llvm-mc which isn't
> a good idea if we want to be able to use another object file
> format. This patch adds a createStreamer() factory method to the correct
> object file streamer to be instantiated for a given target triple.

Looks good, but can you change the functions to be
"createObjectStreamer", etc? That makes more sense, and reflects a
refactoring I am going to (eventually) do to pull out an
MCObjectStreamer class, which will be shared by ELF, COFF, and MachO.

> 0004-section-abstraction.patch:
>
> Instead of calling getMachOSection() directly when parsing section
> directives we should be asking the streamer backend to create the
> correct section given a section name. One thing I didn't understand when
> writing this patch was exactly how MCAsmStreamer should behave, hence
> the FIXME in MCAsmStreamer::LookupSection(). I've left the current
> behaviour in place, e.g. creating a MachOSection because I couldn't
> think of what else to do. I'm guessing the type of Section doesn't
> really matter?

I'd like to go a different direction on this. What I think we should
do is allow targets to define and/or override the directive
processing. For very target dependent directives like .section, we
will just assume that any target parser implements those directives.
It doesn't seem worth trying to make abstract versions of these, and
we know we will need other support for target dependent directives
anyway.

We should start by factoring out the current directive handling to be
table driven, and then allow the target asm parser to override entries
in that table. What do you think about this approach?

 - Daniel

>
> Comments?
>
>
> Index: llvm/lib/MC/MCParser/AsmParser.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCParser/AsmParser.cpp
> +++ llvm/lib/MC/MCParser/AsmParser.cpp
> @@ -13,6 +13,7 @@
>
>  #include "llvm/MC/MCParser/AsmParser.h"
>  #include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/StringSwitch.h"
>  #include "llvm/ADT/Twine.h"
>  #include "llvm/MC/MCContext.h"
>  #include "llvm/MC/MCExpr.h"
> @@ -686,6 +687,8 @@ bool AsmParser::ParseStatement() {
>       return ParseDirectiveSymbolAttribute(MCSA_Protected);
>     if (IDVal == ".reference")
>       return ParseDirectiveSymbolAttribute(MCSA_Reference);
> +    if (IDVal == ".type")
> +      return ParseDirectiveELFType();
>     if (IDVal == ".weak")
>       return ParseDirectiveSymbolAttribute(MCSA_Weak);
>     if (IDVal == ".weak_definition")
> @@ -1241,6 +1244,52 @@ bool AsmParser::ParseDirectiveSymbolAttr
>   return false;
>  }
>
> +/// ParseDirectiveELFType
> +///  ::= .type identifier , @attribute
> +bool AsmParser::ParseDirectiveELFType() {
> +  StringRef Name;
> +  if (ParseIdentifier(Name))
> +    return TokError("expected identifier in directive");
> +
> +  // Handle the identifier as the key symbol.
> +  MCSymbol *Sym = CreateSymbol(Name);
> +
> +  if (Lexer.isNot(AsmToken::Comma))
> +    return TokError("unexpected token in '.type' directive");
> +  Lex();
> +
> +  if (Lexer.isNot(AsmToken::At))
> +    return TokError("expected '@' before type");
> +  Lex();
> +
> +  StringRef Type;
> +  SMLoc TypeLoc;
> +
> +  TypeLoc = Lexer.getLoc();
> +  if (ParseIdentifier(Type))
> +    return TokError("expected symbol type in directive");
> +
> +  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
> +    .Case("function", MCSA_ELF_TypeFunction)
> +    .Case("object", MCSA_ELF_TypeObject)
> +    .Case("tls_object", MCSA_ELF_TypeTLS)
> +    .Case("common", MCSA_ELF_TypeCommon)
> +    .Case("notype", MCSA_ELF_TypeNoType)
> +    .Default(MCSA_Invalid);
> +
> +  if (Attr == MCSA_Invalid)
> +    return Error(TypeLoc, "unsupported attribute in '.type' directive");
> +
> +  if (Lexer.isNot(AsmToken::EndOfStatement))
> +    return TokError("unexpected token in '.type' directive");
> +
> +  Lex();
> +
> +  Out.EmitSymbolAttribute(Sym, Attr);
> +
> +  return false;
> +}
> +
>  /// ParseDirectiveDarwinSymbolDesc
>  ///  ::= .desc identifier , expression
>  bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
> Index: llvm/include/llvm/MC/MCParser/AsmParser.h
> ===================================================================
> --- llvm.orig/include/llvm/MC/MCParser/AsmParser.h
> +++ llvm/include/llvm/MC/MCParser/AsmParser.h
> @@ -131,6 +131,7 @@ private:
>   /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
>   /// accepts a single symbol (which should be a label or an external).
>   bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
> +  bool ParseDirectiveELFType(); // ELF specific ".type"
>   bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc"
>   bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym"
>
> Index: llvm/include/llvm/MC/MCParser/MCAsmLexer.h
> ===================================================================
> --- llvm.orig/include/llvm/MC/MCParser/MCAsmLexer.h
> +++ llvm/include/llvm/MC/MCParser/MCAsmLexer.h
> @@ -47,7 +47,7 @@ public:
>     Pipe, PipePipe, Caret,
>     Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
>     Less, LessEqual, LessLess, LessGreater,
> -    Greater, GreaterEqual, GreaterGreater
> +    Greater, GreaterEqual, GreaterGreater, At
>   };
>
>   TokenKind Kind;
> Index: llvm/lib/MC/MCParser/AsmLexer.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCParser/AsmLexer.cpp
> +++ llvm/lib/MC/MCParser/AsmLexer.cpp
> @@ -280,6 +280,7 @@ AsmToken AsmLexer::LexToken() {
>   case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
>   case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
>   case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
> +  case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
>   case '=':
>     if (*CurPtr == '=')
>       return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
>
> Index: llvm/lib/Target/X86/X86AsmBackend.cpp
> ===================================================================
> --- llvm.orig/lib/Target/X86/X86AsmBackend.cpp
> +++ llvm/lib/Target/X86/X86AsmBackend.cpp
> @@ -211,6 +211,18 @@ public:
>   }
>  };
>
> +class ELFX86_32AsmBackend : public ELFX86AsmBackend {
> +public:
> +  ELFX86_32AsmBackend(const Target &T)
> +    : ELFX86AsmBackend(T) {}
> +};
> +
> +class ELFX86_64AsmBackend : public ELFX86AsmBackend {
> +public:
> +  ELFX86_64AsmBackend(const Target &T)
> +    : ELFX86AsmBackend(T) {}
> +};
> +
>  class DarwinX86AsmBackend : public X86AsmBackend {
>  public:
>   DarwinX86AsmBackend(const Target &T)
> @@ -289,7 +301,7 @@ TargetAsmBackend *llvm::createX86_32AsmB
>   case Triple::Darwin:
>     return new DarwinX86_32AsmBackend(T);
>   default:
> -    return new ELFX86AsmBackend(T);
> +    return new ELFX86_32AsmBackend(T);
>   }
>  }
>
> @@ -299,6 +311,6 @@ TargetAsmBackend *llvm::createX86_64AsmB
>   case Triple::Darwin:
>     return new DarwinX86_64AsmBackend(T);
>   default:
> -    return new ELFX86AsmBackend(T);
> +    return new ELFX86_64AsmBackend(T);
>   }
>  }
>
> Index: llvm/include/llvm/Target/TargetRegistry.h
> ===================================================================
> --- llvm.orig/include/llvm/Target/TargetRegistry.h
> +++ llvm/include/llvm/Target/TargetRegistry.h
> @@ -73,6 +73,13 @@ namespace llvm {
>     typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T,
>                                                 TargetMachine &TM,
>                                                 MCContext &Ctx);
> +    typedef MCStreamer *(*StreamerCtorTy)(const Target &T,
> +                                          const std::string &TT,
> +                                          MCContext &Ctx,
> +                                          TargetAsmBackend &TAB,
> +                                          raw_ostream &_OS,
> +                                          MCCodeEmitter *_Emitter,
> +                                          bool RelaxAll);
>
>   private:
>     /// Next - The next registered target in the linked list, maintained by the
> @@ -126,6 +133,10 @@ namespace llvm {
>     /// if registered.
>     CodeEmitterCtorTy CodeEmitterCtorFn;
>
> +    /// StreamerCtorFn - Construction function for this target's Streamer,
> +    /// if registered.
> +    StreamerCtorTy StreamerCtorFn;
> +
>   public:
>     /// @name Target Information
>     /// @{
> @@ -170,6 +181,9 @@ namespace llvm {
>     /// hasCodeEmitter - Check if this target supports instruction encoding.
>     bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; }
>
> +    /// hasStreamer - Check if this target supports streaming to files.
> +    bool hasStreamer() const { return StreamerCtorFn != 0; }
> +
>     /// @}
>     /// @name Feature Constructors
>     /// @{
> @@ -258,6 +272,24 @@ namespace llvm {
>       return CodeEmitterCtorFn(*this, TM, Ctx);
>     }
>
> +    /// createStreamer - Create a target specific MCStreamer.
> +    ///
> +    /// \arg TT - The target triple.
> +    /// \arg Ctx - The target context.
> +    /// \arg TAB - The target assembler backend object.
> +    /// \arg _OS - The stream object.
> +    /// \arg _Emitter - The target independent assembler object.
> +    /// \arg RelaxAll - Relax all fixups?
> +    MCStreamer *createStreamer(const std::string &TT, MCContext &Ctx,
> +                               TargetAsmBackend &TAB,
> +                               raw_ostream &_OS,
> +                               MCCodeEmitter *_Emitter,
> +                               bool RelaxAll) const {
> +      if (!StreamerCtorFn)
> +        return 0;
> +      return StreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll);
> +    }
> +
>     /// @}
>   };
>
> @@ -479,6 +511,20 @@ namespace llvm {
>         T.CodeEmitterCtorFn = Fn;
>     }
>
> +    /// RegisterStreamer - Register a 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 RegisterStreamer(Target &T, Target::StreamerCtorTy Fn) {
> +      if (!T.StreamerCtorFn)
> +        T.StreamerCtorFn = Fn;
> +    }
> +
>     /// @}
>   };
>
> Index: llvm/tools/llvm-mc/llvm-mc.cpp
> ===================================================================
> --- llvm.orig/tools/llvm-mc/llvm-mc.cpp
> +++ llvm/tools/llvm-mc/llvm-mc.cpp
> @@ -304,7 +304,8 @@ static int AssembleInput(const char *Pro
>     assert(FileType == OFT_ObjectFile && "Invalid file type!");
>     CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
>     TAB.reset(TheTarget->createAsmBackend(TripleName));
> -    Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), RelaxAll));
> +    Str.reset(TheTarget->createStreamer(TripleName, Ctx, *TAB,
> +                                        *Out, CE.get(), RelaxAll));
>   }
>
>   AsmParser Parser(SrcMgr, Ctx, *Str.get(), *MAI);
> Index: llvm/lib/Target/X86/X86TargetMachine.cpp
> ===================================================================
> --- llvm.orig/lib/Target/X86/X86TargetMachine.cpp
> +++ llvm/lib/Target/X86/X86TargetMachine.cpp
> @@ -17,6 +17,8 @@
>  #include "llvm/PassManager.h"
>  #include "llvm/CodeGen/MachineFunction.h"
>  #include "llvm/CodeGen/Passes.h"
> +#include "llvm/MC/MCCodeEmitter.h"
> +#include "llvm/MC/MCStreamer.h"
>  #include "llvm/Support/FormattedStream.h"
>  #include "llvm/Target/TargetOptions.h"
>  #include "llvm/Target/TargetRegistry.h"
> @@ -37,6 +39,18 @@ static MCAsmInfo *createMCAsmInfo(const
>   }
>  }
>
> +static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
> +                                    MCContext &Ctx, TargetAsmBackend &TAB,
> +                                    raw_ostream &_OS,
> +                                    MCCodeEmitter *_Emitter,
> +                                    bool RelaxAll) {
> +  Triple TheTriple(TT);
> +  switch (TheTriple.getOS()) {
> +  default:
> +    return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll);
> +  }
> +}
> +
>  extern "C" void LLVMInitializeX86Target() {
>   // Register the target.
>   RegisterTargetMachine<X86_32TargetMachine> X(TheX86_32Target);
> @@ -57,6 +71,12 @@ extern "C" void LLVMInitializeX86Target(
>                                      createX86_32AsmBackend);
>   TargetRegistry::RegisterAsmBackend(TheX86_64Target,
>                                      createX86_64AsmBackend);
> +
> +  // Register the streamer.
> +  TargetRegistry::RegisterStreamer(TheX86_32Target,
> +                                   createMCStreamer);
> +  TargetRegistry::RegisterStreamer(TheX86_64Target,
> +                                   createMCStreamer);
>  }
>
>
>
> Index: llvm/lib/MC/MCParser/AsmParser.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCParser/AsmParser.cpp
> +++ llvm/lib/MC/MCParser/AsmParser.cpp
> @@ -23,6 +23,7 @@
>  #include "llvm/MC/MCSymbol.h"
>  #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
>  #include "llvm/Support/Compiler.h"
> +#include "llvm/Support/ELF.h"
>  #include "llvm/Support/SourceMgr.h"
>  #include "llvm/Support/raw_ostream.h"
>  #include "llvm/Target/TargetAsmParser.h"
> @@ -103,11 +104,9 @@ const AsmToken &AsmParser::Lex() {
>  bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
>   // Create the initial section, if requested.
>   //
> -  // FIXME: Target hook & command line option for initial section.
> +  // FIXME: Command line option for initial section.
>   if (!NoInitialTextSection)
> -    Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text",
> -                                      MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> -                                      0, SectionKind::getText()));
> +    Out.SwitchSection(Out.LookupSection(".text"));
>
>   // Prime the lexer.
>   Lex();
> @@ -482,145 +481,28 @@ bool AsmParser::ParseStatement() {
>     // FIXME: This should be driven based on a hash lookup and callback.
>     if (IDVal == ".section")
>       return ParseDirectiveDarwinSection();
> -    if (IDVal == ".text")
> -      // FIXME: This changes behavior based on the -static flag to the
> -      // assembler.
> -      return ParseDirectiveSectionSwitch("__TEXT", "__text",
> -                                     MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
> -    if (IDVal == ".const")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__const");
> -    if (IDVal == ".static_const")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
> -    if (IDVal == ".cstring")
> -      return ParseDirectiveSectionSwitch("__TEXT","__cstring",
> -                                         MCSectionMachO::S_CSTRING_LITERALS);
> -    if (IDVal == ".literal4")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
> -                                         MCSectionMachO::S_4BYTE_LITERALS,
> -                                         4);
> -    if (IDVal == ".literal8")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
> -                                         MCSectionMachO::S_8BYTE_LITERALS,
> -                                         8);
> -    if (IDVal == ".literal16")
> -      return ParseDirectiveSectionSwitch("__TEXT","__literal16",
> -                                         MCSectionMachO::S_16BYTE_LITERALS,
> -                                         16);
> -    if (IDVal == ".constructor")
> -      return ParseDirectiveSectionSwitch("__TEXT","__constructor");
> -    if (IDVal == ".destructor")
> -      return ParseDirectiveSectionSwitch("__TEXT","__destructor");
> -    if (IDVal == ".fvmlib_init0")
> -      return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
> -    if (IDVal == ".fvmlib_init1")
> -      return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
> -
> -    // FIXME: The assembler manual claims that this has the self modify code
> -    // flag, at least on x86-32, but that does not appear to be correct.
> -    if (IDVal == ".symbol_stub")
> -      return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
> -                                         MCSectionMachO::S_SYMBOL_STUBS |
> -                                       MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> -                                          // FIXME: Different on PPC and ARM.
> -                                         0, 16);
> -    // FIXME: PowerPC only?
> -    if (IDVal == ".picsymbol_stub")
> -      return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
> -                                         MCSectionMachO::S_SYMBOL_STUBS |
> -                                       MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> -                                         0, 26);
> -    if (IDVal == ".data")
> -      return ParseDirectiveSectionSwitch("__DATA", "__data");
> -    if (IDVal == ".static_data")
> -      return ParseDirectiveSectionSwitch("__DATA", "__static_data");
> -
> -    // FIXME: The section names of these two are misspelled in the assembler
> -    // manual.
> -    if (IDVal == ".non_lazy_symbol_pointer")
> -      return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
> -                                     MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
> -                                         4);
> -    if (IDVal == ".lazy_symbol_pointer")
> -      return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
> -                                         MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
> -                                         4);
> -
> -    if (IDVal == ".dyld")
> -      return ParseDirectiveSectionSwitch("__DATA", "__dyld");
> -    if (IDVal == ".mod_init_func")
> -      return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
> -                                       MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
> -                                         4);
> -    if (IDVal == ".mod_term_func")
> -      return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
> -                                       MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
> -                                         4);
> -    if (IDVal == ".const_data")
> -      return ParseDirectiveSectionSwitch("__DATA", "__const");
> -
> -
> -    if (IDVal == ".objc_class")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__class",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_meta_class")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_cat_cls_meth")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_cat_inst_meth")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_protocol")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_string_object")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_cls_meth")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_inst_meth")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_cls_refs")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
> -                                         MCSectionMachO::S_LITERAL_POINTERS,
> -                                         4);
> -    if (IDVal == ".objc_message_refs")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
> -                                         MCSectionMachO::S_LITERAL_POINTERS,
> -                                         4);
> -    if (IDVal == ".objc_symbols")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_category")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__category",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_class_vars")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_instance_vars")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_module_info")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
> -                                         MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
> -    if (IDVal == ".objc_class_names")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
> -                                         MCSectionMachO::S_CSTRING_LITERALS);
> -    if (IDVal == ".objc_meth_var_types")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
> -                                         MCSectionMachO::S_CSTRING_LITERALS);
> -    if (IDVal == ".objc_meth_var_names")
> -      return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
> -                                         MCSectionMachO::S_CSTRING_LITERALS);
> -    if (IDVal == ".objc_selector_strs")
> -      return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
> -                                         MCSectionMachO::S_CSTRING_LITERALS);
> -
> +
> +    if (IDVal == ".text" || IDVal == ".const" || IDVal == ".static_const" ||
> +        IDVal == ".cstring" || IDVal == ".literal4" || IDVal == ".literal8" ||
> +        IDVal == ".literal16" || IDVal == ".constructor" ||
> +        IDVal == ".destructor" || IDVal == ".fvmlib_init0" ||
> +        IDVal == ".fvmlib_init1" || IDVal == ".symbol_stub" ||
> +        IDVal == ".picsymbol_stub" || IDVal == ".data" ||
> +        IDVal == ".static_data" || IDVal == ".non_lazy_symbol_pointer" ||
> +        IDVal == ".lazy_symbol_pointer" || IDVal == ".dyld" ||
> +        IDVal == ".mod_init_func" || IDVal == ".mod_term_func" ||
> +        IDVal == ".const_data" || IDVal == ".objc_class" ||
> +        IDVal == ".objc_meta_class" || IDVal == ".objc_cat_cls_meth" ||
> +        IDVal == ".objc_cat_inst_meth" || IDVal == ".objc_protocol" ||
> +        IDVal == ".objc_string_object" || IDVal == ".objc_cls_meth" ||
> +        IDVal == ".objc_inst_meth" || IDVal == ".objc_cls_refs" ||
> +        IDVal == ".objc_message_refs" || IDVal == ".objc_symbols" ||
> +        IDVal == ".objc_category" || IDVal == ".objc_class_vars" ||
> +        IDVal == ".objc_instance_vars" || IDVal == ".objc_module_info" ||
> +        IDVal == ".objc_class_names" || IDVal == ".objc_meth_var_types" ||
> +        IDVal == ".objc_meth_var_names" || IDVal == ".objc_selector_strs")
> +      return ParseDirectiveSectionSwitch(IDVal);
> +
>     // Assembler features
>     if (IDVal == ".set")
>       return ParseDirectiveSet();
> @@ -886,30 +768,12 @@ bool AsmParser::ParseDirectiveDarwinSect
>  }
>
>  /// ParseDirectiveSectionSwitch -
> -bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
> -                                            const char *Section,
> -                                            unsigned TAA, unsigned Align,
> -                                            unsigned StubSize) {
> +bool AsmParser::ParseDirectiveSectionSwitch(StringRef Section) {
>   if (Lexer.isNot(AsmToken::EndOfStatement))
>     return TokError("unexpected token in section switching directive");
>   Lex();
>
> -  // FIXME: Arch specific.
> -  bool isText = StringRef(Segment) == "__TEXT";  // FIXME: Hack.
> -  Out.SwitchSection(Ctx.getMachOSection(Segment, Section, TAA, StubSize,
> -                                        isText ? SectionKind::getText()
> -                                               : SectionKind::getDataRel()));
> -
> -  // Set the implicit alignment, if any.
> -  //
> -  // FIXME: This isn't really what 'as' does; I think it just uses the implicit
> -  // alignment on the section (e.g., if one manually inserts bytes into the
> -  // section, then just issueing the section switch directive will not realign
> -  // the section. However, this is arguably more reasonable behavior, and there
> -  // is no good reason for someone to intentionally emit incorrectly sized
> -  // values into the implicitly aligned sections.
> -  if (Align)
> -    Out.EmitValueToAlignment(Align, 0, 1, 0);
> +  Out.SwitchSection(Out.LookupSection(Section));
>
>   return false;
>  }
> Index: llvm/include/llvm/MC/MCParser/AsmParser.h
> ===================================================================
> --- llvm.orig/include/llvm/MC/MCParser/AsmParser.h
> +++ llvm/include/llvm/MC/MCParser/AsmParser.h
> @@ -116,9 +116,7 @@ private:
>
>   // Directive Parsing.
>   bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
> -  bool ParseDirectiveSectionSwitch(const char *Segment, const char *Section,
> -                                   unsigned TAA = 0, unsigned ImplicitAlign = 0,
> -                                   unsigned StubSize = 0);
> +  bool ParseDirectiveSectionSwitch(StringRef Section);
>   bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
>   bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
>   bool ParseDirectiveFill(); // ".fill"
> Index: llvm/include/llvm/MC/MCStreamer.h
> ===================================================================
> --- llvm.orig/include/llvm/MC/MCStreamer.h
> +++ llvm/include/llvm/MC/MCStreamer.h
> @@ -102,6 +102,9 @@ namespace llvm {
>     /// This corresponds to assembler directives like .section, .text, etc.
>     virtual void SwitchSection(const MCSection *Section) = 0;
>
> +    /// LookupSection - Return the corresponding output section for @Section.
> +    virtual const MCSection *LookupSection(StringRef Section) = 0;
> +
>     /// EmitLabel - Emit a label for @p Symbol into the current section.
>     ///
>     /// This corresponds to an assembler statement such as:
> Index: llvm/lib/MC/MCMachOStreamer.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCMachOStreamer.cpp
> +++ llvm/lib/MC/MCMachOStreamer.cpp
> @@ -15,6 +15,7 @@
>  #include "llvm/MC/MCExpr.h"
>  #include "llvm/MC/MCInst.h"
>  #include "llvm/MC/MCSection.h"
> +#include "llvm/MC/MCSectionMachO.h"
>  #include "llvm/MC/MCSymbol.h"
>  #include "llvm/MC/MCMachOSymbolFlags.h"
>  #include "llvm/Support/ErrorHandling.h"
> @@ -95,10 +96,41 @@ public:
>     return Value;
>   }
>
> +  // Set the implicit alignment, if any.
> +  //
> +  // FIXME: This isn't really what 'as' does; I think it just uses the implicit
> +  // alignment on the section (e.g., if one manually inserts bytes into the
> +  // section, then just issueing the section switch directive will not realign
> +  // the section. However, this is arguably more reasonable behavior, and there
> +  // is no good reason for someone to intentionally emit incorrectly sized
> +  // values into the implicitly aligned sections.
> +  const MCSection *AlignedSection(StringRef Segment,
> +                                  StringRef Section,
> +                                  unsigned TypeAndAttributes,
> +                                  unsigned Reserved2,
> +                                  SectionKind K,
> +                                  unsigned Align) {
> +    const MCSection *S = getContext().getMachOSection(Segment, Section,
> +                                                      TypeAndAttributes,
> +                                                      Reserved2, K);
> +
> +    MCSectionData *SD = &Assembler.getOrCreateSectionData(*S);
> +
> +    MCFragment *F = new MCAlignFragment(Align, 0, 1, Align, SD);
> +    F->setAtom(CurrentAtomMap.lookup(SD));
> +
> +    // Update the maximum alignment on the current section if necessary.
> +    if (Align > SD->getAlignment())
> +      SD->setAlignment(Align);
> +
> +    return S;
> +  }
> +
>   /// @name MCStreamer Interface
>   /// @{
>
>   virtual void SwitchSection(const MCSection *Section);
> +  virtual const MCSection *LookupSection(StringRef Section);
>   virtual void EmitLabel(MCSymbol *Symbol);
>   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
>   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
> @@ -166,6 +198,178 @@ void MCMachOStreamer::SwitchSection(cons
>   CurSectionData = &Assembler.getOrCreateSectionData(*Section);
>  }
>
> +
> +const MCSection *MCMachOStreamer::LookupSection(StringRef S) {
> +
> +  MCContext &Ctx = getContext();
> +
> +    if (S == ".text") {
> +      return Ctx.getMachOSection("__TEXT", "__text",
> +                                 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> +                                 0, SectionKind::getText());
> +    } else if (S == ".const") {
> +      return Ctx.getMachOSection("__TEXT", "__const", 0, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".static_const") {
> +      return Ctx.getMachOSection("__TEXT", "__static_const", 0, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".cstring") {
> +      return Ctx.getMachOSection("__TEXT","__cstring",
> +                                 MCSectionMachO::S_CSTRING_LITERALS, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".literal4") {
> +      return AlignedSection("__TEXT", "__literal4",
> +                            MCSectionMachO::S_4BYTE_LITERALS,
> +                            0, SectionKind::getText(), 4);
> +    } else if (S == ".literal8") {
> +      return AlignedSection("__TEXT", "__literal8",
> +                            MCSectionMachO::S_8BYTE_LITERALS,
> +                            0, SectionKind::getText(), 8);
> +    } else if (S == ".literal16") {
> +      return AlignedSection("__TEXT","__literal16",
> +                            MCSectionMachO::S_16BYTE_LITERALS,
> +                            0, SectionKind::getText(), 16);
> +    } else if (S == ".constructor") {
> +      return Ctx.getMachOSection("__TEXT","__constructor", 0, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".destructor") {
> +      return Ctx.getMachOSection("__TEXT","__destructor", 0, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".fvmlib_init0") {
> +      return Ctx.getMachOSection("__TEXT","__fvmlib_init0", 0, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".fvmlib_init1") {
> +      return Ctx.getMachOSection("__TEXT","__fvmlib_init1", 0, 0,
> +                                 SectionKind::getText());
> +
> +    // FIXME: The assembler manual claims that this has the self modify code
> +    // flag, at least on x86-32, but that does not appear to be correct.
> +    } else if (S == ".symbol_stub") {
> +      return Ctx.getMachOSection("__TEXT","__symbol_stub",
> +                                 MCSectionMachO::S_SYMBOL_STUBS |
> +                                 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> +                                 // FIXME: Different on PPC and ARM.
> +                                 16, SectionKind::getText());
> +    // FIXME: PowerPC only?
> +    } else if (S == ".picsymbol_stub") {
> +      return Ctx.getMachOSection("__TEXT","__picsymbol_stub",
> +                                 MCSectionMachO::S_SYMBOL_STUBS |
> +                                 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> +                                 26, SectionKind::getText());
> +    } else if (S == ".data") {
> +      return Ctx.getMachOSection("__DATA", "__data", 0, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".static_data") {
> +      return Ctx.getMachOSection("__DATA", "__static_data", 0, 0,
> +                                 SectionKind::getDataRel());
> +
> +    // FIXME: The section names of these two are misspelled in the assembler
> +    // manual.
> +    } else if (S == ".non_lazy_symbol_pointer") {
> +      return AlignedSection("__DATA", "__nl_symbol_ptr",
> +                            MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".lazy_symbol_pointer") {
> +      return AlignedSection("__DATA", "__la_symbol_ptr",
> +                            MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".dyld") {
> +      return Ctx.getMachOSection("__DATA", "__dyld", 0, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".mod_init_func") {
> +      return AlignedSection("__DATA", "__mod_init_func",
> +                            MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".mod_term_func") {
> +      return AlignedSection("__DATA", "__mod_term_func",
> +                            MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".const_data") {
> +      return Ctx.getMachOSection("__DATA", "__const", 0, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_class") {
> +      return Ctx.getMachOSection("__OBJC", "__class",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_meta_class") {
> +      return Ctx.getMachOSection("__OBJC", "__meta_class",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_cat_cls_meth") {
> +      return Ctx.getMachOSection("__OBJC", "__cat_cls_meth",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_cat_inst_meth") {
> +      return Ctx.getMachOSection("__OBJC", "__cat_inst_meth",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_protocol") {
> +      return Ctx.getMachOSection("__OBJC", "__protocol",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_string_object") {
> +      return Ctx.getMachOSection("__OBJC", "__string_object",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_cls_meth") {
> +      return Ctx.getMachOSection("__OBJC", "__cls_meth",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_inst_meth") {
> +      return Ctx.getMachOSection("__OBJC", "__inst_meth",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_cls_refs") {
> +      return AlignedSection("__OBJC", "__cls_refs",
> +                            MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
> +                            MCSectionMachO::S_LITERAL_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".objc_message_refs") {
> +      return AlignedSection("__OBJC", "__message_refs",
> +                            MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
> +                            MCSectionMachO::S_LITERAL_POINTERS,
> +                            0, SectionKind::getDataRel(), 4);
> +    } else if (S == ".objc_symbols") {
> +      return Ctx.getMachOSection("__OBJC", "__symbols",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_category") {
> +      return Ctx.getMachOSection("__OBJC", "__category",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_class_vars") {
> +      return Ctx.getMachOSection("__OBJC", "__class_vars",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_instance_vars") {
> +      return Ctx.getMachOSection("__OBJC", "__instance_vars",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_module_info") {
> +      return Ctx.getMachOSection("__OBJC", "__module_info",
> +                                 MCSectionMachO::S_ATTR_NO_DEAD_STRIP, 0,
> +                                 SectionKind::getDataRel());
> +    } else if (S == ".objc_class_names") {
> +      return Ctx.getMachOSection("__TEXT", "__cstring",
> +                                 MCSectionMachO::S_CSTRING_LITERALS, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".objc_meth_var_types") {
> +      return Ctx.getMachOSection("__TEXT", "__cstring",
> +                                 MCSectionMachO::S_CSTRING_LITERALS, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".objc_meth_var_names") {
> +      return Ctx.getMachOSection("__TEXT", "__cstring",
> +                                 MCSectionMachO::S_CSTRING_LITERALS, 0,
> +                                 SectionKind::getText());
> +    } else if (S == ".objc_selector_strs") {
> +      return Ctx.getMachOSection("__OBJC", "__selector_strs",
> +                                 MCSectionMachO::S_CSTRING_LITERALS, 0,
> +                                 SectionKind::getDataRel());
> +    }
> +
> +   return 0;
> +}
> +
>  void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
>   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
>   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
> Index: llvm/lib/MC/MCAsmStreamer.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCAsmStreamer.cpp
> +++ llvm/lib/MC/MCAsmStreamer.cpp
> @@ -100,6 +100,15 @@ public:
>
>   virtual void SwitchSection(const MCSection *Section);
>
> +  virtual const MCSection *LookupSection(StringRef Section) {
> +    // FIXME: What sort of section should we create? Does it even
> +    // matter? I think we're just doing this to appease the other
> +    // layers.
> +    return getContext().getMachOSection("__TEXT", ".text",
> +                                   MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
> +                                   0, SectionKind::getText());
> +  }
> +
>   virtual void EmitLabel(MCSymbol *Symbol);
>
>   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
> Index: llvm/lib/MC/MCNullStreamer.cpp
> ===================================================================
> --- llvm.orig/lib/MC/MCNullStreamer.cpp
> +++ llvm/lib/MC/MCNullStreamer.cpp
> @@ -13,6 +13,7 @@
>  #include "llvm/MC/MCInst.h"
>  #include "llvm/MC/MCSectionMachO.h"
>  #include "llvm/MC/MCSymbol.h"
> +#include "llvm/Support/raw_ostream.h"
>
>  using namespace llvm;
>
> @@ -29,6 +30,11 @@ namespace {
>       CurSection = Section;
>     }
>
> +    virtual const MCSection *LookupSection(StringRef Section) {
> +      errs() << "FIXME: MCNullStreamer:LookupSection not implemented\n";
> +      return 0;
> +    }
> +
>     virtual void EmitLabel(MCSymbol *Symbol) {
>       assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
>       assert(CurSection && "Cannot emit before setting section!");
>
>




More information about the llvm-commits mailing list