From 24e52992c030a7dd30455bea773b3b402c37df37 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 7 Jun 2010 23:28:45 +0000 Subject: [PATCH] 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 --- clang/include/clang/Driver/Types.def | 9 +++++++-- clang/include/clang/Driver/Types.h | 4 ++++ clang/lib/Driver/Driver.cpp | 6 +++--- clang/lib/Driver/Tools.cpp | 30 ++++++++++++++++++---------- clang/lib/Driver/Types.cpp | 16 +++++++++++++++ clang/test/Driver/lto.c | 9 ++++----- 6 files changed, 54 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 111262e7128c..ec698ea3107b 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -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") diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h index d93323016fe3..9187529833ac 100644 --- a/clang/include/clang/Driver/Types.h +++ b/clang/include/clang/Driver/Types.h @@ -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); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index cae2243b2ef0..90333bd21d1c 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -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(JA) || JA.getType() == types::TY_AST || - JA.getType() == types::TY_RewrittenObjC) + if (isa(JA) || + types::isOnlyAcceptedByClang(JA.getType())) return true; // Finally, don't use clang if this isn't one of the user specified archs to diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 4ab32ed3eff7..05569074a45d 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -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(); diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 8857fb16a304..752a881ba593 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -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) diff --git a/clang/test/Driver/lto.c b/clang/test/Driver/lto.c index 4543ffcd023e..22b47882691d 100644 --- a/clang/test/Driver/lto.c +++ b/clang/test/Driver/lto.c @@ -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