diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 6e96e8becda..512fd8649ae 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -176,6 +176,11 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const SmallVectorImpl &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) { diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 9854b07a6c4..53ce02c0899 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -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 index 00000000000..bf141db6320 --- /dev/null +++ b/lib/Target/Mips/AsmParser/MipsAsmFlags.h @@ -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_ */ diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 447e7dc6e1c..c2e4bba87b3 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -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 &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(&OutStreamer)) + MES->emitELFHeaderFlagsAsm(Flags); + MCTargetAsmParser::emitEndOfAsmFile(OutStreamer); +} + extern "C" void LLVMInitializeMipsAsmParser() { RegisterMCAsmParser X(TheMipsTarget); RegisterMCAsmParser Y(TheMipselTarget); diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index cfcb877805a..144cb1e4397 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -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); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index b10ccc78e66..9987f348ae6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -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); diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 1dc33265783..b12cb625a78 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -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(&OutStreamer)) - MES->emitELFHeaderFlagsCG(*Subtarget); + MipsELFStreamer *MES = cast(&OutStreamer); + MES->emitELFHeaderFlagsCG(*Subtarget); } void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, diff --git a/test/MC/Mips/mips_directives.s b/test/MC/Mips/mips_directives.s index bbb26165523..b1f81827288 100644 --- a/test/MC/Mips/mips_directives.s +++ b/test/MC/Mips/mips_directives.s @@ -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)