emitting function stub for mips16 floating point patch

I'm rewriting this patch for the stubs to not use outputing of raw text.

Generating the instructions is very straightforward and that part is done.

I'm translating the actual function now.

How do you emit an .ent or .globl from asm printer?
.type ?
.end ??
.section ???

I'm studying the classes now but it should be simple to do so if you know, you can save me some time
because this is another maze of llvm data abstraction.

Tia.

Reed

void MipsAsmPrinter::EmitFPCallStub(
   const char* Symbol, const Mips16HardFloatInfo::FuncSignature* Signature) {
   OutStreamer.EmitRawText("\t.globl "+ Twine(Symbol));
.........
   OutStreamer.EmitRawText("\t# Stub function to call " + Twine(RetType) +
                           " " + Twine(Symbol) + " (" + Twine(Parms) + ")");
OutStreamer.EmitRawText("\t.section\t.mips16.call.fp"+Twine(Symbol)+",\"ax\",@progbits");
   OutStreamer.EmitRawText(".align 2");
   OutStreamer.EmitRawText(".nomips16");
   OutStreamer.EmitRawText(".nomicromips");
   OutStreamer.EmitRawText("\t.ent\t__call_stub_fp_" + Twine(Symbol));
   OutStreamer.EmitRawText("\t.type\t__call_stub_fp_" + Twine(Symbol) + ", @function");
   OutStreamer.EmitRawText("\t__call_stub_fp_" + Twine(Symbol) + ":");
   OutStreamer.EmitRawText("\t.size __call_stub_fp_" + Twine(Symbol) +
                           ", .-__call_stub_fp_" + Twine(Symbol));
   OutStreamer.EmitRawText("\t.end __call_stub_fp_" + Twine(Symbol))

I'm rewriting this patch for the stubs to not use outputing of raw text.

Generating the instructions is very straightforward and that part is done.

I'm translating the actual function now.

How do you emit an .ent or .globl from asm printer?
.type ?
.end ??
.section ???

I'm studying the classes now but it should be simple to do so if you know, you can save me some time
because this is another maze of llvm data abstraction.

Tia.

Reed

We already have this MIpsTargetStreamer class which seems like a place where this could be added.

Given the big storm around any kind of raw text I don't want to add to this if this is already something
we are not supposed to be doing.

Hi Reed,

I think you need to look at:
* MCStreamer::SwitchSection() for .section.
* MipsTargetStreamer::emitDirectiveEnt() for .ent
* MCAsmStreamer::EmitSymbolAttribute() for .globl, and .type

I couldn't find a function for .end. I expect it's there but it's difficult to grep for because it clashes with iterators.

If there are any directives you need that aren't already supported, you'll need an emitX function for each directive in each of the MIPS target streamers. The one in MipsTargetStreamer should be abstract, the one in MipsAsmTargetStreamer should emit the assembly text, and the one in MipsELFTargetStreamer should do the appropriate thing in the ELF. For your purposes you could leave an llvm_unreachable("Not implemented") in the MipsELFTargetStreamer for now, but it would be great if you could implement that as well since someone will have to do it for the planned assembler anyway. If you do implement MipsELFTargetStreamer::emitX(), you will also need to implement the relevant AsmParser support so that you can test the directive (tests using llc -filetype=obj are not ok).
See MipsTargetStreamer::emitDirectiveSetMicroMips() for an example.

I'm rewriting this patch for the stubs to not use outputing of raw text.

Generating the instructions is very straightforward and that part is done.

awesome!

I'm translating the actual function now.

How do you emit an .ent

emitDirectiveEnt in the mips target streamer.

or .globl

EmitSymbolAttribute with MCSA_Global

from asm printer?
.type ?

EmitSymbolAttribute with MCSA_ELF_Type*

.end ??

emitDirectiveEnd on the mips target streamer

.section ???

SwitchSection

I'm studying the classes now but it should be simple to do so if you know,
you can save me some time
because this is another maze of llvm data abstraction.

The rule of the thumb is that each line in assembly is a method in the
streamer or target streamer.

Tia.

Reed

Cheers,
Rafael

THanks.

Your pointers will save some time hunting for the right method.

I have 90% of this done already. Now I know where to look for the remaining methods.

When I finish this one patch (almost done, which is for a specific bug), I'm planning to start to move all the inline assembly code from
pass Mips16HardFloat to this later place in MipsAsmPrinter. Mips16HardFloat pass should shrink to 15% of it's current size. I've already
started to move the infrastructure to this place in MipsAsmPrinter.

We discussed this a while back and I agreed to eventually do this but it was not clear to me at that time exactly where to move it to and it was much
easier for me to do this in the IR pass. Frankly, at that time, I would not have at all thought to move it to AsmPrinter :slight_smile: .
Now I can see where it should go and also understand the gcc mips16 floating
point scheme better (undocumented and complicated at the same time) and how it interacts with llvm and such. It makes sense to move it to AsmPrinter
because in reality the stubs are just a sophisticated asm directive that must be expanded.

There are a few bizarre asm statements that I hardly understand (copied form the gcc mips16 hard float stubs) in some of the yet to be moved stubs.
I may need some additional mc methods to handle those. When I get there we can discuss that.

This scheme is handshake between gcc, gas and ld (all undocumented of course :)))

