#include "clang/Analysis/Analyses/GRConstants.h"
#include "clang/Analysis/LocalCheckers.h"
#include "llvm/Support/Streams.h"
-#include <fstream>
-
using namespace clang;
//===----------------------------------------------------------------------===//
ASTContext *Ctx;
const LangOptions &Features;
protected:
- llvm::Module *M;
+ llvm::Module *&M;
CodeGen::CodeGenModule *Builder;
public:
- CodeGenerator(Diagnostic &diags, const LangOptions &LO)
- : Diags(diags)
- , Features(LO) {}
+ CodeGenerator(Diagnostic &diags, const LangOptions &LO,
+ llvm::Module *&DestModule)
+ : Diags(diags), Features(LO), M(DestModule) {}
+
+ ~CodeGenerator() {
+ CodeGen::Terminate(Builder);
+ }
+
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- M = new llvm::Module("foo");
+
M->setTargetTriple(Ctx->Target.getTargetTriple());
M->setDataLayout(Ctx->Target.getTargetDescription());
TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
};
}
-namespace {
- class LLVMEmitter : public CodeGenerator {
- public:
- LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
- : CodeGenerator(diags,LO) {}
-
- ~LLVMEmitter() {
- CodeGen::Terminate(Builder);
-
- // Print the generated code.
- M->print(llvm::cout.stream());
- delete M;
- }
- };
-}
-
-ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags,
- const LangOptions &Features) {
- return new LLVMEmitter(Diags, Features);
-}
-
-namespace {
- class BCWriter : public CodeGenerator {
- public:
- std::ostream& Out;
-
- BCWriter(std::ostream* out, Diagnostic &diags, const LangOptions &LO)
- : CodeGenerator(diags,LO)
- , Out(*out) {}
-
- ~BCWriter() {
- CodeGen::Terminate(Builder);
- llvm::WriteBitcodeToFile(M, Out);
- delete M;
- }
- };
-}
-
-ASTConsumer *clang::CreateBCWriter(const std::string& InFile,
- const std::string& OutputFile,
- Diagnostic &Diags,
- const LangOptions &Features) {
- std::string FileName = OutputFile;
-
- std::ostream *Out;
- if (OutputFile == "-")
- Out = llvm::cout.stream();
- else if (!OutputFile.size()) {
- if (InFile == "-")
- Out = llvm::cout.stream();
- else {
- llvm::sys::Path Path(InFile);
- Path.eraseSuffix();
- Path.appendSuffix("bc");
- FileName = Path.toString();
- Out = new std::ofstream(FileName.c_str(),
- std::ios_base::binary|std::ios_base::out);
- }
- } else {
- Out = new std::ofstream(FileName.c_str(),
- std::ios_base::binary|std::ios_base::out);
- }
-
- return new BCWriter(Out, Diags, Features);
+ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags,
+ const LangOptions &Features,
+ llvm::Module *&DestModule) {
+ return new CodeGenerator(Diags, Features, DestModule);
}
//===----------------------------------------------------------------------===//
#include <iosfwd>
-namespace llvm { namespace sys { class Path; }}
-
+namespace llvm {
+ class Module;
+ namespace sys { class Path; }
+}
namespace clang {
class ASTConsumer;
ASTConsumer *CreateGRConstants();
-ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features);
-
-ASTConsumer *CreateBCWriter(const std::string& InFile,
- const std::string& OutFile,
- Diagnostic &Diags,
- const LangOptions &LOpts);
+
+ASTConsumer *CreateLLVMCodeGen(Diagnostic &Diags, const LangOptions &Features,
+ llvm::Module *&DestModule);
ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
Diagnostic &Diags);
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/Module.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Signals.h"
#include "llvm/Config/config.h"
#include "llvm/ADT/OwningPtr.h"
#include <memory>
+#include <fstream>
using namespace clang;
//===----------------------------------------------------------------------===//
/// parsed from source files as well as those deserialized from Bitcode.
static ASTConsumer* CreateASTConsumer(const std::string& InFile,
Diagnostic& Diag, FileManager& FileMgr,
- const LangOptions& LangOpts) {
+ const LangOptions& LangOpts,
+ llvm::Module *&DestModule) {
switch (ProgAction) {
default:
return NULL;
return CreateSerializationTest(Diag, FileMgr, LangOpts);
case EmitLLVM:
- return CreateLLVMEmitter(Diag, LangOpts);
-
case EmitBC:
- return CreateBCWriter(InFile, OutputFile, Diag, LangOpts);
+ DestModule = new llvm::Module(InFile);
+ return CreateLLVMCodeGen(Diag, LangOpts, DestModule);
case SerializeAST:
// FIXME: Allow user to tailor where the file is written.
ASTConsumer* Consumer = NULL;
bool ClearSourceMgr = false;
+ llvm::Module *CodeGenModule = 0;
switch (ProgAction) {
default:
Consumer = CreateASTConsumer(InFile,
PP.getDiagnostics(),
PP.getFileManager(),
- PP.getLangOptions());
+ PP.getLangOptions(),
+ CodeGenModule);
if (!Consumer) {
fprintf(stderr, "Unexpected program action!\n");
// This deletes Consumer.
ParseAST(PP, Consumer, Stats);
}
+
+ // If running the code generator, finish up now.
+ if (CodeGenModule) {
+ std::ostream *Out;
+ if (OutputFile == "-") {
+ Out = llvm::cout.stream();
+ } else if (!OutputFile.empty()) {
+ Out = new std::ofstream(OutputFile.c_str(),
+ std::ios_base::binary|std::ios_base::out);
+ } else if (InFile == "-") {
+ Out = llvm::cout.stream();
+ } else {
+ llvm::sys::Path Path(InFile);
+ Path.eraseSuffix();
+ if (ProgAction == EmitLLVM)
+ Path.appendSuffix("ll");
+ else if (ProgAction == EmitBC)
+ Path.appendSuffix("bc");
+ else
+ assert(0 && "Unknown action");
+ Out = new std::ofstream(Path.toString().c_str(),
+ std::ios_base::binary|std::ios_base::out);
+ }
+
+ if (ProgAction == EmitLLVM) {
+ CodeGenModule->print(*Out);
+ } else {
+ assert(ProgAction == EmitBC);
+ llvm::WriteBitcodeToFile(CodeGenModule, *Out);
+ }
+
+ if (Out != llvm::cout.stream())
+ delete Out;
+ delete CodeGenModule;
+ }
if (Stats) {
fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
// Observe that we use the source file name stored in the deserialized
// translation unit, rather than InFile.
+ llvm::Module *DestModule;
llvm::OwningPtr<ASTConsumer>
- Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts()));
+ Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(),
+ DestModule));
if (!Consumer) {
fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
Consumer->Initialize(*TU->getContext());
+ // FIXME: We need to inform Consumer about completed TagDecls as well.
for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
Consumer->HandleTopLevelDecl(*I);
}
-// RUN: clang %s -emit-llvm > %t1
+// RUN: clang %s -emit-llvm -o - > %t1
// RUN: grep "shl i32 %tmp, 19" %t1 &&
// RUN: grep "ashr i32 %tmp1, 19" %t1 &&
// RUN: grep "shl i16 %tmp4, 1" %t1 &&
-// RUN: clang %s -emit-llvm | grep internal | count 1
+// RUN: clang < %s -emit-llvm | grep internal | count 1
// The two decls for 'a' should merge into one llvm GlobalVariable.
-// RUN: clang %s -emit-llvm > %t1
+// RUN: clang < %s -emit-llvm > %t1
// Run grep "STest1 = type { i32, \[4 x i16\], double }" %t1 &&
// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1 &&
// RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1 &&
-// RUN: clang %s -emit-llvm 2>&1 | grep 0x3BFD83C940000000 | count 2
-// RUN: clang %s -emit-llvm 2>&1 | grep 2.000000e+32 | count 2
+// RUN: clang %s -emit-llvm -o - | grep 0x3BFD83C940000000 | count 2
+// RUN: clang %s -emit-llvm -o - | grep 2.000000e+32 | count 2
float F = 1e-19f;
double D = 2e32;