via llvm-dev
2016-May-21 00:34 UTC
[llvm-dev] Using an MCStreamer Directly to produce an object file?
llvm-dev, Thanks so much in advance for any help, tips, or advice you may be able to offer me. I'm going to try to avoid the big-picture description of the project I'm working on, and only talk about the parts that I have trouble with / currently need to implement. -- I've been starting by taking the source code from the "llvm-mc" tool, and working that down into a smaller form that does the kinds of things I want to do at the MC "layer". So, I'd like to be able to use a MCStreamer object directly to make some output file, and object ".o" would be just fine to start with. I seem to be able to create an aarch64 target without too much issue: llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); std::string Error; std::string TripleName("aarch64-unknown-linux-gnu"); Triple TheTriple(Triple::normalize(TripleName)); const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); if (!TheTarget) { std::cerr << "llvm_insts_to_binary(): " << Error; return 1; } Then, I move on to creating some of the needed ASM / REG info and an MCContext, etc.: std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); std::string MCPU("generic"); std::string FeaturesStr(""); MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TheTriple, llvm::Reloc::Model::PIC_, llvm::CodeModel::Model::Default, Ctx); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); OK, that seems, OK. Now I want to setup an output buffer: std::string ofile("/home/users/avose/hpcgp/hpcgp_rundir/tmp.o"); std::unique_ptr<tool_output_file> Out = GetOutputStream(ofile); if (!Out) { return 1; } std::unique_ptr<buffer_ostream> BOS; raw_pwrite_stream *OS = &Out->os(); if (!Out->os().supportsSeeking()) { BOS = make_unique<buffer_ostream>(Out->os()); OS = BOS.get(); } This also seems to do OK. Now I would think I can finally get around to making the code emitter and the MCStreamer: MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); MCStreamer *Str = TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, *OS, CE, *STI, true, false); So, like, wow, I would think I should be good to go here! I should be able to just use functions like: Str->EmitInstruction(); Str->EmitLabel(); These should then result in everything I've tried to emit coming out in my output object file "tmp.o", you know, as long as I'm careful to be sure to make a call to keep my output file from being deleted. So, when I'm done making "emit" calls like the above, I be sure to do the keep call: Out->keep(); I'm aware that the calls to EmitInstruction(); and EmitLabel(); need to have their arguments properly constructed first, and I do try to do that using the context I had set up before, so, something like: const llvm::Twine tname("my_label_name"); llvm::MCSymbol* mcs = Ctx.getOrCreateSymbol(tname); Str->EmitLabel(mcs); Or even something more complicated like setting up an MCInst and all it's operands: llvm::MCInst *llinst = new MCInst(); llinst->setOpcode(input_opcode); llinst->addOperand(llvm::MCOperand::createReg(input_reg0)); llinst->addOperand(llvm::MCOperand::createReg(input_reg1)); const llvm::Twine tname("label_name"); const llvm::MCSymbol* mcs = Ctx.getOrCreateSymbol(tname); const llvm::MCSymbolRefExpr *msre = llvm::MCSymbolRefExpr::create(mcs, Ctx); llinst->addOperand(llvm::MCOperand::createExpr(msre)); However, while I don't get any compiler errors, and everything runs to completion without printing any errors, my output file "tmp.o" is always created, but just empty with zero bytes. I must be doing something silly here.. Does anyone have any ideas about what I'm doing wrong, or perhaps have example code that directly uses the MCStreamer object to write out object binary files? Some examples showing how to make this work would _really_ make my week. This has been hard to debug, as I don't get any errors, just an empty output .o file... I was thinking it may be because of section issues, so I did add some initial sections, hoping that might help: Str->InitSections(false); MCSection *textsect = Ctx.getELFSection(".text", ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC); Str->SwitchSection(textsect); This did not seem to help at all. I'm running out of ideas. Anyone know how to use an MCStreamer object directly to make and object file? Thanks so much for your time, ~Aaron Vose (Software Engineer) (Cray Inc.)
David Blaikie via llvm-dev
2016-May-22 18:07 UTC
[llvm-dev] Using an MCStreamer Directly to produce an object file?
Personally I looked at llvm-dsymutil as an example of writing a basic object file with MCStreamer when I created llvm-dwp to do a similar task. Perhaps you could model things off either of those? Did you call "Finish" on your MCStreamer? Also, I don't think I needed to use tool_output_file - not sure where that's from. there's simple raw_ostreams that go straight to files. On Fri, May 20, 2016 at 5:34 PM, via llvm-dev <llvm-dev at lists.llvm.org> wrote:> llvm-dev, > > > Thanks so much in advance for any help, tips, or advice you may be able > to offer me. I'm going to try to avoid the big-picture description of > the project I'm working on, and only talk about the parts that I have > trouble with / currently need to implement. -- I've been starting by > taking the source code from the "llvm-mc" tool, and working that down > into a smaller form that does the kinds of things I want to do at the MC > "layer". > > > So, I'd like to be able to use a MCStreamer object directly to make some > output file, and object ".o" would be just fine to start with. > > I seem to be able to create an aarch64 target without too much issue: > > llvm::InitializeAllTargetInfos(); > llvm::InitializeAllTargetMCs(); > llvm::InitializeAllAsmParsers(); > llvm::InitializeAllDisassemblers(); > > std::string Error; > std::string TripleName("aarch64-unknown-linux-gnu"); > Triple TheTriple(Triple::normalize(TripleName)); > const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, > Error); > if (!TheTarget) { > std::cerr << "llvm_insts_to_binary(): " << Error; > return 1; > } > > > Then, I move on to creating some of the needed ASM / REG info and an > MCContext, etc.: > > std::unique_ptr<MCRegisterInfo> > MRI(TheTarget->createMCRegInfo(TripleName)); > assert(MRI && "Unable to create target register info!"); > std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, > TripleName)); > assert(MAI && "Unable to create target asm info!"); > std::string MCPU("generic"); > std::string FeaturesStr(""); > MCObjectFileInfo MOFI; > MCContext Ctx(MAI.get(), MRI.get(), &MOFI); > MOFI.InitMCObjectFileInfo(TheTriple, llvm::Reloc::Model::PIC_, > llvm::CodeModel::Model::Default, Ctx); > std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); > std::unique_ptr<MCSubtargetInfo> > STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); > > > OK, that seems, OK. Now I want to setup an output buffer: > > std::string ofile("/home/users/avose/hpcgp/hpcgp_rundir/tmp.o"); > std::unique_ptr<tool_output_file> Out = GetOutputStream(ofile); > if (!Out) { > return 1; > } > std::unique_ptr<buffer_ostream> BOS; > raw_pwrite_stream *OS = &Out->os(); > if (!Out->os().supportsSeeking()) { > BOS = make_unique<buffer_ostream>(Out->os()); > OS = BOS.get(); > } > > > This also seems to do OK. Now I would think I can finally get around to > making the code emitter and the MCStreamer: > > MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); > MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, > MCPU); > MCStreamer *Str = TheTarget->createMCObjectStreamer(TheTriple, Ctx, > *MAB, *OS, CE, *STI, true, false); > > > So, like, wow, I would think I should be good to go here! I should be > able to just use functions like: > > Str->EmitInstruction(); > Str->EmitLabel(); > > > These should then result in everything I've tried to emit coming out in > my output object file "tmp.o", you know, as long as I'm careful to be > sure to make a call to keep my output file from being deleted. So, when > I'm done making "emit" calls like the above, I be sure to do the keep > call: > > Out->keep(); > > > I'm aware that the calls to EmitInstruction(); and EmitLabel(); need to > have their arguments properly constructed first, and I do try to do that > using the context I had set up before, so, something like: > > const llvm::Twine tname("my_label_name"); > llvm::MCSymbol* mcs = Ctx.getOrCreateSymbol(tname); > Str->EmitLabel(mcs); > > > Or even something more complicated like setting up an MCInst and all > it's operands: > > llvm::MCInst *llinst = new MCInst(); > llinst->setOpcode(input_opcode); > llinst->addOperand(llvm::MCOperand::createReg(input_reg0)); > llinst->addOperand(llvm::MCOperand::createReg(input_reg1)); > const llvm::Twine tname("label_name"); > const llvm::MCSymbol* mcs = Ctx.getOrCreateSymbol(tname); > const llvm::MCSymbolRefExpr *msre = llvm::MCSymbolRefExpr::create(mcs, > Ctx); > llinst->addOperand(llvm::MCOperand::createExpr(msre)); > > > However, while I don't get any compiler errors, and everything runs to > completion without printing any errors, my output file "tmp.o" is always > created, but just empty with zero bytes. I must be doing something > silly here.. Does anyone have any ideas about what I'm doing wrong, or > perhaps have example code that directly uses the MCStreamer object to > write out object binary files? Some examples showing how to make this > work would _really_ make my week. > > This has been hard to debug, as I don't get any errors, just an empty > output .o file... > > I was thinking it may be because of section issues, so I did add some > initial sections, hoping that might help: > > Str->InitSections(false); > MCSection *textsect = Ctx.getELFSection(".text", ELF::SHT_PROGBITS, > ELF::SHF_EXECINSTR | ELF::SHF_ALLOC); > Str->SwitchSection(textsect); > > > This did not seem to help at all. I'm running out of ideas. Anyone > know how to use an MCStreamer object directly to make and object file? > > > Thanks so much for your time, > ~Aaron Vose > > > (Software Engineer) > (Cray Inc.) > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160522/4a5b8210/attachment.html>
Maybe Matching Threads
- Using an MCStreamer Directly to produce an object file?
- [LLVMdev] Looking for ideas on how to make llvm-objdump handle both arm and thumb disassembly from the same object file
- [LLVMdev] Moving Private Label Prefixes from MCAsmInfo to MCObjectFileInfo
- Problems using LLVM as a disassembler.
- [LLVMdev] Disassembly arbitrary machine-code byte arrays