MCELFStreamer subclassing

I need to create a subclass that derives from MCELFStreamer.

We use MCELFStreamer for direct object generation and need to override a virtual method in the base class MCStreamer::EmitGPRel32Value().

I have been having trouble creating the subclass due to #include issues. I can’t seem to get it right at the lib/target//MCTargetDesc level. My first thought is always that I am doing something wrong and that may still be the issue, but it is suspicious that no one has subclassed MCELFStreamer yet.

Am I missing something obvious or is this class in need of header file reorganization?

Any constructive suggestion is welcome. I need to get my gp relative data relocations generated :slight_smile:

Jack

Hi Jack,

Can you elaborate a bit on what you're trying to do? Relocations are handled by the ObjectWriter interfaces, not by the streamer. The <ObjectFormat>Streamer classes aren't intended to be subclassed by targets.

-Jim

Well Jim, that may just be my problem.

As background I am working on the outer reaches of llvm for the direct object output for Mips. Part of what I am to do is instruct the folks working closer to the backend what I am getting that is incorrect. My first reaction is to assume that I am being fed things the correct way and that I am not handling it correctly.

I feed the compiler a source file (attached) -O0 that untilizes a switch statement. This produces, in Mips, an rodata section with gp relative relocations associated with it. I know this because that is what I get when producing a .s file and then running gas on it. When compiling for direct object output I got the error stemming from MCStreamer.

Since we are using MCELFStreamer, my assumption (possibly/probably wrong) was that we needed to subclass MCELFStreamer to somehow set the magic flag so that the relocation get generated.

in AsmPrinter::EmitJumpTableEntry, MJTI->getEntryKind() is of type EK_GPRel32BlockAddress.

Any insight is appreciated. I am rereading the llvm documentation. Right now it is magic to me and need to have the magic turn into knowledge.

Thanks,

Jack

switch.c (1.4 KB)

Hi Jack,

I'm not 100% up on how MIPS represents jump tables, so take with a grain of salt and all that.

Normally how this stuff works is that the streamer will create Fixups (MCDataFragment::addFixup()) for anything that might require a relocation. That may come from the generic streamer stuff (see MCObjectStreamer::EmitValueImpl() for example), or from the target's MCCodeEmitter (for any target-specific fixups in code, for example). Then the object streamer resolves those fixups, directly if it can or via relocations otherwise via the MCObjectWriter::RecordRelocation() hook. For MachO, that's been moved to a target hook, but for ELF that's directly in ELFObjectWriter.cpp still, including all the target specific bits.

For your specific problem, I suspect what needs to happen is something like:

1) In MCELFStreamer(), implement EmitGPRel32Value() to add an appropriate fixup, and
2) in ELFObjectWriter.cpp, teach the Mips bits what relocation type to use for that fixup, if it doesn't know already. (MipsELFObjectWriter::GetRelocType()).

Regards,

-Jim

Jim,

Ok, you are where I am in the understanding. This is exactly what I do for relocations applied to code. Now I want to apply fixup information to relocations applied to data.

The issue I was having was the difficulty of subclassing MCELFStreamer. Or are you saying that I should be messing with the base MCELFStreamer for a specific fixup.

One of the issues I hit initially with llvm is that in terms of relocation and fixups there was an assumption of universal fixups/relocation types. That was really Utopian. These need to be all down in the Target regions and not in the base classes. Eventually we will have to change the organization of MCExpr to allow this, but I digress.

If I am to subclass MCELFStreamer, that brings me back to my original question. Is it possible to do this currently at the Target/<my processor>/MCTargetDesc level or are the class headers not organized correctly for this?

If I am to change MCELFStreamer base for this method, I will be introducing Mips specific fixup information.

Jack

Jim,

Ok, you are where I am in the understanding. This is exactly what I do for relocations applied to code. Now I want to apply fixup information to relocations applied to data.

The issue I was having was the difficulty of subclassing MCELFStreamer. Or are you saying that I should be messing with the base MCELFStreamer for a specific fixup.

No subclassing needed. Are you sure the fixup needs to be Mips specific? That would be highly unusual for a data section. Normally, the data fixup is target-independent, then it's mapped to a target-dependent relocation by the object writer (the step 2 below). I strongly suspect we want to add a generic GP-relative fixup to MCFixup.h and just use that. There's nothing inherently MIPS-specific to having a global pointer.

Daniel, are you aware of anything w/ this sort of fixup that would necessitate target-specific logic before we get to relocations?

-Jim

Jim,

Ok, you are where I am in the understanding. This is exactly what I do for relocations applied to code. Now I want to apply fixup information to relocations applied to data.

The issue I was having was the difficulty of subclassing MCELFStreamer. Or are you saying that I should be messing with the base MCELFStreamer for a specific fixup.

No subclassing needed. Are you sure the fixup needs to be Mips specific? That would be highly unusual for a data section. Normally, the data fixup is target-independent, then it's mapped to a target-dependent relocation by the object writer (the step 2 below). I strongly suspect we want to add a generic GP-relative fixup to MCFixup.h and just use that. There's nothing inherently MIPS-specific to having a global pointer.

Daniel, are you aware of anything w/ this sort of fixup that would necessitate target-specific logic before we get to relocations?

Not offhand, although we would need to know more details about the
exact fixup/relocation required.

Regardless, Jim is right, this shouldn't require subclassing the
MCELFStreamer. The goal is that we use common fix-up kinds when
possible, but even if the particular data relocation required (and I
do recall that MIPS has some curious ones) a custom fix-up, that still
wouldn't require subclassing.

For example, look at how ARM handles upper and lower. Take a look at
  ARM/MCTargetDesc/ARMMCExpr.h
  ARM/ARMAsmPrinter.cpp
  ARM/MCTargetDesc/ARMFixupKinds.h
  ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
  ARM/MCTargetDesc/ARMMachObjectWriter.cpp

- Daniel

So what I am hearing is that I should add the following to MC/MCFixup.h:

  FK_GPRel_1, ///< A one-byte pc relative fixup.
  FK_GPRel_2, ///< A two-byte pc relative fixup.
  FK_GPRel_4, ///< A four-byte pc relative fixup.
  FK_GPRel_8, ///< A eight-byte pc relative fixup.

In MC/MCStreamer.cpp MCStreamer::EmitGpRel32Value()

  Figure out how to mark it with the imprint of FK_GPRel_4

In MC/ELFObjectWriter.cpp MipsELFObjectWriter::GetRelocType()

  Add a switch case for FK_GPRel_4 to put out the correct target specific relocation.

Is that correct? Did I miss anything?

Thanks,

Jack

Yep, that's the idea.

So what I am hearing is that I should add the following to MC/MCFixup.h:

FK_GPRel_1, ///< A one-byte pc relative fixup.
FK_GPRel_2, ///< A two-byte pc relative fixup.
FK_GPRel_4, ///< A four-byte pc relative fixup.
FK_GPRel_8, ///< A eight-byte pc relative fixup.

Comments need to be changed to reference GP rather than PC.