add .o file writing for inline asm in llc. Here's a silly
authorChris Lattner <sabre@nondot.org>
Mon, 5 Apr 2010 23:11:24 +0000 (23:11 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 5 Apr 2010 23:11:24 +0000 (23:11 +0000)
demo:

$ clang asm.c -S -o - -emit-llvm | llc -filetype=obj -o t.o
<inline asm>:1:2: error: unrecognized instruction
abc incl    %eax
^
LLVM ERROR: Error parsing inline asm

Only problem seems to be that the parser finalizes OutStreamer
at the end of the first inline asm, which isn't what we want.
For example:

$ cat asm.c
int foo(int X) {
 __asm__ ("incl    %0" : "+r" (X));
 return X;
}
$ clang asm.c -S -o - -emit-llvm | llc
...
subq $8, %rsp
movl %edi, (%rsp)
movl %edi, %eax
## InlineAsm Start
incl    %eax
## InlineAsm End
movl %eax, (%rsp)
movl %eax, 4(%rsp)
addq $8, %rsp
ret
$ clang asm.c -S -o - -emit-llvm | llc -filetype=obj -o t.o
$ otool -tv t.o
t.o:
(__TEXT,__text) section
_foo:
0000000000000000 subq $0x08,%rsp
0000000000000004 movl %edi,(%rsp)
0000000000000007 movl %edi,%eax
0000000000000009 incl %eax
$

don't stop at inc!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100491 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
tools/llc/llc.cpp

index cd8329d65ebca20f89df3ea6c2d8f48dee37a5e0..090bd9b2bff5b9749cf1b08aa70b9d9281125948 100644 (file)
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCParser/AsmParser.h"
+#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
@@ -28,6 +35,11 @@ using namespace llvm;
 void AsmPrinter::EmitInlineAsm(StringRef Str) const {
   assert(!Str.empty() && "Can't emit empty inline asm block");
   
 void AsmPrinter::EmitInlineAsm(StringRef Str) const {
   assert(!Str.empty() && "Can't emit empty inline asm block");
   
+  // Remember if the buffer is nul terminated or not so we can avoid a copy.
+  bool isNullTerminated = Str.back() == 0;
+  if (isNullTerminated)
+    Str = Str.substr(0, Str.size()-1);
+  
   // If the output streamer is actually a .s file, just emit the blob textually.
   // This is useful in case the asm parser doesn't handle something but the
   // system assembler does.
   // If the output streamer is actually a .s file, just emit the blob textually.
   // This is useful in case the asm parser doesn't handle something but the
   // system assembler does.
@@ -36,7 +48,27 @@ void AsmPrinter::EmitInlineAsm(StringRef Str) const {
     return;
   }
   
     return;
   }
   
-  errs() << "Inline asm not supported by this streamer!\n";
+  SourceMgr SrcMgr;
+  MemoryBuffer *Buffer;
+  if (isNullTerminated)
+    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
+  else
+    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
+
+  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
+  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
+  
+  AsmParser Parser(SrcMgr, OutContext, OutStreamer, *MAI);
+  OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(Parser));
+  if (!TAP)
+    llvm_report_error("Inline asm not supported by this streamer because"
+                      " we don't have an asm parser for this target\n");
+  Parser.setTargetParser(*TAP.get());
+
+  // Don't implicitly switch to the text section before the asm.
+  int Res = Parser.Run(/*NoInitialTextSection*/ true);
+  if (Res)
+    llvm_report_error("Error parsing inline asm\n");
 }
 
 
 }
 
 
@@ -249,8 +281,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
     }
     }
   }
     }
     }
   }
-  OS << "\n";
-  
+  OS << '\n' << (char)0;  // null terminate string.
   EmitInlineAsm(OS.str());
   
   // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
   EmitInlineAsm(OS.str());
   
   // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
index aa977a7032c44dd73f4a41d0b15bd7e066433008..dccfb26e74556aed0aa660377d8c5b14c4399ea7 100644 (file)
@@ -214,6 +214,7 @@ int main(int argc, char **argv) {
   // Initialize targets first, so that --version shows registered targets.
   InitializeAllTargets();
   InitializeAllAsmPrinters();
   // Initialize targets first, so that --version shows registered targets.
   InitializeAllTargets();
   InitializeAllAsmPrinters();
+  InitializeAllAsmParsers();
 
   cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
   
 
   cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");