Driver: Support invoking Clang on .ll or .bc inputs.
- We actually pretend that we have two separate types for LLVM assembly/bitcode because we need to use the standard suffixes with LTO ('clang -O4 -c t.c' should generate 't.o'). It is now possible to do something like: $ clang -emit-llvm -S t.c -o t.ll ... assorted other compile flags ... $ clang -c t.ll -o t.o ... assorted other compile flags ... and expect that the output will be almost* identical to: $ clang -c t.c -o t.o ... assorted other compile flags ... because all the target settings (default CPU, target features, etc.) will all be initialized properly by the driver/frontend. *: This isn't perfect yet, because in practice we will end up running the optimization passes twice. It's possible to get something equivalent out with a well placed -mllvm -disable-llvm-optzns, but I'm still thinking about the cleanest way to solve this problem more generally. llvm-svn: 105584
This commit is contained in:
parent
6f8362c6bf
commit
24e52992c0
|
@ -67,10 +67,15 @@ TYPE("f95", PP_Fortran, INVALID, 0, "u")
|
|||
TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u")
|
||||
TYPE("java", Java, INVALID, 0, "u")
|
||||
|
||||
// LLVM IR/LTO types. We define separate types for IR and LTO because LTO
|
||||
// outputs should use the standard suffixes.
|
||||
TYPE("ir", LLVM_IR, INVALID, "ll", "")
|
||||
TYPE("ir", LLVM_BC, INVALID, "bc", "")
|
||||
TYPE("lto-ir", LTO_IR, INVALID, "s", "")
|
||||
TYPE("lto-bc", LTO_BC, INVALID, "o", "")
|
||||
|
||||
// Misc.
|
||||
TYPE("ast", AST, INVALID, "ast", "u")
|
||||
TYPE("llvm-asm", LLVMAsm, INVALID, "s", "")
|
||||
TYPE("llvm-bc", LLVMBC, INVALID, "o", "")
|
||||
TYPE("plist", Plist, INVALID, "plist", "")
|
||||
TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "")
|
||||
TYPE("precompiled-header", PCH, INVALID, "gch", "A")
|
||||
|
|
|
@ -59,6 +59,10 @@ namespace types {
|
|||
/// isAcceptedByClang - Can clang handle this input type.
|
||||
bool isAcceptedByClang(ID Id);
|
||||
|
||||
/// isOnlyAcceptedByClang - Is clang the only compiler that can handle this
|
||||
/// input type.
|
||||
bool isOnlyAcceptedByClang(ID Id);
|
||||
|
||||
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
|
||||
bool isCXX(ID Id);
|
||||
|
||||
|
|
|
@ -797,7 +797,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
|
|||
} else if (Args.hasArg(options::OPT_emit_llvm) ||
|
||||
Args.hasArg(options::OPT_flto) || HasO4) {
|
||||
types::ID Output =
|
||||
Args.hasArg(options::OPT_S) ? types::TY_LLVMAsm : types::TY_LLVMBC;
|
||||
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
|
||||
return new CompileJobAction(Input, Output);
|
||||
} else {
|
||||
return new CompileJobAction(Input, types::TY_PP_Asm);
|
||||
|
@ -1263,8 +1263,8 @@ bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
|
|||
|
||||
// Always use clang for precompiling, AST generation, and rewriting,
|
||||
// regardless of archs.
|
||||
if (isa<PrecompileJobAction>(JA) || JA.getType() == types::TY_AST ||
|
||||
JA.getType() == types::TY_RewrittenObjC)
|
||||
if (isa<PrecompileJobAction>(JA) ||
|
||||
types::isOnlyAcceptedByClang(JA.getType()))
|
||||
return true;
|
||||
|
||||
// Finally, don't use clang if this isn't one of the user specified archs to
|
||||
|
|
|
@ -792,9 +792,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
if (JA.getType() == types::TY_Nothing) {
|
||||
CmdArgs.push_back("-fsyntax-only");
|
||||
} else if (JA.getType() == types::TY_LLVMAsm) {
|
||||
} else if (JA.getType() == types::TY_LLVM_IR ||
|
||||
JA.getType() == types::TY_LTO_IR) {
|
||||
CmdArgs.push_back("-emit-llvm");
|
||||
} else if (JA.getType() == types::TY_LLVMBC) {
|
||||
} else if (JA.getType() == types::TY_LLVM_BC ||
|
||||
JA.getType() == types::TY_LTO_BC) {
|
||||
CmdArgs.push_back("-emit-llvm-bc");
|
||||
} else if (JA.getType() == types::TY_PP_Asm) {
|
||||
CmdArgs.push_back("-S");
|
||||
|
@ -1634,7 +1636,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM or AST inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
|
||||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString();
|
||||
else if (II.getType() == types::TY_AST)
|
||||
|
@ -1676,7 +1679,8 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
|
|||
const Driver &D = getToolChain().getDriver();
|
||||
|
||||
// If -flto, etc. are present then make sure not to force assembly output.
|
||||
if (JA.getType() == types::TY_LLVMBC)
|
||||
if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
|
||||
JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
|
||||
CmdArgs.push_back("-c");
|
||||
else {
|
||||
if (JA.getType() != types::TY_PP_Asm)
|
||||
|
@ -2083,9 +2087,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
|
||||
<< A->getAsString(Args) << "-E";
|
||||
|
||||
if (Output.getType() == types::TY_LLVMAsm)
|
||||
if (JA.getType() == types::TY_LLVM_IR ||
|
||||
JA.getType() == types::TY_LTO_IR)
|
||||
CmdArgs.push_back("-emit-llvm");
|
||||
else if (Output.getType() == types::TY_LLVMBC)
|
||||
else if (JA.getType() == types::TY_LLVM_BC ||
|
||||
JA.getType() == types::TY_LTO_BC)
|
||||
CmdArgs.push_back("-emit-llvm-bc");
|
||||
else if (Output.getType() == types::TY_AST)
|
||||
D.Diag(clang::diag::err_drv_no_ast_support)
|
||||
|
@ -2679,7 +2685,8 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
|
||||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString();
|
||||
|
||||
|
@ -2809,7 +2816,8 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
|
||||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString();
|
||||
|
||||
|
@ -2947,7 +2955,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
|
||||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString();
|
||||
|
||||
|
@ -3100,7 +3109,8 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
|
||||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString();
|
||||
|
||||
|
|
|
@ -86,6 +86,20 @@ bool types::isAcceptedByClang(ID Id) {
|
|||
case TY_CXXHeader: case TY_PP_CXXHeader:
|
||||
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
|
||||
case TY_AST:
|
||||
case TY_LLVM_IR: case TY_LLVM_BC:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool types::isOnlyAcceptedByClang(ID Id) {
|
||||
switch (Id) {
|
||||
default:
|
||||
return false;
|
||||
|
||||
case TY_AST:
|
||||
case TY_LLVM_IR:
|
||||
case TY_LLVM_BC:
|
||||
case TY_RewrittenObjC:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -132,11 +146,13 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
|
|||
.Case("ii", TY_PP_CXX)
|
||||
.Case("mi", TY_PP_ObjC)
|
||||
.Case("mm", TY_ObjCXX)
|
||||
.Case("bc", TY_LLVM_BC)
|
||||
.Case("cc", TY_CXX)
|
||||
.Case("CC", TY_CXX)
|
||||
.Case("cl", TY_CL)
|
||||
.Case("cp", TY_CXX)
|
||||
.Case("hh", TY_CXXHeader)
|
||||
.Case("ll", TY_LLVM_IR)
|
||||
.Case("hpp", TY_CXXHeader)
|
||||
.Case("ads", TY_Ada)
|
||||
.Case("adb", TY_Ada)
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
// -emit-llvm, -flto, and -O4 all cause a switch to llvm-bc object
|
||||
// files.
|
||||
// -emit-llvm, -flto, and -O4 all cause a switch to llvm-bc object files.
|
||||
// RUN: %clang -ccc-print-phases -c %s -flto 2> %t.log
|
||||
// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
|
||||
// RUN: grep '2: compiler, {1}, lto-bc' %t.log
|
||||
// RUN: %clang -ccc-print-phases -c %s -O4 2> %t.log
|
||||
// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
|
||||
// RUN: grep '2: compiler, {1}, lto-bc' %t.log
|
||||
|
||||
// and -emit-llvm doesn't alter pipeline (unfortunately?).
|
||||
// RUN: %clang -ccc-print-phases %s -emit-llvm 2> %t.log
|
||||
// RUN: grep '0: input, ".*lto.c", c' %t.log
|
||||
// RUN: grep '1: preprocessor, {0}, cpp-output' %t.log
|
||||
// RUN: grep '2: compiler, {1}, llvm-bc' %t.log
|
||||
// RUN: grep '2: compiler, {1}, lto-bc' %t.log
|
||||
// RUN: grep '3: linker, {2}, image' %t.log
|
||||
|
||||
// llvm-bc and llvm-ll outputs need to match regular suffixes
|
||||
|
|
Loading…
Reference in New Issue