[MC][AsmParser] Hook for post assembly file processing
authorJack Carter <jack.carter@imgtec.com>
Fri, 4 Oct 2013 21:26:15 +0000 (21:26 +0000)
committerJack Carter <jack.carter@imgtec.com>
Fri, 4 Oct 2013 21:26:15 +0000 (21:26 +0000)
This patch handles LLVM standalone assembler (llvm-mc) ELF flag setting based on input file
directive processing.

Mips assembly requires processing inline directives that directly and
indirectly affect the output ELF header flags. This patch handles one
".abicalls".

To process these directives we are following the model the code generator
uses by storing state in a container as we go through processing and when
we detect the end of input file processing, AsmParser is notified and we
update the ELF header flags through a MipsELFStreamer method with a call from
MCTargetAsmParser::emitEndOfAsmFile(MCStreamer &OutStreamer).

This patch will allow other targets the same functionality.

Jack

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191982 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCTargetAsmParser.h
lib/MC/MCParser/AsmParser.cpp
lib/Target/Mips/AsmParser/MipsAsmFlags.h [new file with mode: 0644]
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
lib/Target/Mips/MipsAsmPrinter.cpp
test/MC/Mips/mips_directives.s

index 6e96e8becdab1e31d2e4586fff2407e329a03daa..512fd8649ae31c35d2c1ab10288c984ccd243ed7 100644 (file)
@@ -176,6 +176,11 @@ public:
   virtual void convertToMapAndConstraints(unsigned Kind,
                       const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
 
+  /// End of assembly processing.
+  /// This gets called when all assembly has been read and gives the local
+  /// Target AsmParsers an opportunity for any final data processing, etc..
+  virtual void emitEndOfAsmFile(MCStreamer &Out) {}
+
   virtual const MCExpr *applyModifierToExpr(const MCExpr *E,
                                             MCSymbolRefExpr::VariantKind,
                                             MCContext &Ctx) {
index 9854b07a6c43b058422aaec94d2afcc960c7ce5a..53ce02c08996587d30bf583f739856e1e18ee052 100644 (file)
@@ -673,8 +673,10 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
 
   // Finalize the output stream if there are no errors and if the client wants
   // us to.
-  if (!HadError && !NoFinalize)
+  if (!HadError && !NoFinalize) {
+    getTargetParser().emitEndOfAsmFile(Out);
     Out.Finish();
+  }
 
   return HadError;
 }
@@ -779,7 +781,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
           // temporary label to the streamer and refer to it.
           MCSymbol *Sym = Ctx.CreateTempSymbol();
           Out.EmitLabel(Sym);
-          Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
+          Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+                                        getContext());
           EndLoc = FirstTokenLoc;
           return false;
         } else
diff --git a/lib/Target/Mips/AsmParser/MipsAsmFlags.h b/lib/Target/Mips/AsmParser/MipsAsmFlags.h
new file mode 100644 (file)
index 0000000..bf141db
--- /dev/null
@@ -0,0 +1,53 @@
+//=== MipsMCAsmFlags.h - MipsMCAsmFlags --------------------------------===//
+//
+//                    The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENCE.TXT for details.
+//
+//===-------------------------------------------------------------------===//
+#ifndef MIPSMCASMFLAGS_H_
+#define MIPSMCASMFLAGS_H_
+
+namespace llvm {
+class MipsMCAsmFlags;
+
+// We have the flags apart from the ELF defines because state will determine
+// the final values put into the ELF flag bits.
+//
+// Currently we have only Relocation Model, but will soon follow with ABI,
+// Architecture, and ASE.
+class MipsMCAsmFlags {
+public:
+  // These act as bit flags because more that one can be
+  // active at the same time, sometimes ;-)
+  enum MAFRelocationModelTy {
+    MAF_RM_DEFAULT = 0,
+    MAF_RM_STATIC = 1,
+    MAF_RM_CPIC = 2,
+    MAF_RM_PIC = 4
+  } MAFRelocationModel;
+
+public:
+  MipsMCAsmFlags() : Model(MAF_RM_DEFAULT) {}
+
+  ~MipsMCAsmFlags() {}
+
+  // Setting a bit we can later translate to the ELF header flags.
+  void setRelocationModel(unsigned RM) { (Model |= RM); }
+
+  bool isModelCpic() const { return (Model & MAF_RM_CPIC) == MAF_RM_CPIC; }
+  bool isModelPic() const { return (Model & MAF_RM_PIC) == MAF_RM_PIC; }
+  bool isModelStatic() const {
+    return (Model & MAF_RM_STATIC) == MAF_RM_STATIC;
+  }
+  bool isModelDefault() const {
+    return (Model & MAF_RM_DEFAULT) == MAF_RM_DEFAULT;
+  }
+
+private:
+  unsigned Model; // pic, cpic, etc.
+};
+}
+
+#endif /* MIPSMCASMFLAGS_H_ */
index 447e7dc6e1c449a1d270b820c35219c52c259c7b..c2e4bba87b31b3ae82086f0b02e01bca53d05525 100644 (file)
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "AsmParser/MipsAsmFlags.h"
+#include "MCTargetDesc/MipsELFStreamer.h"
 #include "MCTargetDesc/MipsMCTargetDesc.h"
 #include "MipsRegisterInfo.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -59,6 +61,7 @@ class MipsAsmParser : public MCTargetAsmParser {
   MCSubtargetInfo &STI;
   MCAsmParser &Parser;
   MipsAssemblerOptions Options;