Reed

Reed

I'm planning to move most of the inline assembly emission

How is alignment set?

Of a symbol? EmitValueToAlignment.

A tip on how to find this is to look at what clang prints
(".align...") and grep for it "git grep '\.align'").

Cheers,
Rafael

Not on a symbol but in a section to set the current value.

I have not found it so far but am looking where this can be in AsmPrinter or MC.

I have these statements left to translate.

Most we already discussed.

.align 2

the .nomips16 and .nomicromips we have it in mipsTargetStreamer (which to me seems
little different from emit raw text).

I think you mentioned already how to do the .size

   OutStreamer.EmitRawText(".align 2");
   OutStreamer.EmitRawText(".nomips16");
   OutStreamer.EmitRawText(".nomicromips");
   OutStreamer.EmitRawText("\t.ent\t__call_stub_fp_" + Twine(Symbol));
   OutStreamer.EmitRawText("\t.type\t__call_stub_fp_" + Twine(Symbol) + ", @function");
   OutStreamer.EmitRawText("\t__call_stub_fp_" + Twine(Symbol) + ":");
   OutStreamer.EmitRawText("\t.size __call_stub_fp_" + Twine(Symbol) +
                           ", .-__call_stub_fp_" + Twine(Symbol));
   OutStreamer.EmitRawText("\t.end __call_stub_fp_" + Twine(Symbol));

Not on a symbol but in a section to set the current value.

If I remember correctly a section is as aligned as its most aligned
symbol. What directive does gcc use?

Cheers,
Rafael

.align

.align

So yes, EmitValueToAlignment.

Cheers,
Rafael

One more:::

   OutStreamer.EmitRawText("\t.size __call_stub_fp_" + Twine(Symbol) +
                           ", .-__call_stub_fp_" + Twine(Symbol));

You have to make an expression???

i.e.

.size __call_stub_fp___floatdidf, .-__call_stub_fp___floatdidf

TIA.

Reed

It seems like usually llvm is creating a temporary symbol to get ".".

tmp2$:

.size __call_stub_fp___floatdidf, (tmp2$)-__call_stub_fp___floatdidf

EmitELFSize takes a MCExpr, so yes.

Cheers,
Rafael

I'm able get this almost.

.size __call_stub_fp___floatdidf, ($tmp6)+(-__call_stub_fp___floatdidf)

is there a way to get a binary minus?

I'm able get this almost.

.size __call_stub_fp___floatdidf, ($tmp6)+(-__call_stub_fp___floatdidf)

is there a way to get a binary minus?

Yes, there is a MCBinaryExpr::Sub.

Cheers,
Rafael

__call_stub_fp___floatdidf:
$tmp6:
     .size __call_stub_fp___floatdidf, ($tmp6)+(-__call_stub_fp___floatdidf)