[PATCH][AsmParser][MC] Allow asm parser to emit elf header flags
Jim Grosbach
grosbach at apple.com
Wed Oct 2 14:41:33 PDT 2013
Hey guys. Really sorry for the delay. Totally my fault. Hopefully today or tomorrow.
On Oct 2, 2013, at 2:39 PM, Jack Carter <Jack.Carter at imgtec.com> wrote:
> Ping :-)
> From: Vladimir Medic
> Sent: Tuesday, September 10, 2013 12:52 AM
> To: llvm-commits at cs.uiuc.edu
> Cc: Jack Carter; Jim Grosbach
> Subject: RE: [PATCH][AsmParser][MC] Allow asm parser to emit elf header flags
>
> Hi all,
> 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).
>
> It has been suggested that we use AsmPrinter::EmitEndOfAsmFile() to
> trigger the updating of the ELF header flags, but as far as we can tell
> MipsAsmPrinter is not available for the AsmParser.
>
> Also, the location of the call to emitEndOfAsmFile() is our best guess for when
> the input assembler file processing is at an end. If there is a better location
> for this please be specific and we will make the change.
>
> We have separate enum values for the relocation models than are in the ELF
> defines for Mips because static (non-shared) model is an active state, but is
> represented by 0 in the flags. Also we want to have a "default" state.
>
> Kind regards
>
> Vladimir
> From: Jim Grosbach [grosbach at apple.com]
> Sent: Monday, August 26, 2013 11:08 PM
> To: Vladimir Medic
> Cc: llvm-commits at cs.uiuc.edu; Jack Carter
> Subject: Re: [PATCH][AsmParser][MC] Allow asm parser to emit elf header flags
>
> Hi Vladimir,
>
> Detailed comments inline below.
>
> Generally speaking, please run new code through clang-format. There are lots of small formatting problems here and there that tool will help clean up without having to fuss about the details.
>
> I don’t have much to comment on regarding the Mips specific side of things. You guys know that stuff better than I do.
>
>
>> Index: test/MC/Mips/mips_directives.s
>> ===================================================================
>> --- test/MC/Mips/mips_directives.s
>> (revision 188764)
>> +++ test/MC/Mips/mips_directives.s
>> (working copy)
>> @@ -3,7 +3,10 @@
>> # CHECK: .text
>> # CHECK: $BB0_2:
>> $BB0_2:
>> - .ent directives_test
>> + .ent directives_test
>> + .abicalls
>> + .option pic0
>> + .set mips16
>> .frame $sp,0,$ra
>> .mask 0x00000000,0
>> .fmask 0x00000000,0
>> Index: include/llvm/MC/MCTargetAsmParser.h
>> ===================================================================
>> --- include/llvm/MC/MCTargetAsmParser.h
>> (revision 188764)
>> +++ include/llvm/MC/MCTargetAsmParser.h
>> (working copy)
>> @@ -174,6 +174,10 @@
>>
>> virtual void convertToMapAndConstraints(unsigned Kind,
>> const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
>> +
>> + /// setAssemblerDialect - Target specific cleanup such as Ehdr flag setting.
>> + /// Analogous to MipsAsmPrinter::EmitEndOfAsmFile().
>> + virtual void emitEndOfObjFile(MCStreamer &Out) { }
>
> The comment doesn’t match the function.
>
> Relatedly, please refer to http://llvm.org/docs/CodingStandards.html#doxygen-use-in-documentation-comments for the latest style preferences for these comments. I wouldn’t trust that the surrounding code is up-to-date.
>
> That said, why is this function necessary at all? EmitEndOfAsmFile() is called even for object files.
>
>> };
>>
>> } // End llvm namespace
>> Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp
>> ===================================================================
>> --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp
>> (revision 188764)
>> +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp
>> (working copy)
>> @@ -7,6 +7,8 @@
>> //
>> //===----------------------------------------------------------------------===//
>>
>> +#include "AsmParser/MipsAsmFlags.h"
>> +#include "MCTargetDesc/MipsELFStreamer.h"
>> #include "MCTargetDesc/MipsMCTargetDesc.h"
>> #include "MipsRegisterInfo.h"
>> #include "llvm/ADT/StringSwitch.h"
>> @@ -63,6 +65,7 @@
>> MCSubtargetInfo &STI;
>> MCAsmParser &Parser;
>> MipsAssemblerOptions Options;
>> + MipsMCAsmFlags Flags;
>> bool hasConsumedDollar;
>>
>> #define GET_ASSEMBLER_HEADER
>> @@ -166,6 +169,8 @@
>>
>> bool parseDirectiveWord(unsigned Size, SMLoc L);
>>
>> + bool parseDirectiveOption();
>> +
>> MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
>>
>> bool isMips64() const {
>> @@ -198,11 +203,20 @@
>>
>> bool processInstruction(MCInst &Inst, SMLoc IDLoc,
>> SmallVectorImpl<MCInst> &Instructions);
>> + void emitEndOfObjFile(MCStreamer &Out);
>> +
>> + void setAbiTy();
>> + void setArchTy();
>> + void setAseTy();
>
> setXXX() is the usual name for the setter of a getter/setter pair. These are a different sort of thing, and should be named differently. Comments about what they do would be good.
>
>
>> +
>> public:
>> MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
>> : MCTargetAsmParser(), STI(sti), Parser(parser), hasConsumedDollar(false) {
>> // Initialize the set of available features.
>> setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
>> + setAbiTy();
>> + setArchTy();
>> + setAseTy();
>
> Since these are just called once, and all in order, why have three separate functions at all?
>
>> }
>>
>> MCAsmParser &getParser() const { return Parser; }
>> @@ -446,6 +460,43 @@
>> return MipsInsts[Opcode];
>> }
>>
>> +void MipsAsmParser::setAbiTy() {
>> + uint64_t FeatureBits = STI.getFeatureBits();
>> + unsigned AbiType = MipsMCAsmFlags::MAF_ABI_DEFAULT;
>> + if (FeatureBits & Mips::FeatureN32)
>> + AbiType = MipsMCAsmFlags::MAF_ABI_N32;
>> + else if (FeatureBits & Mips::FeatureO32)
>> + AbiType = MipsMCAsmFlags::MAF_ABI_O32;
>> + else if (FeatureBits & Mips::FeatureN64)
>> + AbiType = MipsMCAsmFlags::MAF_ABI_N64;
>> +
>> + Flags.setAbi(AbiType);
>> +}
>> +void MipsAsmParser::setArchTy() {
>> + uint64_t FeatureBits = STI.getFeatureBits();
>> + unsigned ArchType = MipsMCAsmFlags::MAF_ARCH_DEFAULT;
>> + if (FeatureBits & Mips::FeatureMips64r2)
>> + ArchType = MipsMCAsmFlags::MAF_ARCH_64R2;
>> + else if (FeatureBits & Mips::FeatureMips64)
>> + ArchType = MipsMCAsmFlags::MAF_ARCH_64R1;
>> + else if (FeatureBits & Mips::FeatureMips32r2)
>> + ArchType = MipsMCAsmFlags::MAF_ARCH_32R2;
>> + else if (FeatureBits & Mips::FeatureMips32)
>> + ArchType = MipsMCAsmFlags::MAF_ARCH_32R1;
>> +
>> + Flags.setArch(ArchType);
>> +
>> +}
>> +void MipsAsmParser::setAseTy() {
>> + uint64_t FeatureBits = STI.getFeatureBits();
>> + unsigned AseType = MipsMCAsmFlags::MAF_ASE_DEFAULT;
>> + if (FeatureBits & Mips::FeatureMips16)
>> + AseType = MipsMCAsmFlags::MAF_ASE_MIPS16;
>> + else if (FeatureBits & Mips::FeatureMicroMips)
>> + AseType = MipsMCAsmFlags::MAF_ASE_MICROMIPS;
>> + Flags.setAse(AseType);
>> +}
>> +
>> bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
>> SmallVectorImpl<MCInst> &Instructions) {
>> const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
>> @@ -1807,14 +1858,30 @@
>> } else if (Tok.getString() == "nomacro") {
>> return parseSetNoMacroDirective();
>> } else if (Tok.getString() == "nomips16") {
>> - // Ignore this directive for now.
>> - Parser.eatToEndOfStatement();
>> + if ((STI.getFeatureBits() & Mips::FeatureMips16))
>> + STI.ToggleFeature(Mips::FeatureMips16);
>> + Flags.setAse(MipsMCAsmFlags::MAF_ASE_DEFAULT);
>> + Parser.Lex();
>> return false;
>> - } else if (Tok.getString() == "nomicromips") {
>> - // Ignore this directive for now.
>> - Parser.eatToEndOfStatement();
>> + } else if (Tok.getString() == "mips16") {
>> + if (!(STI.getFeatureBits() & Mips::FeatureMips16))
>> + STI.ToggleFeature(Mips::FeatureMips16);
>> + Flags.setAse(MipsMCAsmFlags::MAF_ASE_MIPS16);
>> + Parser.Lex();
>> return false;
>> - } else {
>> + }else if (Tok.getString() == "nomicromips") {
>> + if (STI.getFeatureBits() & Mips::FeatureMicroMips)
>> + STI.ToggleFeature(Mips::FeatureMicroMips);
>> + Flags.setAse(MipsMCAsmFlags::MAF_ASE_DEFAULT);
>> + Parser.Lex();
>> + return false;
>> + } else if (Tok.getString() == "micromips") {
>> + if (!(STI.getFeatureBits() & Mips::FeatureMicroMips))
>> + STI.ToggleFeature(Mips::FeatureMicroMips);
>> + Flags.setAse(MipsMCAsmFlags::MAF_ASE_MICROMIPS);
>> + Parser.Lex();
>> + return false;
>> + }else {
>> // It is just an identifier, look for an assignment.
>> parseSetAssignment();
>> return false;
>> @@ -1848,6 +1915,36 @@
>> return false;
>> }
>>
>> +bool MipsAsmParser::parseDirectiveOption() {
>> + // Get the option token
>> + AsmToken Tok = Parser.getTok();
>> + // At the moment only identifiers are supported
>> + if (Tok.isNot(AsmToken::Identifier)) {
>> + // Clear line
>> + Parser.eatToEndOfStatement();
>> + return Error(Tok.getLoc(), "unexpected token in directive");
>> + }
>> + StringRef Option = Tok.getIdentifier();
>> + if (Option == "pic0") {
>> + Flags.setRelocationModel(MipsMCAsmFlags::MAF_RM_STATIC);
>> + Parser.Lex();
>> + if (Parser.getTok().isNot(AsmToken::EndOfStatement))
>> + return Error(Parser.getTok().getLoc(), "unexpected token in directive");
>> + return false;
>> + }
>> +
>> + if (Option == "pic2") {
>> + Flags.setRelocationModel(MipsMCAsmFlags::MAF_RM_PIC);
>> + Parser.Lex();
>> + if (Parser.getTok().isNot(AsmToken::EndOfStatement))
>> + return Error(Parser.getTok().getLoc(), "unexpected token in directive");
>> + return false;
>> + }
>> + // Unknown option
>> + Parser.eatToEndOfStatement();
>> + return Warning(Parser.getTok().getLoc(), "unknown option in directive");
>> +}
>> +
>> bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
>>
>> StringRef IDVal = DirectiveID.getString();
>> @@ -1897,9 +1994,29 @@
>> return false;
>> }
>>
>> + if (IDVal == ".abicalls") {
>> + // TODO: Set the Reloc::PIC_
>> + Flags.setRelocationModel(MipsMCAsmFlags::MAF_RM_PIC);
>> + if (Parser.getTok().isNot(AsmToken::EndOfStatement))
>> + return Error(Parser.getTok().getLoc(), "unexpected token in directive");
>> + return false;
>> + }
>> + if (IDVal == ".option") {
>> + return parseDirectiveOption();
>> + }
>> +
>> return true;
>> }
>>
>> +/// setAssemblerDialect -
>> +/// Analogous to MipsAsmPrinter::EmitEndOfAsmFile().
>
> Incorrect comment again.
>> +void MipsAsmParser::emitEndOfObjFile(MCStreamer &OutStreamer)
>> +{
>> + if (MipsELFStreamer *MES = dyn_cast<MipsELFStreamer>(&OutStreamer))
>> + MES->emitELFHeaderFlagsAsm(Flags);
>> + MCTargetAsmParser::emitEndOfObjFile(OutStreamer);
>> +}
>
> This can definitely be done without this function being added. See how ARM handles the EHDR flags.
>
>> +
>> extern "C" void LLVMInitializeMipsAsmParser() {
>> RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
>> RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
>> Index: lib/Target/Mips/AsmParser/MipsAsmFlags.h
>> ===================================================================
>> --- lib/Target/Mips/AsmParser/MipsAsmFlags.h
>> (revision 0)
>> +++ lib/Target/Mips/AsmParser/MipsAsmFlags.h
>> (revision 0)
>> @@ -0,0 +1,93 @@
>> +//=== 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;
>> +
>> +class MipsMCAsmFlags {
>> +public:
>> + enum MAFAbiTy {
>> + MAF_ABI_DEFAULT,
>> + MAF_ABI_O32,
>> + MAF_ABI_N32,
>> + MAF_ABI_N64
>> + } MAFAbi;
>> +
>> + // 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;
>> +
>> + enum MAFArchTy {
>> + MAF_ARCH_DEFAULT,
>> + MAF_ARCH_32R1,
>> + MAF_ARCH_32R2,
>> + MAF_ARCH_64R1,
>> + MAF_ARCH_64R2
>> + } MAFArch;
>> +
>> + enum MAFAseTy {
>> + MAF_ASE_DEFAULT,
>> + MAF_ASE_MIPS16,
>> + MAF_ASE_MICROMIPS
>> + } MAFAse;
>> +
>
> Shouldn’t these be part of the MIPS ELF object file information if they’re not already? They’re not really internal to the MIPS AsmParser, right?
>
>> +public:
>> + MipsMCAsmFlags()
>> + : abi(MAF_ABI_DEFAULT),
>> + model(MAF_RM_DEFAULT),
>> + arch(MAF_ARCH_DEFAULT),
>> + ase(MAF_ASE_DEFAULT) {}
>> +
>> + ~MipsMCAsmFlags() {}
>> +
>> + // This is simplistic. Mips16 may need on off switches.
>> + void setAbi(unsigned Abi) {(abi = Abi);}
>> + void setRelocationModel(unsigned RM) {(model |= RM);}
>> + void setArch(unsigned Arch) {(arch = Arch);}
>> + void setAse(unsigned Ase) {(ase = Ase);}
>> +
>> + bool isAbiO32() const {return (abi == MAF_ABI_O32);}
>> + bool isAbiN32() const {return (abi == MAF_ABI_N32);}
>> + bool isAbiN64() const {return (abi == MAF_ABI_N64);}
>> + bool isAbiDefault() const {return (abi == MAF_ABI_DEFAULT);}
>> +
>> + 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;
>> + }
>> +
>> + bool isArch32r1() const {return (arch == MAF_ARCH_32R1);}
>> + bool isArch32r2() const {return (arch == MAF_ARCH_32R2);}
>> + bool isArch64r1() const {return (arch == MAF_ARCH_64R1);}
>> + bool isArch64r2() const {return (arch == MAF_ARCH_64R2);}
>> + bool isArchDefault() const {return (arch == MAF_ARCH_DEFAULT);}
>> +
>> + bool isAseMips16() const {return (ase == MAF_ASE_MIPS16);}
>> + bool isAseMicroMips() const {return (ase == MAF_ASE_MICROMIPS);}
>> + bool isAseDefault() const {return (ase == MAF_ASE_DEFAULT);}
>> +
>> +private:
>> + unsigned abi; // o32, n32, n64, etc.
>> + unsigned model; // pic, cpic, etc.
>> + unsigned arch; // 32, 32r2, 64,etc.
>> + unsigned ase; // 16, MicroMips, etc.
>
> Class member variables shouldn’t be all-lower-case. See http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly
>
>> +};
>> +
>> +}
>> +
>> +#endif /* MIPSMCASMFLAGS_H_ */
>> Index: lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
>> ===================================================================
>> --- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
>> (revision 188764)
>> +++ lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
>> (working copy)
>> @@ -6,6 +6,7 @@
>> // License. See LICENSE.TXT for details.
>> //
>> //===-------------------------------------------------------------------===//
>> +#include "AsmParser/MipsAsmFlags.h"
>> #include "MCTargetDesc/MipsELFStreamer.h"
>> #include "MipsSubtarget.h"
>> #include "llvm/MC/MCAssembler.h"
>> @@ -74,6 +75,59 @@
>> 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();
>> +
>> + if (Flags.isAseMips16())
>> + EFlags |= ELF::EF_MIPS_ARCH_ASE_M16;
>> + else if (Flags.isAseMicroMips())
>> + EFlags |= ELF::EF_MIPS_ARCH_ASE_M16;
>> + else
>> + EFlags |= ELF::EF_MIPS_NOREORDER;
>> +
>> + // Architecture
>> + if (Flags.isArch64r2())
>> + EFlags |= ELF::EF_MIPS_ARCH_64R2;
>> + else if (Flags.isArch64r1())
>> + EFlags |= ELF::EF_MIPS_ARCH_64;
>> + else if (Flags.isArch32r2())
>> + EFlags |= ELF::EF_MIPS_ARCH_32R2;
>> + else
>> + EFlags |= ELF::EF_MIPS_ARCH_32;
>> +
>> + if (Flags.isAseMicroMips())
>> + EFlags |= ELF::EF_MIPS_MICROMIPS;
>> +
>> + // ABI
>> + if (Flags.isAbiO32() || Flags.isAbiDefault())
>> + EFlags |= ELF::EF_MIPS_ABI_O32;
>> +// else if (Flags.isAbiN32())
>> +// EFlags |= ELF::EF_MIPS_ABI2;
>> +// else if (Flags.isAbiN64())
>> +// EFlags |= ELF::EF_MIPS_ABI2;
>
> Please remove commented out code.
>
>> + else
>> + llvm_unreachable("Unsupported ABI for e_flags");
>> +
>> + // Relocation Model
>> + // TODO: Need to add -mabicalls and -mno-abicalls flags.
>> + // Currently we assume that -mabicalls is the default.
>> + if (Flags.isModelCpic() || Flags.isModelDefault())
>> + EFlags |= ELF::EF_MIPS_CPIC;
>> + if (Flags.isModelPic() || Flags.isModelDefault())
>> + EFlags |= ELF::EF_MIPS_PIC;
>> + else if (Flags.isModelStatic())
>> + ; // Do nothing for Reloc::Static
>> + else
>> + llvm_unreachable("Unsupported relocation model for e_flags");
>> +
>> + MCA.setELFHeaderEFlags(EFlags);
>> + }
>> +
>> // For llc. Set a symbol's STO flags
>> void
>> MipsELFStreamer::emitMipsSTOCG(const MipsSubtarget &Subtarget,
>> Index: lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
>> ===================================================================
>> --- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
>> (revision 188764)
>> +++ lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
>> (working copy)
>> @@ -13,6 +13,7 @@
>>
>> namespace llvm {
>> class MipsAsmPrinter;
>> +class MipsMCAsmFlags;
>> class MipsSubtarget;
>> class MCSymbol;
>>
>> @@ -26,6 +27,7 @@
>>
>> ~MipsELFStreamer() {}
>> void emitELFHeaderFlagsCG(const MipsSubtarget &Subtarget);
>> + void emitELFHeaderFlagsAsm(const MipsMCAsmFlags &MAFlags);
>> void emitMipsSTOCG(const MipsSubtarget &Subtarget,
>> MCSymbol *Sym,
>> unsigned Val);
>
> On Aug 20, 2013, at 7:28 AM, Vladimir Medic <Vladimir.Medic at imgtec.com> wrote:
>
>> The assembler effects changes to the ELF environment through commandline
>> options and inline directives. These need to be written out into the ELF
>> header's eflags.
>>
>> The mechanism for this is through the MCELFStreamer. We have modeled the
>> assembler's version after the previously implemented codegen one.
>>
>> I'm looking forward to your comments and remarks
>>
>> Vladimir
>> <MipsElfFlags.patch>_______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131002/48f257a1/attachment.html>
More information about the llvm-commits
mailing list