[PATCH] clang-cl: add support for /FA (output assembly file)

Hans Wennborg hans at chromium.org
Tue Oct 15 16:41:06 PDT 2013


Hi rnk,

This adds support for the /FA option (output assembly file), and /Fa which sets the filename.

The patch achieves this in a way similar to how -save-temps works: it changes the compilation pipeline to not use the integrated assembler, and keeps the intermediate assembly output.

The catch here is that clang is often not able to assemble the output it produces on Windows. I've uploaded http://llvm-reviews.chandlerc.com/D1945 to address that.

http://llvm-reviews.chandlerc.com/D1946

Files:
  docs/UsersManual.rst
  include/clang/Driver/CLCompatOptions.td
  lib/Driver/Driver.cpp
  lib/Driver/Types.cpp
  test/Driver/cl-outputs.c

Index: docs/UsersManual.rst
===================================================================
--- docs/UsersManual.rst
+++ docs/UsersManual.rst
@@ -1456,6 +1456,8 @@
     /c                     Compile only
     /D <macro[=value]>     Define macro
     /fallback              Fall back to cl.exe if clang-cl fails to compile
+    /FA                    Output assembly code file during compilation
+    /Fa<file or directory> Set filename to use for /FA
     /Fe<file or directory> Set output executable file or directory (ends in / or \)
     /FI<value>             Include file before parsing
     /Fo<file or directory> Set output object file, or directory (ends in / or \)
Index: include/clang/Driver/CLCompatOptions.td
===================================================================
--- include/clang/Driver/CLCompatOptions.td
+++ include/clang/Driver/CLCompatOptions.td
@@ -112,6 +112,11 @@
 
 def _SLASH_M_Group : OptionGroup<"</M group>">, Group<cl_compile_Group>;
 
+def _SLASH_FA : CLFlag<"FA">,
+  HelpText<"Output assembly code file during compilation">;
+def _SLASH_Fa : CLJoined<"Fa">,
+  HelpText<"Set filename to use for /FA">,
+  MetaVarName<"<file or directory>">;
 def _SLASH_fallback : CLCompileFlag<"fallback">,
   HelpText<"Fall back to cl.exe if clang-cl fails to compile">;
 def _SLASH_FI : CLJoined<"FI">,
@@ -165,8 +170,7 @@
 
 def _SLASH_bigobj : CLFlag<"bigobj">;
 def _SLASH_EH : CLJoined<"EH">;
-def _SLASH_FA : CLJoined<"FA">;
-def _SLASH_Fa : CLJoined<"Fa">;
+def _SLASH_FA_joined : CLJoined<"FA">;
 def _SLASH_Fd : CLJoined<"Fd">;
 def _SLASH_fp : CLJoined<"fp">;
 def _SLASH_Gd : CLFlag<"Gd">;
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -1446,6 +1446,7 @@
 
   if (TC->useIntegratedAs() &&
       !C.getArgs().hasArg(options::OPT_save_temps) &&
+      !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
       isa<AssembleJobAction>(JA) &&
       Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
     const Tool *Compiler =
@@ -1568,8 +1569,10 @@
   }
 }
 
-/// \brief Create output filename based on ArgValue, which could either be a 
-/// full filename, filename without extension, or a directory.
+/// \brief Create output filename based on ArgValue, which could either be a
+/// full filename, filename without extension, or a directory. If ArgValue
+/// does not provide a filename, then use BaseName, and use the extension
+/// suitable for FileType.
 static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
                                         StringRef BaseName, types::ID FileType) {
   SmallString<128> Filename = ArgValue;
@@ -1617,6 +1620,16 @@
       (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
     return "-";
 
+  // Is this the assembly listing for /FA?
+  if (JA.getType() == types::TY_PP_Asm &&
+      C.getArgs().hasArg(options::OPT__SLASH_FA)) {
+    // Use /Fa and the input filename to determine the asm file name.
+    StringRef BaseName = llvm::sys::path::filename(BaseInput);
+    StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
+    return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName,
+                                                JA.getType()), &JA);
+  }
+
   // Output to a temporary file?
   if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
         !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
Index: lib/Driver/Types.cpp
===================================================================
--- lib/Driver/Types.cpp
+++ lib/Driver/Types.cpp
@@ -49,6 +49,8 @@
     return "obj";
   if (Id == TY_Image && CLMode)
     return "exe";
+  if (Id == TY_PP_Asm && CLMode)
+    return "asm";
   return getInfo(Id).TempSuffix;
 }
 
Index: test/Driver/cl-outputs.c
===================================================================
--- test/Driver/cl-outputs.c
+++ test/Driver/cl-outputs.c
@@ -88,3 +88,19 @@
 
 // RUN: %clang_cl /Fefoo /Febar -### -- %s 2>&1 | FileCheck -check-prefix=FeOVERRIDE %s
 // FeOVERRIDE: "-out:bar.exe"
+
+
+// RUN: %clang_cl /FA -### -- %s 2>&1 | FileCheck -check-prefix=FA %s
+// FA: "-o" "cl-outputs.asm"
+// RUN: %clang_cl /FA /Fafoo -### -- %s 2>&1 | FileCheck -check-prefix=FaNAME %s
+// FaNAME:  "-o" "foo.asm"
+// RUN: %clang_cl /FA /Faa.ext /Fab.ext -### -- %s 2>&1 | FileCheck -check-prefix=FaNAMEEXT %s
+// FaNAMEEXT:  "-o" "b.ext"
+// RUN: %clang_cl /FA /Fafoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FaDIR %s
+// FaDIR:  "-o" "foo.dir{{[/\\]+}}cl-outputs.asm"
+// RUN: %clang_cl /FA /Fafoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FaDIRNAME %s
+// FaDIRNAME:  "-o" "foo.dir{{[/\\]+}}a.asm"
+// RUN: %clang_cl /FA /Fafoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FaDIRNAMEEXT %s
+// FaDIRNAMEEXT:  "-o" "foo.dir{{[/\\]+}}a.ext"
+// RUN: %clang_cl /Fafoo -### -- %s 2>&1 | FileCheck -check-prefix=FaNOFA %s
+// FaNOFA: argument unused during compilation: '/Fafoo'
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1946.1.patch
Type: text/x-patch
Size: 5041 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131015/dac2867b/attachment.bin>


More information about the cfe-commits mailing list