+  MipsMCAsmFlags Flags;
   bool hasConsumedDollar;
 
 #define GET_ASSEMBLER_HEADER
@@ -228,6 +231,8 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   bool processInstruction(MCInst &Inst, SMLoc IDLoc,
                         SmallVectorImpl<MCInst> &Instructions);
+  void emitEndOfAsmFile(MCStreamer &Out);
+
 public:
   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
                 const MCInstrInfo &MII)
@@ -2172,9 +2177,23 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
     return false;
   }
 
+  if (IDVal == ".abicalls") {
+    Flags.setRelocationModel(MipsMCAsmFlags::MAF_RM_CPIC);
+    if (Parser.getTok().isNot(AsmToken::EndOfStatement))
+      return Error(Parser.getTok().getLoc(), "unexpected token in directive");
+    return false;
+  }
+
   return true;
 }
 
+/// End of assembly processing such as updating ELF header flags.
+void MipsAsmParser::emitEndOfAsmFile(MCStreamer &OutStreamer) {
+  if (MipsELFStreamer *MES = dyn_cast<MipsELFStreamer>(&OutStreamer))
+    MES->emitELFHeaderFlagsAsm(Flags);
+  MCTargetAsmParser::emitEndOfAsmFile(OutStreamer);
+}
+
 extern "C" void LLVMInitializeMipsAsmParser() {
   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
index cfcb877805af46b269aa8118d3b07f63ef753f91..144cb1e4397e02b95801b0d1ec8777b013ef9bd1 100644 (file)
@@ -7,6 +7,7 @@
 //
 //===-------------------------------------------------------------------===//
 #include "MCTargetDesc/MipsELFStreamer.h"
+#include "AsmParser/MipsAsmFlags.h"
 #include "MipsSubtarget.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCELF.h"
@@ -66,10 +67,26 @@ namespace llvm {
     Reloc::Model RM = Subtarget.getRelocationModel();
     if (RM == Reloc::PIC_ || RM == Reloc::Default)
       EFlags |= ELF::EF_MIPS_PIC;
-    else if (RM == Reloc::Static)
+
+    MCA.setELFHeaderEFlags(EFlags);
+  }
+
+  // For llvm-mc. Set a group of ELF header flags
+  void MipsELFStreamer::emitELFHeaderFlagsAsm(const MipsMCAsmFlags &Flags) {
+
+    // Update e_header flags
+    MCAssembler &MCA = getAssembler();
+    unsigned EFlags = MCA.getELFHeaderEFlags();
+
+    // Relocation Model
+    if (Flags.isModelCpic() || Flags.isModelDefault())
+      EFlags |= ELF::EF_MIPS_CPIC;
+    if (Flags.isModelStatic())
       ; // Do nothing for Reloc::Static
+    else if (Flags.isModelPic() || Flags.isModelDefault())
+      EFlags |= ELF::EF_MIPS_PIC;
     else
-      llvm_unreachable("Unsupported relocation model for e_flags");
+      assert(0 && "Unsupported relocation model for e_flags");
 
     MCA.setELFHeaderEFlags(EFlags);
   }
index b10ccc78e665b0b70642dbdca82fe6056b91ef5c..9987f348ae6085426126afbdbb0ea7849628f7b8 100644 (file)
@@ -13,6 +13,7 @@
 
 namespace llvm {
 class MipsAsmPrinter;
+class MipsMCAsmFlags;
 class MipsSubtarget;
 class MCSymbol;
 
@@ -26,6 +27,7 @@ public:
 
   ~MipsELFStreamer() {}
   void emitELFHeaderFlagsCG(const MipsSubtarget &Subtarget);
+  void emitELFHeaderFlagsAsm(const MipsMCAsmFlags &MAFlags);
   void emitMipsSTOCG(const MipsSubtarget &Subtarget,
                      MCSymbol *Sym,
                      unsigned Val);
index 1dc3326578354dda309263b93526e9c1acd242df..b12cb625a789026061a69e165295b9c98df5413b 100644 (file)
@@ -594,8 +594,8 @@ void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) {
   // Emit Mips ELF register info
   Subtarget->getMReginfo().emitMipsReginfoSectionCG(
              OutStreamer, getObjFileLowering(), *Subtarget);
-  if (MipsELFStreamer *MES = dyn_cast<MipsELFStreamer>(&OutStreamer))
-    MES->emitELFHeaderFlagsCG(*Subtarget);
+  MipsELFStreamer *MES = cast<MipsELFStreamer>(&OutStreamer);
+  MES->emitELFHeaderFlagsCG(*Subtarget);
 }
 
 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
index bbb26165523cbe95460d14744db89e14144f707e..b1f8182728868bc89fc7be33c27e77c8b6c47c13 100644 (file)
@@ -1,9 +1,12 @@
 # RUN: llvm-mc -show-encoding -triple mips-unknown-unknown %s | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple mips-unknown-unknown %s | \
+# RUN: llvm-readobj -h | FileCheck -check-prefix=CHECK-ELF %s
 #
 # CHECK:  .text
 # CHECK:  $BB0_2:
 $BB0_2:
-  .ent directives_test
+    .ent directives_test
+    .abicalls
     .frame    $sp,0,$ra
     .mask     0x00000000,0
     .fmask    0x00000000,0
@@ -43,3 +46,5 @@ $JTI0_0:
 # CHECK:    and     $3, $15, $15       # encoding: [0x01,0xef,0x18,0x24]
     abs.s  f6,FPU_MASK
     and    r3,$t7,STORE_MASK
+
+# CHECK-ELF: Flags [ (0x6)