[llvm-commits] [vector_llvm] CVS: llvm/lib/Target/CBackend/AltiVecCTargetMachine.h AltiVecWriter.cpp AltiVecWriter.h SSECTargetMachine.h SSEWriter.cpp SSEWriter.h Writer.h
Robert Bocchino
bocchino at cs.uiuc.edu
Tue Oct 18 12:37:04 PDT 2005
Changes in directory llvm/lib/Target/CBackend:
AltiVecCTargetMachine.h added (r1.1.2.1)
AltiVecWriter.cpp added (r1.1.2.1)
AltiVecWriter.h added (r1.1.2.1)
SSECTargetMachine.h added (r1.1.2.1)
SSEWriter.cpp added (r1.1.2.1)
SSEWriter.h added (r1.1.2.1)
Writer.h added (r1.1.2.1)
---
Log message:
Initial commit of Vector LLVM.
---
Diffs of the changes: (+799 -0)
AltiVecCTargetMachine.h | 36 ++++++
AltiVecWriter.cpp | 206 ++++++++++++++++++++++++++++++++++++
AltiVecWriter.h | 66 +++++++++++
SSECTargetMachine.h | 36 ++++++
SSEWriter.cpp | 129 +++++++++++++++++++++++
SSEWriter.h | 57 ++++++++++
Writer.h | 269 ++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 799 insertions(+)
Index: llvm/lib/Target/CBackend/AltiVecCTargetMachine.h
diff -c /dev/null llvm/lib/Target/CBackend/AltiVecCTargetMachine.h:1.1.2.1
*** /dev/null Tue Oct 18 14:37:02 2005
--- llvm/lib/Target/CBackend/AltiVecCTargetMachine.h Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,36 ----
+ //===-- CTargetMachine.h - TargetMachine for the C backend ------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file declares the TargetMachine that is used by the AltiVec C backend.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef ALTIVECCTARGETMACHINE_H
+ #define ALTIVECCTARGETMACHINE_H
+
+ #include "CTargetMachine.h"
+
+ namespace llvm {
+
+ class IntrinsicLowering;
+
+ struct AltiVecCTargetMachine : public CTargetMachine {
+ AltiVecCTargetMachine(const Module &M, IntrinsicLowering *IL, const std::string& name) :
+ CTargetMachine(M, IL, "AltiVecCBackend") {}
+
+ // This is the only thing that actually does anything here.
+ bool addPassesToEmitFile(PassManager &PM, std::ostream &Out,
+ CodeGenFileType FileType);
+
+ };
+
+ } // End llvm namespace
+
+
+ #endif
Index: llvm/lib/Target/CBackend/AltiVecWriter.cpp
diff -c /dev/null llvm/lib/Target/CBackend/AltiVecWriter.cpp:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/AltiVecWriter.cpp Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,206 ----
+ //===-- Writer.cpp - Library for converting LLVM code to C ----------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This library converts LLVM code to C code with AltiVec extensions.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "AltiVecCTargetMachine.h"
+ #include "AltiVecWriter.h"
+
+ using namespace llvm;
+
+ namespace {
+ // Register the target.
+ RegisterTarget<AltiVecCTargetMachine> X("altivec-c", " AltiVec C backend");
+ }
+
+ static void badValue(Value *V) {
+ std::cerr << "AltiVec C Backend can't handle this value!\n";
+ std::cerr << *V << "\n";
+ abort();
+ }
+
+ void AltiVecCWriter::printConstant(Constant *CPV) {
+ if (!isa<FixedVectorType>(CPV->getType())) {
+ CWriter::printConstant(CPV);
+ return;
+ }
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
+ switch (CE->getOpcode()) {
+ case Instruction::Cast:
+ Out << "((";
+ printType(Out, CPV->getType());
+ Out << ") (";
+ printConstant(CE->getOperand(0));
+ Out << "))";
+ return;
+ default:
+ badValue(CPV);
+ }
+ }
+ // FIXME: Add support for literal vector constants here
+ //
+ Out << "((";
+ printType(Out, CPV->getType());
+ Out << ") (";
+ for (unsigned i = 0; i < CPV->getNumOperands()-1; ++i) {
+ printConstant(CPV->getOperand(i));
+ Out << ", ";
+ }
+ printConstant(CPV->getOperand(CPV->getNumOperands()-1));
+ Out << "))";
+ return;
+
+ }
+
+ void AltiVecCWriter::visitCastInst (CastInst &I) {
+ if (!isa<FixedVectorType>(I.getType()) ||
+ isa<FixedVectorType>(I.getOperand(0)->getType()))
+ return CWriter::visitCastInst(I);
+ if (!isa<Constant>(I.getOperand(0))) {
+ std::cerr << I;
+ std::cerr << "AltiVec C Backend can handle only cast of constant to vector!\n";
+ exit(1);
+ }
+ Out << '(';
+ printType(Out, I.getType());
+ Out << ") (";
+ writeOperand(I.getOperand(0));
+ Out << ')';
+ }
+
+ void AltiVecCWriter::visitVImmInst (VImmInst &VL) {
+ if (!isa<Constant>(VL.getOperand(0))) {
+ std::cerr << VL;
+ std::cerr << "AltiVec C Backend can handle only vimm of constant!\n";
+ exit(1);
+ }
+ Out << '(';
+ printType(Out, VL.getType());
+ Out << ") (";
+ writeOperand(VL.getOperand(0));
+ Out << ')';
+ }
+
+ void AltiVecCWriter::visitBinaryOperator(Instruction &I) {
+ if (!isa<FixedVectorType>(I.getType()))
+ return CWriter::visitBinaryOperator(I);
+ switch(I.getOpcode()) {
+ case Instruction::Add:
+ // Check for mladd pattern
+ //
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I.getOperand(0))) {
+ if (BO->getOpcode() == Instruction::Mul) {
+ Out << "vec_mladd(";
+ writeOperand(BO->getOperand(0));
+ Out << ",";
+ writeOperand(BO->getOperand(1));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ }
+ }
+ Out << "vec_add(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ case Instruction::Mul:
+ Out << "vec_mladd(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ",(vector short)(0))";
+ break;
+ case Instruction::And:
+ Out << "vec_and(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ default:
+ std::cerr << "AltiVec C Backend can't handle this instruction:\n" << I;
+ exit(1);
+ }
+ }
+
+ std::ostream &AltiVecCWriter::printFixedVectorType(std::ostream &Out,
+ const FixedVectorType *Ty,
+ const std::string &VariableName) {
+ unsigned numElements = Ty->getNumElements();
+ switch(Ty->getElementType()->getTypeID()) {
+ case(Type::SByteTyID):
+ if (numElements != 16) {
+ std::cerr << "Vector of sbyte must have 16 elements!\n";
+ exit(1);
+ }
+ Out << "vector signed char " << VariableName;
+ break;
+ case (Type::UByteTyID):
+ if (numElements != 16) {
+ std::cerr << "Vector of ubyte must have 16 elements!\n";
+ exit(1);
+ }
+ Out << "vector unsigned char " << VariableName;
+ break;
+ case(Type::ShortTyID):
+ if (numElements != 8) {
+ std::cerr << "Vector of short must have 8 elements!\n";
+ exit(1);
+ }
+ Out << "vector signed short " << VariableName;
+ break;
+ case(Type::UShortTyID):
+ if (numElements != 8) {
+ std::cerr << "Vector of ushort must have 8 elements!\n";
+ exit(1);
+ }
+ Out << "vector unsigned short " << VariableName;
+ break;
+ case(Type::BoolTyID):
+ switch(numElements) {
+ case 8:
+ Out << "vector bool short ";
+ break;
+ default:
+ std::cerr << "AltiVec C Backend cannot handle boolean vector with "
+ << numElements << " elements!\n";
+ break;
+ }
+ Out << VariableName;
+ break;
+ default:
+ std::cerr << "AltiVec C Backend cannot handle " << Ty->getDescription() << "!\n";
+ exit(1);
+ break;
+ }
+ return Out;
+ }
+
+
+ //===----------------------------------------------------------------------===//
+ // External Interface declaration
+ //===----------------------------------------------------------------------===//
+
+ bool AltiVecCTargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &o,
+ CodeGenFileType FileType) {
+ if (FileType != TargetMachine::AssemblyFile) return true;
+ // Add lowervectors pass here to lower variable-length vectors, which we can't handle
+ PM.add(createLowerGCPass());
+ PM.add(createLowerAllocationsPass(true));
+ PM.add(createLowerInvokePass());
+ PM.add(new CBackendNameAllUsedStructs());
+ PM.add(new AltiVecCWriter(o, getIntrinsicLowering()));
+ return false;
+ }
+
Index: llvm/lib/Target/CBackend/AltiVecWriter.h
diff -c /dev/null llvm/lib/Target/CBackend/AltiVecWriter.h:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/AltiVecWriter.h Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,66 ----
+ //===---------------- Writer.h - C backend interface ------------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file exposes the interface that is common to all C backends.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef ALTIVECCWRITER_H
+ #define ALTIVECCWRITER_H
+
+ #include "Writer.h"
+
+ using namespace llvm;
+
+ namespace llvm {
+ /// AltiVecCWriter - This class is the main chunk of code that
+ /// converts an LLVM module to an AltiVec/C translation unit.
+ class AltiVecCWriter : public CWriter {
+ void printConstant(Constant *CPV);
+ void visitCastInst(CastInst &I);
+ void visitVImmInst(VImmInst &I);
+ void visitBinaryOperator(Instruction &I);
+
+ public:
+ AltiVecCWriter(std::ostream &o, IntrinsicLowering &il) :
+ CWriter(o,il) {}
+
+ void writeValueName(Value *V) {
+ std::string name = Mang->getValueName(V);
+ if (name.substr(0,8) == "altivec_") {
+ unsigned pos = name.find("_", 8);
+ if (pos == std::string::npos) {
+ std::cerr << "Bad syntax for AltiVec intrinsic " << name << "\n";
+ exit(1);
+ }
+ // C name is vec_xxx
+ Out << name.substr(4, pos-4);
+ } else {
+ CWriter::writeValueName(V);
+ }
+ }
+
+ bool printDeclarationFor(Function *F) {
+ if (F->getName().substr(0, 7) == "altivec")
+ return false;
+ return CWriter::printDeclarationFor(F);
+ }
+ virtual const char *getPassName() const { return "AltiVec C backend"; }
+
+ std::ostream &printFixedVectorType(std::ostream &Out,
+ const FixedVectorType *Ty,
+ const std::string &VariableName = "");
+
+ };
+ }
+
+
+
+ #endif
+
Index: llvm/lib/Target/CBackend/SSECTargetMachine.h
diff -c /dev/null llvm/lib/Target/CBackend/SSECTargetMachine.h:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/SSECTargetMachine.h Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,36 ----
+ //===-- CTargetMachine.h - TargetMachine for the C backend ------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file declares the TargetMachine that is used by the SSE C backend.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef SSECTARGETMACHINE_H
+ #define SSECTARGETMACHINE_H
+
+ #include "CTargetMachine.h"
+
+ namespace llvm {
+
+ class IntrinsicLowering;
+
+ struct SSECTargetMachine : public CTargetMachine {
+ SSECTargetMachine(const Module &M, IntrinsicLowering *IL, const std::string& name) :
+ CTargetMachine(M, IL, "SSECBackend") {}
+
+ // This is the only thing that actually does anything here.
+ bool addPassesToEmitFile(PassManager &PM, std::ostream &Out,
+ CodeGenFileType FileType);
+
+ };
+
+ } // End llvm namespace
+
+
+ #endif
Index: llvm/lib/Target/CBackend/SSEWriter.cpp
diff -c /dev/null llvm/lib/Target/CBackend/SSEWriter.cpp:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/SSEWriter.cpp Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,129 ----
+ //===-- Writer.cpp - Library for converting LLVM code to C ----------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This library converts LLVM code to C code with SSE extensions.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "SSECTargetMachine.h"
+ #include "SSEWriter.h"
+
+ using namespace llvm;
+
+ namespace {
+ // Register the target.
+ RegisterTarget<SSECTargetMachine> X("sse-c", " SSE C backend");
+ }
+
+ static void badValue(Value *V) {
+ std::cerr << "SSE C Backend can't handle this value!\n";
+ std::cerr << *V << "\n";
+ abort();
+ }
+
+ void SSECWriter::printConstant(Constant *CPV) {
+ if (!isa<FixedVectorType>(CPV->getType())) {
+ CWriter::printConstant(CPV);
+ return;
+ }
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
+ switch (CE->getOpcode()) {
+ case Instruction::Cast:
+ Out << "((";
+ printType(Out, CPV->getType());
+ Out << ") (";
+ printConstant(CE->getOperand(0));
+ Out << "))";
+ return;
+ default:
+ badValue(CPV);
+ }
+ }
+ // FIXME: Add support for literal vector constants here
+ //
+ Out << "((";
+ printType(Out, CPV->getType());
+ Out << ") (";
+ for (unsigned i = 0; i < CPV->getNumOperands()-1; ++i) {
+ printConstant(CPV->getOperand(i));
+ Out << ", ";
+ }
+ printConstant(CPV->getOperand(CPV->getNumOperands()-1));
+ Out << "))";
+ return;
+
+ }
+
+ void SSECWriter::visitCastInst (CastInst &I) {
+ if (!isa<FixedVectorType>(I.getType()) ||
+ isa<FixedVectorType>(I.getOperand(0)->getType()))
+ return CWriter::visitCastInst(I);
+ std::cerr << I;
+ std::cerr << "SSE C Backend cannot handle this cast!\n";
+ }
+
+ void SSECWriter::visitBinaryOperator(Instruction &I) {
+ if (!isa<FixedVectorType>(I.getType()))
+ return CWriter::visitBinaryOperator(I);
+ switch(I.getOpcode()) {
+ case Instruction::Add:
+ Out << "_mm_add_epi16(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ case Instruction::Mul:
+ Out << "_mm_mullo_epi16(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ case Instruction::And:
+ Out << "_mm_and_si128(";
+ writeOperand(I.getOperand(0));
+ Out << ",";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ break;
+ default:
+ std::cerr << "SSE C Backend can't handle this instruction:\n" << I;
+ exit(1);
+ }
+ }
+
+ std::ostream &SSECWriter::printFixedVectorType(std::ostream &Out,
+ const FixedVectorType *Ty,
+ const std::string &VariableName) {
+ if (Ty->isIntegralVector()) {
+ Out << "__m128i " << VariableName;
+ } else {
+ std::cerr << "SSE C Backend cannot handle type!\n" << Ty->getDescription() << "\n";
+ exit(1);
+ }
+ return Out;
+ }
+
+
+ //===----------------------------------------------------------------------===//
+ // External Interface declaration
+ //===----------------------------------------------------------------------===//
+
+ bool SSECTargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &o,
+ CodeGenFileType FileType) {
+ if (FileType != TargetMachine::AssemblyFile) return true;
+ // Add lowervectors pass here to lower variable-length vectors, which we can't handle
+ PM.add(createLowerGCPass());
+ PM.add(createLowerAllocationsPass(true));
+ PM.add(createLowerInvokePass());
+ PM.add(new CBackendNameAllUsedStructs());
+ PM.add(new SSECWriter(o, getIntrinsicLowering()));
+ return false;
+ }
Index: llvm/lib/Target/CBackend/SSEWriter.h
diff -c /dev/null llvm/lib/Target/CBackend/SSEWriter.h:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/SSEWriter.h Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,57 ----
+ //===---------------- Writer.h - C backend interface ------------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file exposes the interface that is common to all C backends.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef SSECWRITER_H
+ #define SSECWRITER_H
+
+ #include "Writer.h"
+
+ using namespace llvm;
+
+ namespace llvm {
+ /// SSECWriter - This class is the main chunk of code that
+ /// converts an LLVM module to an SSE/C translation unit.
+ class SSECWriter : public CWriter {
+ void printConstant(Constant *CPV);
+ void visitCastInst (CastInst &I);
+ void visitBinaryOperator(Instruction &I);
+
+ public:
+ SSECWriter(std::ostream &o, IntrinsicLowering &il) :
+ CWriter(o,il) {}
+
+ // Provide declaration for SSE intrinsics
+ //
+ bool doInitialization(Module &M) {
+ Out << "#include \"SSE.h\"\n";
+ return CWriter::doInitialization(M);
+ }
+
+ bool printDeclarationFor(Function *F) {
+ if (F->getName().substr(0, 4) == "_mm_")
+ return false;
+ return CWriter::printDeclarationFor(F);
+ }
+ virtual const char *getPassName() const { return "SSE C backend"; }
+
+ std::ostream &printFixedVectorType(std::ostream &Out,
+ const FixedVectorType *Ty,
+ const std::string &VariableName = "");
+
+ };
+ }
+
+
+
+ #endif
+
Index: llvm/lib/Target/CBackend/Writer.h
diff -c /dev/null llvm/lib/Target/CBackend/Writer.h:1.1.2.1
*** /dev/null Tue Oct 18 14:37:03 2005
--- llvm/lib/Target/CBackend/Writer.h Tue Oct 18 14:36:52 2005
***************
*** 0 ****
--- 1,269 ----
+ //===---------------- Writer.h - C backend interface ------------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file exposes the interface that is common to all C backends.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef CWRITER_H
+ #define CWRITER_H
+
+ #include "llvm/Constants.h"
+ #include "llvm/DerivedTypes.h"
+ #include "llvm/Module.h"
+ #include "llvm/Instructions.h"
+ #include "llvm/Pass.h"
+ #include "llvm/PassManager.h"
+ #include "llvm/SymbolTable.h"
+ #include "llvm/Intrinsics.h"
+ #include "llvm/Analysis/ConstantsScanner.h"
+ #include "llvm/Analysis/FindUsedTypes.h"
+ #include "llvm/Analysis/LoopInfo.h"
+ #include "llvm/CodeGen/IntrinsicLowering.h"
+ #include "llvm/Transforms/Scalar.h"
+ #include "llvm/Target/TargetMachineRegistry.h"
+ #include "llvm/Support/CallSite.h"
+ #include "llvm/Support/CFG.h"
+ #include "llvm/Support/GetElementPtrTypeIterator.h"
+ #include "llvm/Support/InstVisitor.h"
+ #include "llvm/Support/Mangler.h"
+ #include "llvm/ADT/StringExtras.h"
+ #include "llvm/ADT/STLExtras.h"
+ #include "llvm/Support/MathExtras.h"
+ #include "llvm/Config/config.h"
+ #include <algorithm>
+ #include <iostream>
+ #include <sstream>
+
+ using namespace llvm;
+
+ namespace llvm {
+ /// NameAllUsedStructs - This pass inserts names for any unnamed structure
+ /// types that are used by the program.
+ ///
+ class CBackendNameAllUsedStructs : public ModulePass {
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<FindUsedTypes>();
+ }
+
+ virtual const char *getPassName() const {
+ return "C backend type canonicalizer";
+ }
+
+ virtual bool runOnModule(Module &M);
+ };
+
+ /// CWriter - This class is the main chunk of code that converts an LLVM
+ /// module to a C translation unit.
+ class CWriter : public FunctionPass, public InstVisitor<CWriter> {
+ protected:
+ std::ostream &Out;
+ IntrinsicLowering &IL;
+ Mangler *Mang;
+ LoopInfo *LI;
+ const Module *TheModule;
+ std::map<const Type *, std::string> TypeNames;
+
+ std::map<const ConstantFP *, unsigned> FPConstantMap;
+ public:
+ CWriter(std::ostream &o, IntrinsicLowering &il) : Out(o), IL(il) {}
+
+ virtual const char *getPassName() const { return "C backend"; }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<LoopInfo>();
+ AU.setPreservesAll();
+ }
+
+ virtual bool printDeclarationFor(Function *F);
+ virtual bool doInitialization(Module &M);
+
+ bool runOnFunction(Function &F) {
+ LI = &getAnalysis<LoopInfo>();
+
+ // Get rid of intrinsics we can't handle.
+ lowerIntrinsics(F);
+
+ // Output all floating point constants that cannot be printed accurately.
+ printFloatingPointConstants(F);
+
+ // Ensure that no local symbols conflict with global symbols.
+ F.renameLocalSymbols();
+
+ printFunction(F);
+ FPConstantMap.clear();
+ return false;
+ }
+
+ virtual bool doFinalization(Module &M) {
+ // Free memory...
+ delete Mang;
+ TypeNames.clear();
+ return false;
+ }
+
+ std::ostream &printType(std::ostream &Out, const Type *Ty,
+ const std::string &VariableName = "",
+ bool IgnoreName = false);
+
+ // Methods for printing vector types; these can be overridden by
+ // target-specific subclasses (AltiVec, SSE, etc.)
+ //
+ virtual std::ostream &printFixedVectorType(std::ostream &Out,
+ const FixedVectorType *Ty,
+ const std::string &VariableName = "") {
+ // FIXME: Insert lowering so this never happens
+ //
+ std::cerr << "Backend cannot handle vector types!\n";
+ exit(1);
+ }
+
+ virtual std::ostream &printVectorType(std::ostream &Out,
+ const VectorType *Ty,
+ const std::string &VariableName = "") {
+ // FIXME: Insert lowering so this never happens
+ //
+ std::cerr << "Backend cannot handle vector types!\n";
+ exit(1);
+ }
+
+ virtual void writeValueName(Value *V);
+ void writeOperand(Value *Operand);
+ void writeOperandInternal(Value *Operand);
+
+ protected:
+ void lowerIntrinsics(Function &F);
+
+ bool nameAllUsedStructureTypes(Module &M);
+ void printModule(Module *M);
+ void printModuleTypes(const SymbolTable &ST);
+ void printContainedStructs(const Type *Ty, std::set<const StructType *> &);
+ void printFloatingPointConstants(Function &F);
+ void printFunctionSignature(const Function *F, bool Prototype);
+
+ void printFunction(Function &);
+ void printBasicBlock(BasicBlock *BB);
+ void printLoop(Loop *L);
+
+ virtual void printConstant(Constant *CPV);
+ void printConstantArray(ConstantArray *CPA);
+
+ // isInlinableInst - Attempt to inline instructions into their uses to build
+ // trees as much as possible. To do this, we have to consistently decide
+ // what is acceptable to inline, so that variable declarations don't get
+ // printed and an extra copy of the expr is not emitted.
+ //
+ static bool isInlinableInst(const Instruction &I) {
+ // Always inline setcc instructions, even if they are shared by multiple
+ // expressions. GCC generates horrible code if we don't.
+ if (isa<SetCondInst>(I)) return true;
+
+ // Must be an expression, must be used exactly once. If it is dead, we
+ // emit it inline where it would go.
+ if (I.getType() == Type::VoidTy || !I.hasOneUse() ||
+ isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I) ||
+ isa<LoadInst>(I) || isa<VAArgInst>(I))
+ // Don't inline a load across a store or other bad things!
+ return false;
+
+ // Only inline instruction if its use is in the same BB as the inst.
+ return I.getParent() == cast<Instruction>(I.use_back())->getParent();
+ }
+
+ static const bool isSafeUse(const Value *user, const Value *use) {
+ if (isa<LoadInst>(user))
+ return true;
+ if (const StoreInst *SI = dyn_cast<StoreInst>(user))
+ return (use == SI->getOperand(1));
+ if (isa<CastInst>(user)) {
+ return isSafeUser(user);
+ }
+ return false;
+ }
+
+ static const bool isSafeUser(const Value *user) {
+ for (User::use_const_iterator I = user->use_begin(),
+ E = user->use_end(); I != E; ++I)
+ if (!isSafeUse(*I, user))
+ return false;
+ return true;
+ }
+
+ // isDirectAlloca - Define fixed sized allocas in the entry block
+ // as direct variables which are accessed with the & operator.
+ // This causes GCC to generate significantly better code than to
+ // emit alloca calls directly.
+ //
+ static const AllocaInst *isDirectAlloca(const Value *V) {
+ const AllocaInst *AI = dyn_cast<AllocaInst>(V);
+ if (!AI) return false;
+ if (AI->isArrayAllocation())
+ return 0; // FIXME: we can also inline fixed size array allocas!
+ if (AI->getParent() != &AI->getParent()->getParent()->getEntryBlock())
+ if (!isSafeUser(AI))
+ return 0;
+ return AI;
+ }
+
+ // Instruction visitation functions
+ friend class InstVisitor<CWriter>;
+
+ void visitReturnInst(ReturnInst &I);
+ void visitBranchInst(BranchInst &I);
+ void visitSwitchInst(SwitchInst &I);
+ void visitInvokeInst(InvokeInst &I) {
+ assert(0 && "Lowerinvoke pass didn't work!");
+ }
+
+ void visitUnwindInst(UnwindInst &I) {
+ assert(0 && "Lowerinvoke pass didn't work!");
+ }
+ void visitUnreachableInst(UnreachableInst &I);
+
+ void visitPHINode(PHINode &I);
+ virtual void visitBinaryOperator(Instruction &I);
+
+ virtual void visitCastInst (CastInst &I);
+ virtual void visitVImmInst(VImmInst &VL) { visitInstruction(VL); }
+ void visitSelectInst(SelectInst &I);
+ void visitCallInst (CallInst &I);
+ void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
+
+ void visitMallocInst(MallocInst &I);
+ void visitAllocaInst(AllocaInst &I);
+ void visitFreeInst (FreeInst &I);
+ void visitLoadInst (LoadInst &I);
+ void visitStoreInst (StoreInst &I);
+ void visitGetElementPtrInst(GetElementPtrInst &I);
+ //void visitVANextInst(VANextInst &I);
+ void visitVAArgInst (VAArgInst &I);
+
+ void visitInstruction(Instruction &I) {
+ std::cerr << "C Writer does not know about " << I;
+ abort();
+ }
+
+ void outputLValue(Instruction *I) {
+ Out << " " << Mang->getValueName(I) << " = ";
+ }
+
+ bool isGotoCodeNecessary(BasicBlock *From, BasicBlock *To);
+ void printPHICopiesForSuccessor(BasicBlock *CurBlock,
+ BasicBlock *Successor, unsigned Indent);
+ void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock,
+ unsigned Indent);
+ void printIndexingExpression(Value *Ptr, gep_type_iterator I,
+ gep_type_iterator E);
+ };
+ }
+
+
+
+ #endif
+
More information about the llvm-commits
mailing list