[LLVMdev] How to output a .S *and* a .OBJ file?
John Slagel
john.slagel at gmail.com
Mon Jan 7 11:52:43 PST 2013
Hi,
I'm embarrassed that I can't figure this out... I have a compiler that
outputs my module in either .s assembly format or .obj binary format,
either one works just fine. But if I try to output both of them by adding
passes, LLVM throws an Assert:
void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
MCObjectStreamer::EmitLabel(Symbol);
}
I attached my code which attempts to make it output both... if I comment
out the lines for one or the other it works just fine.
That code is just a copy of the llvm c compiler's code, changed slightly to
suit my needs.
A general "do this and then this" answer will probably get me on the right
path...
Thanks!!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130107/06c571c4/attachment.html>
-------------- next part --------------
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
Triple *TheTriple = NULL;
if ( DoMingw ) {
TheTriple = new Triple("i686-pc-mingw32");
} else {
TheTriple = new Triple("i686-pc-win32");
}
Assert(!TheTriple->getTriple().empty()) //TheTriple.setTriple(sys::getHostTriple());
9 std::string Err;
const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple->getTriple(), Err);
if (TheTarget == 0) {
printf( "Error selecting target\n" );
return false;
}
/*
CodeGenOpt::None
CodeGenOpt::Less
CodeGenOpt::Default
CodeGenOpt::Aggressive
*/
CodeGenOpt::Level OLvl = CodeGenOpt::Aggressive;
TargetOptions Options;
std::auto_ptr<TargetMachine>
target(TheTarget->createTargetMachine(TheTriple->getTriple(),"","",Options,Reloc::Default,CodeModel::Default,OLvl));
assert(target.get() && "Could not allocate target machine!");
TargetMachine &Target = *target.get();
/*
TargetMachine::CGFT_AssemblyFile
TargetMachine::CGFT_ObjectFile
*/
TargetMachine::CodeGenFileType FileType_S = TargetMachine::CGFT_AssemblyFile;
TargetMachine::CodeGenFileType FileType_OBJ = TargetMachine::CGFT_ObjectFile;
//if ( DoCompileObj ) {
//} else if ( DoCompileS ) {
OwningPtr<tool_output_file> Out_S(GetOutputStream(FileType_S, TheTarget->getName(), TheTriple->getOS(), "BasicParser.exe"));
if ( !Out_S) {
printf( "Error creating output file\n" );
return false;
}
OwningPtr<tool_output_file> Out_OBJ(GetOutputStream(FileType_OBJ, TheTarget->getName(), TheTriple->getOS(), "BasicParser.exe"));
if ( !Out_OBJ) {
printf( "Error creating output file\n" );
return false;
}
// Build up all of the passes that we want to do to the module.
PassManager PM;
PM.add(new TargetData(module));
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
{
formatted_raw_ostream FOS_S(Out_S->os());
formatted_raw_ostream FOS_OBJ(Out_OBJ->os());
// Ask the target to add backend passes as necessary.
bool NoVerify = true;
if (Target.addPassesToEmitFile(PM, FOS_S, FileType_S, NoVerify)) {
printf( "target does not support generation of this file type!\n");
return false;
}
if (Target.addPassesToEmitFile(PM, FOS_OBJ, FileType_OBJ, NoVerify)) {
printf( "target does not support generation of this file type!\n");
return false;
}
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
PM.run(*module);
}
// Declare success.
Out_S->keep();
Out_OBJ->keep();
More information about the llvm-dev
mailing list