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'
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'
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits