[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