2007-01-10 04:17:32 +00:00
|
|
|
//===-- CBackend.cpp - Library for converting LLVM code to C --------------===//
|
2005-04-20 16:05:03 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-20 16:05:03 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2002-05-08 18:09:58 +00:00
|
|
|
//
|
2004-02-13 06:18:21 +00:00
|
|
|
// This library converts LLVM code to C code, compilable by GCC and other C
|
|
|
|
// compilers.
|
2002-05-09 02:28:59 +00:00
|
|
|
//
|
2003-05-03 03:14:35 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2003-05-03 07:11:00 +00:00
|
|
|
|
2004-02-13 23:18:48 +00:00
|
|
|
#include "CTargetMachine.h"
|
2006-05-23 23:39:48 +00:00
|
|
|
#include "llvm/CallingConv.h"
|
2002-05-08 18:09:58 +00:00
|
|
|
#include "llvm/Constants.h"
|
2002-05-09 03:28:37 +00:00
|
|
|
#include "llvm/DerivedTypes.h"
|
|
|
|
#include "llvm/Module.h"
|
2003-04-22 20:19:52 +00:00
|
|
|
#include "llvm/Instructions.h"
|
2008-02-22 22:17:59 +00:00
|
|
|
#include "llvm/ParamAttrsList.h"
|
2002-08-31 00:29:16 +00:00
|
|
|
#include "llvm/Pass.h"
|
2004-02-13 23:00:29 +00:00
|
|
|
#include "llvm/PassManager.h"
|
2007-01-06 07:24:44 +00:00
|
|
|
#include "llvm/TypeSymbolTable.h"
|
2003-05-08 18:41:45 +00:00
|
|
|
#include "llvm/Intrinsics.h"
|
2006-03-23 18:08:29 +00:00
|
|
|
#include "llvm/IntrinsicInst.h"
|
2006-11-27 23:50:49 +00:00
|
|
|
#include "llvm/InlineAsm.h"
|
2002-09-20 23:26:33 +00:00
|
|
|
#include "llvm/Analysis/ConstantsScanner.h"
|
2004-05-09 20:41:32 +00:00
|
|
|
#include "llvm/Analysis/FindUsedTypes.h"
|
|
|
|
#include "llvm/Analysis/LoopInfo.h"
|
2008-01-07 01:30:38 +00:00
|
|
|
#include "llvm/CodeGen/Passes.h"
|
2004-06-20 07:49:54 +00:00
|
|
|
#include "llvm/CodeGen/IntrinsicLowering.h"
|
2004-02-13 23:00:29 +00:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2004-07-11 02:48:49 +00:00
|
|
|
#include "llvm/Target/TargetMachineRegistry.h"
|
2006-11-28 19:53:36 +00:00
|
|
|
#include "llvm/Target/TargetAsmInfo.h"
|
2007-01-29 17:51:02 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2003-11-25 20:49:55 +00:00
|
|
|
#include "llvm/Support/CallSite.h"
|
2004-05-09 03:42:48 +00:00
|
|
|
#include "llvm/Support/CFG.h"
|
2003-11-25 20:49:55 +00:00
|
|
|
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
2002-05-08 18:09:58 +00:00
|
|
|
#include "llvm/Support/InstVisitor.h"
|
2003-07-25 20:21:06 +00:00
|
|
|
#include "llvm/Support/Mangler.h"
|
2005-08-17 19:34:49 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2004-09-01 22:55:40 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2005-03-18 16:12:37 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2004-09-01 22:55:40 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
#include "llvm/Config/config.h"
|
2002-05-08 18:09:58 +00:00
|
|
|
#include <algorithm>
|
2006-12-07 23:41:45 +00:00
|
|
|
#include <sstream>
|
2004-02-13 06:18:21 +00:00
|
|
|
using namespace llvm;
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
namespace {
|
2004-07-11 02:48:49 +00:00
|
|
|
// Register the target.
|
2004-07-11 03:27:42 +00:00
|
|
|
RegisterTarget<CTargetMachine> X("c", " C backend");
|
2004-07-11 02:48:49 +00:00
|
|
|
|
2006-02-13 22:22:42 +00:00
|
|
|
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
|
|
|
|
/// any unnamed structure types that are used by the program, and merges
|
|
|
|
/// external functions with the same name.
|
2004-05-09 06:20:51 +00:00
|
|
|
///
|
2006-02-13 22:22:42 +00:00
|
|
|
class CBackendNameAllUsedStructsAndMergeFunctions : public ModulePass {
|
2007-05-01 21:15:47 +00:00
|
|
|
public:
|
2007-05-03 01:11:54 +00:00
|
|
|
static char ID;
|
2007-05-01 21:15:47 +00:00
|
|
|
CBackendNameAllUsedStructsAndMergeFunctions()
|
|
|
|
: ModulePass((intptr_t)&ID) {}
|
2004-05-09 06:20:51 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.addRequired<FindUsedTypes>();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char *getPassName() const {
|
|
|
|
return "C backend type canonicalizer";
|
|
|
|
}
|
|
|
|
|
2004-09-20 04:48:05 +00:00
|
|
|
virtual bool runOnModule(Module &M);
|
2004-05-09 06:20:51 +00:00
|
|
|
};
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2007-05-03 01:11:54 +00:00
|
|
|
char CBackendNameAllUsedStructsAndMergeFunctions::ID = 0;
|
2007-05-01 21:15:47 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
/// 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> {
|
2005-04-20 16:05:03 +00:00
|
|
|
std::ostream &Out;
|
2007-01-29 17:51:02 +00:00
|
|
|
IntrinsicLowering *IL;
|
2003-07-24 20:20:44 +00:00
|
|
|
Mangler *Mang;
|
2004-05-09 20:41:32 +00:00
|
|
|
LoopInfo *LI;
|
2002-05-08 18:09:58 +00:00
|
|
|
const Module *TheModule;
|
2006-11-28 19:53:36 +00:00
|
|
|
const TargetAsmInfo* TAsm;
|
2007-01-29 17:51:02 +00:00
|
|
|
const TargetData* TD;
|
2003-05-03 03:14:35 +00:00
|
|
|
std::map<const Type *, std::string> TypeNames;
|
|
|
|
std::map<const ConstantFP *, unsigned> FPConstantMap;
|
2007-04-12 21:00:45 +00:00
|
|
|
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
|
2008-03-02 08:07:24 +00:00
|
|
|
std::set<const Argument*> ByValParams;
|
2007-04-12 21:00:45 +00:00
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
public:
|
2007-05-03 01:11:54 +00:00
|
|
|
static char ID;
|
2007-05-01 21:15:47 +00:00
|
|
|
CWriter(std::ostream &o)
|
|
|
|
: FunctionPass((intptr_t)&ID), Out(o), IL(0), Mang(0), LI(0),
|
|
|
|
TheModule(0), TAsm(0), TD(0) {}
|
2002-08-31 00:29:16 +00:00
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
virtual const char *getPassName() const { return "C backend"; }
|
2002-08-31 00:29:16 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.addRequired<LoopInfo>();
|
|
|
|
AU.setPreservesAll();
|
|
|
|
}
|
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
virtual bool doInitialization(Module &M);
|
2002-08-31 00:29:16 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
bool runOnFunction(Function &F) {
|
2004-05-09 20:41:32 +00:00
|
|
|
LI = &getAnalysis<LoopInfo>();
|
|
|
|
|
2004-12-05 06:49:44 +00:00
|
|
|
// Get rid of intrinsics we can't handle.
|
|
|
|
lowerIntrinsics(F);
|
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
// Output all floating point constants that cannot be printed accurately.
|
|
|
|
printFloatingPointConstants(F);
|
2004-12-05 06:49:44 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
printFunction(F);
|
|
|
|
return false;
|
|
|
|
}
|
2002-08-31 00:29:16 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
virtual bool doFinalization(Module &M) {
|
2002-08-31 00:29:16 +00:00
|
|
|
// Free memory...
|
2003-07-24 20:20:44 +00:00
|
|
|
delete Mang;
|
2008-01-11 09:12:49 +00:00
|
|
|
FPConstantMap.clear();
|
2002-08-31 00:29:16 +00:00
|
|
|
TypeNames.clear();
|
2008-01-11 09:12:49 +00:00
|
|
|
ByValParams.clear();
|
2008-03-02 08:07:24 +00:00
|
|
|
intrinsicPrototypesAlreadyGenerated.clear();
|
2004-05-09 20:41:32 +00:00
|
|
|
return false;
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2007-01-07 03:24:48 +00:00
|
|
|
std::ostream &printType(std::ostream &Out, const Type *Ty,
|
2007-01-09 17:09:09 +00:00
|
|
|
bool isSigned = false,
|
2003-05-03 03:14:35 +00:00
|
|
|
const std::string &VariableName = "",
|
2007-11-27 13:23:08 +00:00
|
|
|
bool IgnoreName = false,
|
|
|
|
const ParamAttrsList *PAL = 0);
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
std::ostream &printSimpleType(std::ostream &Out, const Type *Ty,
|
2008-03-02 03:16:38 +00:00
|
|
|
bool isSigned,
|
|
|
|
const std::string &NameSoFar = "");
|
2002-05-09 03:06:06 +00:00
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
void printStructReturnPointerFunctionType(std::ostream &Out,
|
2007-11-27 13:23:08 +00:00
|
|
|
const ParamAttrsList *PAL,
|
2006-05-23 23:39:48 +00:00
|
|
|
const PointerType *Ty);
|
2008-03-02 08:07:24 +00:00
|
|
|
|
|
|
|
/// writeOperandDeref - Print the result of dereferencing the specified
|
|
|
|
/// operand with '*'. This is equivalent to printing '*' then using
|
|
|
|
/// writeOperand, but avoids excess syntax in some cases.
|
|
|
|
void writeOperandDeref(Value *Operand) {
|
|
|
|
if (isAddressExposed(Operand)) {
|
|
|
|
// Already something with an address exposed.
|
|
|
|
writeOperandInternal(Operand);
|
|
|
|
} else {
|
|
|
|
Out << "*(";
|
|
|
|
writeOperand(Operand);
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
}
|
2006-05-23 23:39:48 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void writeOperand(Value *Operand);
|
2006-11-27 23:50:49 +00:00
|
|
|
void writeOperandRaw(Value *Operand);
|
2002-06-25 15:57:03 +00:00
|
|
|
void writeOperandInternal(Value *Operand);
|
2006-10-26 06:15:43 +00:00
|
|
|
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
2007-09-15 06:51:03 +00:00
|
|
|
void writeOperandWithCast(Value* Operand, const ICmpInst &I);
|
2006-10-26 06:15:43 +00:00
|
|
|
bool writeInstructionCast(const Instruction &I);
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2008-02-01 21:25:59 +00:00
|
|
|
void writeMemoryAccess(Value *Operand, const Type *OperandType,
|
|
|
|
bool IsVolatile, unsigned Alignment);
|
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
private :
|
2006-11-28 19:53:36 +00:00
|
|
|
std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c);
|
|
|
|
|
2004-05-09 04:30:20 +00:00
|
|
|
void lowerIntrinsics(Function &F);
|
2004-02-14 00:31:10 +00:00
|
|
|
|
2002-05-09 15:49:41 +00:00
|
|
|
void printModule(Module *M);
|
2007-01-06 07:24:44 +00:00
|
|
|
void printModuleTypes(const TypeSymbolTable &ST);
|
2002-09-20 15:05:40 +00:00
|
|
|
void printContainedStructs(const Type *Ty, std::set<const StructType *> &);
|
2004-05-09 06:20:51 +00:00
|
|
|
void printFloatingPointConstants(Function &F);
|
2002-08-20 16:55:48 +00:00
|
|
|
void printFunctionSignature(const Function *F, bool Prototype);
|
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
void printFunction(Function &);
|
2004-05-09 20:41:32 +00:00
|
|
|
void printBasicBlock(BasicBlock *BB);
|
|
|
|
void printLoop(Loop *L);
|
2002-05-09 03:06:06 +00:00
|
|
|
|
2006-11-27 01:05:10 +00:00
|
|
|
void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
|
2002-08-19 21:32:41 +00:00
|
|
|
void printConstant(Constant *CPV);
|
2006-10-26 06:15:43 +00:00
|
|
|
void printConstantWithCast(Constant *CPV, unsigned Opcode);
|
|
|
|
bool printConstExprCast(const ConstantExpr *CE);
|
2002-08-19 21:32:41 +00:00
|
|
|
void printConstantArray(ConstantArray *CPA);
|
2008-03-02 08:07:24 +00:00
|
|
|
void printConstantVector(ConstantVector *CV);
|
2002-08-19 21:32:41 +00:00
|
|
|
|
2008-03-02 08:07:24 +00:00
|
|
|
/// isAddressExposed - Return true if the specified value's name needs to
|
|
|
|
/// have its address taken in order to get a C value of the correct type.
|
|
|
|
/// This happens for global variables, byval parameters, and direct allocas.
|
|
|
|
bool isAddressExposed(const Value *V) const {
|
|
|
|
if (const Argument *A = dyn_cast<Argument>(V))
|
|
|
|
return ByValParams.count(A);
|
|
|
|
return isa<GlobalVariable>(V) || isDirectAlloca(V);
|
|
|
|
}
|
|
|
|
|
2002-05-09 21:18:38 +00:00
|
|
|
// 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.
|
|
|
|
//
|
2002-06-25 15:57:03 +00:00
|
|
|
static bool isInlinableInst(const Instruction &I) {
|
2006-12-23 06:05:41 +00:00
|
|
|
// Always inline cmp instructions, even if they are shared by multiple
|
2004-05-20 20:25:50 +00:00
|
|
|
// expressions. GCC generates horrible code if we don't.
|
2006-12-23 06:05:41 +00:00
|
|
|
if (isa<CmpInst>(I))
|
|
|
|
return true;
|
2004-05-20 20:25:50 +00:00
|
|
|
|
2002-05-09 21:18:38 +00:00
|
|
|
// Must be an expression, must be used exactly once. If it is dead, we
|
|
|
|
// emit it inline where it would go.
|
2003-10-15 16:48:29 +00:00
|
|
|
if (I.getType() == Type::VoidTy || !I.hasOneUse() ||
|
2005-04-20 16:05:03 +00:00
|
|
|
isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I) ||
|
2008-03-02 03:52:39 +00:00
|
|
|
isa<LoadInst>(I) || isa<VAArgInst>(I) || isa<InsertElementInst>(I))
|
2003-07-23 20:45:31 +00:00
|
|
|
// Don't inline a load across a store or other bad things!
|
2002-05-09 21:18:38 +00:00
|
|
|
return false;
|
|
|
|
|
2008-03-02 05:41:07 +00:00
|
|
|
// Must not be used in inline asm, extractelement, or shufflevector.
|
|
|
|
if (I.hasOneUse()) {
|
|
|
|
const Instruction &User = cast<Instruction>(*I.use_back());
|
|
|
|
if (isInlineAsm(User) || isa<ExtractElementInst>(User) ||
|
|
|
|
isa<ShuffleVectorInst>(User))
|
|
|
|
return false;
|
|
|
|
}
|
2006-11-27 23:50:49 +00:00
|
|
|
|
2006-12-11 20:39:15 +00:00
|
|
|
// Only inline instruction it if it's use is in the same BB as the inst.
|
2002-06-25 15:57:03 +00:00
|
|
|
return I.getParent() == cast<Instruction>(I.use_back())->getParent();
|
2002-05-09 21:18:38 +00:00
|
|
|
}
|
|
|
|
|
2003-06-17 04:39:14 +00:00
|
|
|
// 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!
|
2003-09-20 14:39:18 +00:00
|
|
|
if (AI->getParent() != &AI->getParent()->getParent()->getEntryBlock())
|
2003-06-17 04:39:14 +00:00
|
|
|
return 0;
|
|
|
|
return AI;
|
|
|
|
}
|
2006-11-27 23:50:49 +00:00
|
|
|
|
|
|
|
// isInlineAsm - Check if the instruction is a call to an inline asm chunk
|
|
|
|
static bool isInlineAsm(const Instruction& I) {
|
|
|
|
if (isa<CallInst>(&I) && isa<InlineAsm>(I.getOperand(0)))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
// Instruction visitation functions
|
|
|
|
friend class InstVisitor<CWriter>;
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitReturnInst(ReturnInst &I);
|
|
|
|
void visitBranchInst(BranchInst &I);
|
2003-04-22 20:19:52 +00:00
|
|
|
void visitSwitchInst(SwitchInst &I);
|
2004-05-09 20:41:32 +00:00
|
|
|
void visitInvokeInst(InvokeInst &I) {
|
|
|
|
assert(0 && "Lowerinvoke pass didn't work!");
|
|
|
|
}
|
|
|
|
|
|
|
|
void visitUnwindInst(UnwindInst &I) {
|
|
|
|
assert(0 && "Lowerinvoke pass didn't work!");
|
|
|
|
}
|
2004-10-16 18:12:13 +00:00
|
|
|
void visitUnreachableInst(UnreachableInst &I);
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2003-05-03 07:11:00 +00:00
|
|
|
void visitPHINode(PHINode &I);
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitBinaryOperator(Instruction &I);
|
2006-12-23 06:05:41 +00:00
|
|
|
void visitICmpInst(ICmpInst &I);
|
|
|
|
void visitFCmpInst(FCmpInst &I);
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitCastInst (CastInst &I);
|
2004-03-12 05:52:14 +00:00
|
|
|
void visitSelectInst(SelectInst &I);
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitCallInst (CallInst &I);
|
2006-11-27 23:50:49 +00:00
|
|
|
void visitInlineAsm(CallInst &I);
|
2008-03-02 08:29:41 +00:00
|
|
|
bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee);
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitMallocInst(MallocInst &I);
|
|
|
|
void visitAllocaInst(AllocaInst &I);
|
|
|
|
void visitFreeInst (FreeInst &I);
|
|
|
|
void visitLoadInst (LoadInst &I);
|
|
|
|
void visitStoreInst (StoreInst &I);
|
|
|
|
void visitGetElementPtrInst(GetElementPtrInst &I);
|
2003-10-18 05:57:43 +00:00
|
|
|
void visitVAArgInst (VAArgInst &I);
|
2008-03-02 03:52:39 +00:00
|
|
|
|
|
|
|
void visitInsertElementInst(InsertElementInst &I);
|
2008-03-02 03:57:08 +00:00
|
|
|
void visitExtractElementInst(ExtractElementInst &I);
|
2008-03-02 05:41:07 +00:00
|
|
|
void visitShuffleVectorInst(ShuffleVectorInst &SVI);
|
2002-05-09 15:49:41 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void visitInstruction(Instruction &I) {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "C Writer does not know about " << I;
|
2002-05-09 20:53:56 +00:00
|
|
|
abort();
|
2002-05-09 15:49:41 +00:00
|
|
|
}
|
2002-05-09 20:14:10 +00:00
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
void outputLValue(Instruction *I) {
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << " " << GetValueName(I) << " = ";
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
2004-05-09 20:41:32 +00:00
|
|
|
|
|
|
|
bool isGotoCodeNecessary(BasicBlock *From, BasicBlock *To);
|
2004-10-20 14:38:39 +00:00
|
|
|
void printPHICopiesForSuccessor(BasicBlock *CurBlock,
|
|
|
|
BasicBlock *Successor, unsigned Indent);
|
2002-05-09 20:53:56 +00:00
|
|
|
void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock,
|
|
|
|
unsigned Indent);
|
2008-03-02 08:07:24 +00:00
|
|
|
void printGEPExpression(Value *Ptr, gep_type_iterator I,
|
|
|
|
gep_type_iterator E);
|
2007-02-23 22:45:08 +00:00
|
|
|
|
|
|
|
std::string GetValueName(const Value *Operand);
|
2002-05-09 20:53:56 +00:00
|
|
|
};
|
2004-02-14 00:31:10 +00:00
|
|
|
}
|
2002-05-09 03:50:42 +00:00
|
|
|
|
2007-05-03 01:11:54 +00:00
|
|
|
char CWriter::ID = 0;
|
2007-05-01 21:15:47 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
/// This method inserts names for any unnamed structure types that are used by
|
|
|
|
/// the program, and removes names from structure types that are not used by the
|
|
|
|
/// program.
|
|
|
|
///
|
2006-02-13 22:22:42 +00:00
|
|
|
bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) {
|
2004-05-09 06:20:51 +00:00
|
|
|
// Get a set of types that are used by the program...
|
|
|
|
std::set<const Type *> UT = getAnalysis<FindUsedTypes>().getTypes();
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
// Loop over the module symbol table, removing types from UT that are
|
2005-03-08 16:19:59 +00:00
|
|
|
// already named, and removing names for types that are not used.
|
2004-05-09 06:20:51 +00:00
|
|
|
//
|
2007-01-06 07:24:44 +00:00
|
|
|
TypeSymbolTable &TST = M.getTypeSymbolTable();
|
|
|
|
for (TypeSymbolTable::iterator TI = TST.begin(), TE = TST.end();
|
2004-05-25 08:53:40 +00:00
|
|
|
TI != TE; ) {
|
2007-01-06 07:24:44 +00:00
|
|
|
TypeSymbolTable::iterator I = TI++;
|
2007-01-16 07:22:23 +00:00
|
|
|
|
|
|
|
// If this isn't a struct type, remove it from our set of types to name.
|
|
|
|
// This simplifies emission later.
|
2007-01-16 18:02:45 +00:00
|
|
|
if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second)) {
|
2007-01-06 07:24:44 +00:00
|
|
|
TST.remove(I);
|
2007-01-16 07:22:23 +00:00
|
|
|
} else {
|
|
|
|
// If this is not used, remove it from the symbol table.
|
|
|
|
std::set<const Type *>::iterator UTI = UT.find(I->second);
|
|
|
|
if (UTI == UT.end())
|
|
|
|
TST.remove(I);
|
|
|
|
else
|
|
|
|
UT.erase(UTI); // Only keep one name for this type.
|
|
|
|
}
|
2004-05-25 08:53:40 +00:00
|
|
|
}
|
2004-05-09 06:20:51 +00:00
|
|
|
|
|
|
|
// UT now contains types that are not named. Loop over it, naming
|
|
|
|
// structure types.
|
|
|
|
//
|
|
|
|
bool Changed = false;
|
2004-05-28 05:47:27 +00:00
|
|
|
unsigned RenameCounter = 0;
|
2004-05-09 06:20:51 +00:00
|
|
|
for (std::set<const Type *>::const_iterator I = UT.begin(), E = UT.end();
|
|
|
|
I != E; ++I)
|
|
|
|
if (const StructType *ST = dyn_cast<StructType>(*I)) {
|
2004-05-28 05:47:27 +00:00
|
|
|
while (M.addTypeName("unnamed"+utostr(RenameCounter), ST))
|
|
|
|
++RenameCounter;
|
2004-05-09 06:20:51 +00:00
|
|
|
Changed = true;
|
|
|
|
}
|
2006-02-13 22:22:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Loop over all external functions and globals. If we have two with
|
|
|
|
// identical names, merge them.
|
|
|
|
// FIXME: This code should disappear when we don't allow values with the same
|
|
|
|
// names when they have different types!
|
|
|
|
std::map<std::string, GlobalValue*> ExtSymbols;
|
|
|
|
for (Module::iterator I = M.begin(), E = M.end(); I != E;) {
|
|
|
|
Function *GV = I++;
|
2007-01-30 20:08:39 +00:00
|
|
|
if (GV->isDeclaration() && GV->hasName()) {
|
2006-02-13 22:22:42 +00:00
|
|
|
std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
|
|
|
|
= ExtSymbols.insert(std::make_pair(GV->getName(), GV));
|
|
|
|
if (!X.second) {
|
|
|
|
// Found a conflict, replace this global with the previous one.
|
|
|
|
GlobalValue *OldGV = X.first->second;
|
2006-12-12 05:05:00 +00:00
|
|
|
GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
|
2006-02-13 22:22:42 +00:00
|
|
|
GV->eraseFromParent();
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Do the same for globals.
|
|
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E;) {
|
|
|
|
GlobalVariable *GV = I++;
|
2007-01-30 20:08:39 +00:00
|
|
|
if (GV->isDeclaration() && GV->hasName()) {
|
2006-02-13 22:22:42 +00:00
|
|
|
std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
|
|
|
|
= ExtSymbols.insert(std::make_pair(GV->getName(), GV));
|
|
|
|
if (!X.second) {
|
|
|
|
// Found a conflict, replace this global with the previous one.
|
|
|
|
GlobalValue *OldGV = X.first->second;
|
2006-12-12 05:05:00 +00:00
|
|
|
GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
|
2006-02-13 22:22:42 +00:00
|
|
|
GV->eraseFromParent();
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
/// printStructReturnPointerFunctionType - This is like printType for a struct
|
|
|
|
/// return type, except, instead of printing the type as void (*)(Struct*, ...)
|
|
|
|
/// print it as "Struct (*)(...)", for struct return functions.
|
|
|
|
void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
|
2007-11-27 13:23:08 +00:00
|
|
|
const ParamAttrsList *PAL,
|
2006-05-23 23:39:48 +00:00
|
|
|
const PointerType *TheTy) {
|
|
|
|
const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
|
|
|
|
std::stringstream FunctionInnards;
|
|
|
|
FunctionInnards << " (*) (";
|
|
|
|
bool PrintedType = false;
|
|
|
|
|
|
|
|
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
|
|
|
|
const Type *RetTy = cast<PointerType>(I->get())->getElementType();
|
2007-01-07 03:24:48 +00:00
|
|
|
unsigned Idx = 1;
|
2008-01-11 03:07:46 +00:00
|
|
|
for (++I, ++Idx; I != E; ++I, ++Idx) {
|
2006-05-23 23:39:48 +00:00
|
|
|
if (PrintedType)
|
|
|
|
FunctionInnards << ", ";
|
2008-01-11 03:07:46 +00:00
|
|
|
const Type *ArgTy = *I;
|
2008-01-11 09:12:49 +00:00
|
|
|
if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
|
|
|
|
assert(isa<PointerType>(ArgTy));
|
|
|
|
ArgTy = cast<PointerType>(ArgTy)->getElementType();
|
|
|
|
}
|
2008-01-11 03:07:46 +00:00
|
|
|
printType(FunctionInnards, ArgTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedType = true;
|
|
|
|
}
|
|
|
|
if (FTy->isVarArg()) {
|
|
|
|
if (PrintedType)
|
|
|
|
FunctionInnards << ", ...";
|
|
|
|
} else if (!PrintedType) {
|
|
|
|
FunctionInnards << "void";
|
|
|
|
}
|
|
|
|
FunctionInnards << ')';
|
|
|
|
std::string tstr = FunctionInnards.str();
|
2007-01-07 03:24:48 +00:00
|
|
|
printType(Out, RetTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
|
2006-05-23 23:39:48 +00:00
|
|
|
}
|
|
|
|
|
2006-12-23 06:05:41 +00:00
|
|
|
std::ostream &
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned,
|
2008-03-02 03:41:23 +00:00
|
|
|
const std::string &NameSoFar) {
|
2008-03-02 03:33:31 +00:00
|
|
|
assert((Ty->isPrimitiveType() || Ty->isInteger() || isa<VectorType>(Ty)) &&
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
"Invalid type for printSimpleType");
|
2006-12-23 06:05:41 +00:00
|
|
|
switch (Ty->getTypeID()) {
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
case Type::VoidTyID: return Out << "void " << NameSoFar;
|
|
|
|
case Type::IntegerTyID: {
|
|
|
|
unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
|
|
|
|
if (NumBits == 1)
|
|
|
|
return Out << "bool " << NameSoFar;
|
|
|
|
else if (NumBits <= 8)
|
|
|
|
return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar;
|
|
|
|
else if (NumBits <= 16)
|
|
|
|
return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar;
|
|
|
|
else if (NumBits <= 32)
|
|
|
|
return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar;
|
|
|
|
else {
|
|
|
|
assert(NumBits <= 64 && "Bit widths > 64 not implemented yet");
|
|
|
|
return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case Type::FloatTyID: return Out << "float " << NameSoFar;
|
|
|
|
case Type::DoubleTyID: return Out << "double " << NameSoFar;
|
2007-09-17 00:38:27 +00:00
|
|
|
// Lacking emulation of FP80 on PPC, etc., we assume whichever of these is
|
|
|
|
// present matches host 'long double'.
|
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
case Type::PPC_FP128TyID:
|
|
|
|
case Type::FP128TyID: return Out << "long double " << NameSoFar;
|
2008-03-02 03:33:31 +00:00
|
|
|
|
|
|
|
case Type::VectorTyID: {
|
|
|
|
const VectorType *VTy = cast<VectorType>(Ty);
|
2008-03-02 03:41:23 +00:00
|
|
|
return printSimpleType(Out, VTy->getElementType(), isSigned,
|
2008-03-02 03:39:43 +00:00
|
|
|
" __attribute__((vector_size(" +
|
|
|
|
utostr(TD->getABITypeSize(VTy)) + " ))) " + NameSoFar);
|
2008-03-02 03:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2006-12-23 06:05:41 +00:00
|
|
|
cerr << "Unknown primitive type: " << *Ty << "\n";
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
2004-05-09 06:20:51 +00:00
|
|
|
|
2002-08-19 22:17:53 +00:00
|
|
|
// Pass the Type* and the variable name and this prints out the variable
|
|
|
|
// declaration.
|
|
|
|
//
|
2003-05-03 03:14:35 +00:00
|
|
|
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
|
2007-01-07 03:24:48 +00:00
|
|
|
bool isSigned, const std::string &NameSoFar,
|
2007-11-27 13:23:08 +00:00
|
|
|
bool IgnoreName, const ParamAttrsList* PAL) {
|
2008-03-02 03:33:31 +00:00
|
|
|
if (Ty->isPrimitiveType() || Ty->isInteger() || isa<VectorType>(Ty)) {
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, Ty, isSigned, NameSoFar);
|
2006-12-23 06:05:41 +00:00
|
|
|
return Out;
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2002-08-19 22:17:53 +00:00
|
|
|
// Check to see if the type is named.
|
2002-10-16 00:08:22 +00:00
|
|
|
if (!IgnoreName || isa<OpaqueType>(Ty)) {
|
2003-05-03 03:14:35 +00:00
|
|
|
std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
|
2005-02-14 18:52:35 +00:00
|
|
|
if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar;
|
2002-10-16 00:08:22 +00:00
|
|
|
}
|
2002-08-19 22:17:53 +00:00
|
|
|
|
2004-06-17 18:19:28 +00:00
|
|
|
switch (Ty->getTypeID()) {
|
2002-08-19 22:17:53 +00:00
|
|
|
case Type::FunctionTyID: {
|
2006-05-23 23:39:48 +00:00
|
|
|
const FunctionType *FTy = cast<FunctionType>(Ty);
|
2005-04-20 16:05:03 +00:00
|
|
|
std::stringstream FunctionInnards;
|
2003-06-25 04:52:09 +00:00
|
|
|
FunctionInnards << " (" << NameSoFar << ") (";
|
2007-01-07 03:24:48 +00:00
|
|
|
unsigned Idx = 1;
|
2006-05-23 23:39:48 +00:00
|
|
|
for (FunctionType::param_iterator I = FTy->param_begin(),
|
|
|
|
E = FTy->param_end(); I != E; ++I) {
|
2008-01-12 18:53:07 +00:00
|
|
|
const Type *ArgTy = *I;
|
|
|
|
if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
|
|
|
|
assert(isa<PointerType>(ArgTy));
|
|
|
|
ArgTy = cast<PointerType>(ArgTy)->getElementType();
|
|
|
|
}
|
2006-05-23 23:39:48 +00:00
|
|
|
if (I != FTy->param_begin())
|
2003-06-25 04:52:09 +00:00
|
|
|
FunctionInnards << ", ";
|
2008-01-12 18:53:07 +00:00
|
|
|
printType(FunctionInnards, ArgTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
|
2007-01-07 03:24:48 +00:00
|
|
|
++Idx;
|
2002-08-19 22:17:53 +00:00
|
|
|
}
|
2006-05-23 23:39:48 +00:00
|
|
|
if (FTy->isVarArg()) {
|
|
|
|
if (FTy->getNumParams())
|
2004-05-25 08:53:40 +00:00
|
|
|
FunctionInnards << ", ...";
|
2006-05-23 23:39:48 +00:00
|
|
|
} else if (!FTy->getNumParams()) {
|
2003-06-25 04:52:09 +00:00
|
|
|
FunctionInnards << "void";
|
2002-08-19 22:17:53 +00:00
|
|
|
}
|
2005-02-14 18:52:35 +00:00
|
|
|
FunctionInnards << ')';
|
2003-06-25 04:52:09 +00:00
|
|
|
std::string tstr = FunctionInnards.str();
|
2007-01-07 03:24:48 +00:00
|
|
|
printType(Out, FTy->getReturnType(),
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
|
2002-11-18 20:55:50 +00:00
|
|
|
return Out;
|
2002-08-19 22:17:53 +00:00
|
|
|
}
|
|
|
|
case Type::StructTyID: {
|
|
|
|
const StructType *STy = cast<StructType>(Ty);
|
|
|
|
Out << NameSoFar + " {\n";
|
|
|
|
unsigned Idx = 0;
|
2004-02-09 04:37:31 +00:00
|
|
|
for (StructType::element_iterator I = STy->element_begin(),
|
|
|
|
E = STy->element_end(); I != E; ++I) {
|
2002-08-19 22:17:53 +00:00
|
|
|
Out << " ";
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, *I, false, "field" + utostr(Idx++));
|
2002-08-19 22:17:53 +00:00
|
|
|
Out << ";\n";
|
|
|
|
}
|
2007-07-11 19:56:53 +00:00
|
|
|
Out << '}';
|
|
|
|
if (STy->isPacked())
|
|
|
|
Out << " __attribute__ ((packed))";
|
|
|
|
return Out;
|
2005-04-20 16:05:03 +00:00
|
|
|
}
|
2002-08-19 22:17:53 +00:00
|
|
|
|
|
|
|
case Type::PointerTyID: {
|
|
|
|
const PointerType *PTy = cast<PointerType>(Ty);
|
2002-08-25 20:00:08 +00:00
|
|
|
std::string ptrName = "*" + NameSoFar;
|
|
|
|
|
2006-01-20 20:43:57 +00:00
|
|
|
if (isa<ArrayType>(PTy->getElementType()) ||
|
2007-02-15 02:26:10 +00:00
|
|
|
isa<VectorType>(PTy->getElementType()))
|
2003-11-03 04:31:54 +00:00
|
|
|
ptrName = "(" + ptrName + ")";
|
2002-08-25 20:00:08 +00:00
|
|
|
|
2008-01-12 18:53:07 +00:00
|
|
|
if (PAL)
|
|
|
|
// Must be a function ptr cast!
|
|
|
|
return printType(Out, PTy->getElementType(), false, ptrName, true, PAL);
|
2007-01-09 17:09:09 +00:00
|
|
|
return printType(Out, PTy->getElementType(), false, ptrName);
|
2003-07-21 16:34:35 +00:00
|
|
|
}
|
2002-08-19 22:17:53 +00:00
|
|
|
|
|
|
|
case Type::ArrayTyID: {
|
|
|
|
const ArrayType *ATy = cast<ArrayType>(Ty);
|
|
|
|
unsigned NumElements = ATy->getNumElements();
|
2004-12-15 23:13:15 +00:00
|
|
|
if (NumElements == 0) NumElements = 1;
|
2007-01-09 17:09:09 +00:00
|
|
|
return printType(Out, ATy->getElementType(), false,
|
2002-08-19 22:17:53 +00:00
|
|
|
NameSoFar + "[" + utostr(NumElements) + "]");
|
|
|
|
}
|
2002-10-16 00:08:22 +00:00
|
|
|
|
|
|
|
case Type::OpaqueTyID: {
|
|
|
|
static int Count = 0;
|
2003-05-03 03:14:35 +00:00
|
|
|
std::string TyName = "struct opaque_" + itostr(Count++);
|
2002-10-16 00:08:22 +00:00
|
|
|
assert(TypeNames.find(Ty) == TypeNames.end());
|
|
|
|
TypeNames[Ty] = TyName;
|
2005-02-14 18:52:35 +00:00
|
|
|
return Out << TyName << ' ' << NameSoFar;
|
2002-10-16 00:08:22 +00:00
|
|
|
}
|
2002-08-19 22:17:53 +00:00
|
|
|
default:
|
|
|
|
assert(0 && "Unhandled case in getTypeProps!");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Out;
|
|
|
|
}
|
|
|
|
|
2002-08-19 21:32:41 +00:00
|
|
|
void CWriter::printConstantArray(ConstantArray *CPA) {
|
|
|
|
|
|
|
|
// As a special case, print the array as a string if it is an array of
|
|
|
|
// ubytes or an array of sbytes with positive values.
|
2005-04-20 16:05:03 +00:00
|
|
|
//
|
2002-08-19 21:32:41 +00:00
|
|
|
const Type *ETy = CPA->getType()->getElementType();
|
2006-12-31 05:55:36 +00:00
|
|
|
bool isString = (ETy == Type::Int8Ty || ETy == Type::Int8Ty);
|
2002-08-19 21:32:41 +00:00
|
|
|
|
|
|
|
// Make sure the last character is a null char, as automatically added by C
|
2003-06-16 12:09:09 +00:00
|
|
|
if (isString && (CPA->getNumOperands() == 0 ||
|
|
|
|
!cast<Constant>(*(CPA->op_end()-1))->isNullValue()))
|
2002-08-19 21:32:41 +00:00
|
|
|
isString = false;
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2002-08-19 21:32:41 +00:00
|
|
|
if (isString) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '\"';
|
2003-06-16 12:09:09 +00:00
|
|
|
// Keep track of whether the last number was a hexadecimal escape
|
|
|
|
bool LastWasHex = false;
|
|
|
|
|
2002-08-19 21:32:41 +00:00
|
|
|
// Do not include the last character, which we know is null
|
|
|
|
for (unsigned i = 0, e = CPA->getNumOperands()-1; i != e; ++i) {
|
2006-10-20 07:07:24 +00:00
|
|
|
unsigned char C = cast<ConstantInt>(CPA->getOperand(i))->getZExtValue();
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2003-06-16 12:09:09 +00:00
|
|
|
// Print it out literally if it is a printable character. The only thing
|
|
|
|
// to be careful about is when the last letter output was a hex escape
|
|
|
|
// code, in which case we have to be careful not to print out hex digits
|
2003-06-16 12:21:19 +00:00
|
|
|
// explicitly (the C compiler thinks it is a continuation of the previous
|
|
|
|
// character, sheesh...)
|
2003-06-16 12:09:09 +00:00
|
|
|
//
|
|
|
|
if (isprint(C) && (!LastWasHex || !isxdigit(C))) {
|
|
|
|
LastWasHex = false;
|
2002-11-06 21:40:23 +00:00
|
|
|
if (C == '"' || C == '\\')
|
|
|
|
Out << "\\" << C;
|
2002-09-30 21:11:55 +00:00
|
|
|
else
|
|
|
|
Out << C;
|
2002-08-19 21:32:41 +00:00
|
|
|
} else {
|
2003-06-16 12:09:09 +00:00
|
|
|
LastWasHex = false;
|
2002-08-19 21:32:41 +00:00
|
|
|
switch (C) {
|
|
|
|
case '\n': Out << "\\n"; break;
|
|
|
|
case '\t': Out << "\\t"; break;
|
|
|
|
case '\r': Out << "\\r"; break;
|
|
|
|
case '\v': Out << "\\v"; break;
|
|
|
|
case '\a': Out << "\\a"; break;
|
2002-09-30 21:11:55 +00:00
|
|
|
case '\"': Out << "\\\""; break;
|
2005-04-20 16:05:03 +00:00
|
|
|
case '\'': Out << "\\\'"; break;
|
2002-08-19 21:32:41 +00:00
|
|
|
default:
|
|
|
|
Out << "\\x";
|
2003-06-16 12:09:09 +00:00
|
|
|
Out << (char)(( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'));
|
|
|
|
Out << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
|
|
|
|
LastWasHex = true;
|
2002-08-19 21:32:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '\"';
|
2002-08-19 21:32:41 +00:00
|
|
|
} else {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '{';
|
2002-08-19 21:32:41 +00:00
|
|
|
if (CPA->getNumOperands()) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ' ';
|
2002-08-19 21:32:41 +00:00
|
|
|
printConstant(cast<Constant>(CPA->getOperand(0)));
|
|
|
|
for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
printConstant(cast<Constant>(CPA->getOperand(i)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << " }";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-15 02:26:10 +00:00
|
|
|
void CWriter::printConstantVector(ConstantVector *CP) {
|
2006-01-20 20:43:57 +00:00
|
|
|
Out << '{';
|
|
|
|
if (CP->getNumOperands()) {
|
|
|
|
Out << ' ';
|
|
|
|
printConstant(cast<Constant>(CP->getOperand(0)));
|
|
|
|
for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
printConstant(cast<Constant>(CP->getOperand(i)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << " }";
|
|
|
|
}
|
|
|
|
|
2003-10-05 00:40:51 +00:00
|
|
|
// isFPCSafeToPrint - Returns true if we may assume that CFP may be written out
|
|
|
|
// textually as a double (rather than as a reference to a stack-allocated
|
|
|
|
// variable). We decide this by converting CFP to a string and back into a
|
|
|
|
// double, and then checking whether the conversion results in a bit-equal
|
|
|
|
// double to the original value of CFP. This depends on us and the target C
|
|
|
|
// compiler agreeing on the conversion process (which is pretty likely since we
|
|
|
|
// only deal in IEEE FP).
|
|
|
|
//
|
2004-05-09 20:41:32 +00:00
|
|
|
static bool isFPCSafeToPrint(const ConstantFP *CFP) {
|
2007-09-17 00:38:27 +00:00
|
|
|
// Do long doubles in hex for now.
|
2007-09-14 22:26:36 +00:00
|
|
|
if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
|
|
|
|
return false;
|
2007-09-06 18:13:44 +00:00
|
|
|
APFloat APF = APFloat(CFP->getValueAPF()); // copy
|
|
|
|
if (CFP->getType()==Type::FloatTy)
|
|
|
|
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
|
2006-11-05 19:26:37 +00:00
|
|
|
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
|
2003-10-12 08:12:58 +00:00
|
|
|
char Buffer[100];
|
2007-09-06 18:13:44 +00:00
|
|
|
sprintf(Buffer, "%a", APF.convertToDouble());
|
2003-10-12 08:12:58 +00:00
|
|
|
if (!strncmp(Buffer, "0x", 2) ||
|
|
|
|
!strncmp(Buffer, "-0x", 3) ||
|
|
|
|
!strncmp(Buffer, "+0x", 3))
|
2007-09-06 18:13:44 +00:00
|
|
|
return APF.bitwiseIsEqual(APFloat(atof(Buffer)));
|
2003-10-12 08:12:58 +00:00
|
|
|
return false;
|
|
|
|
#else
|
2007-09-06 18:13:44 +00:00
|
|
|
std::string StrVal = ftostr(APF);
|
2003-10-12 04:36:29 +00:00
|
|
|
|
|
|
|
while (StrVal[0] == ' ')
|
|
|
|
StrVal.erase(StrVal.begin());
|
|
|
|
|
2003-10-05 00:40:51 +00:00
|
|
|
// Check to make sure that the stringized number is not some string like "Inf"
|
|
|
|
// or NaN. Check that the string matches the "[-+]?[0-9]" regex.
|
2003-06-17 23:55:35 +00:00
|
|
|
if ((StrVal[0] >= '0' && StrVal[0] <= '9') ||
|
|
|
|
((StrVal[0] == '-' || StrVal[0] == '+') &&
|
|
|
|
(StrVal[1] >= '0' && StrVal[1] <= '9')))
|
|
|
|
// Reparse stringized version!
|
2007-09-06 18:13:44 +00:00
|
|
|
return APF.bitwiseIsEqual(APFloat(atof(StrVal.c_str())));
|
2003-06-17 23:55:35 +00:00
|
|
|
return false;
|
2003-10-12 08:12:58 +00:00
|
|
|
#endif
|
2003-06-17 23:55:35 +00:00
|
|
|
}
|
2002-08-19 21:32:41 +00:00
|
|
|
|
2006-11-27 01:05:10 +00:00
|
|
|
/// Print out the casting for a cast operation. This does the double casting
|
|
|
|
/// necessary for conversion to the destination type, if necessary.
|
|
|
|
/// @brief Print a cast
|
|
|
|
void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
|
2006-12-23 06:05:41 +00:00
|
|
|
// Print the destination type cast
|
2006-11-27 01:05:10 +00:00
|
|
|
switch (opc) {
|
|
|
|
case Instruction::UIToFP:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::BitCast:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::FPTrunc: // For these the DstTy sign doesn't matter
|
|
|
|
Out << '(';
|
|
|
|
printType(Out, DstTy);
|
|
|
|
Out << ')';
|
|
|
|
break;
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::ZExt:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::PtrToInt:
|
|
|
|
case Instruction::FPToUI: // For these, make sure we get an unsigned dest
|
|
|
|
Out << '(';
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, DstTy, false);
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << ')';
|
|
|
|
break;
|
|
|
|
case Instruction::SExt:
|
|
|
|
case Instruction::FPToSI: // For these, make sure we get a signed dest
|
|
|
|
Out << '(';
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, DstTy, true);
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << ')';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid cast opcode");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the source type cast
|
|
|
|
switch (opc) {
|
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::ZExt:
|
|
|
|
Out << '(';
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, SrcTy, false);
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << ')';
|
2006-11-27 01:05:10 +00:00
|
|
|
break;
|
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::SExt:
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << '(';
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, SrcTy, true);
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << ')';
|
2006-11-27 01:05:10 +00:00
|
|
|
break;
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::PtrToInt:
|
2006-12-23 06:05:41 +00:00
|
|
|
// Avoid "cast to pointer from integer of different size" warnings
|
|
|
|
Out << "(unsigned long)";
|
|
|
|
break;
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::BitCast:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::FPTrunc:
|
|
|
|
case Instruction::FPToSI:
|
|
|
|
case Instruction::FPToUI:
|
2006-12-23 06:05:41 +00:00
|
|
|
break; // These don't need a source cast.
|
2006-11-27 01:05:10 +00:00
|
|
|
default:
|
2006-12-23 06:05:41 +00:00
|
|
|
assert(0 && "Invalid cast opcode");
|
2006-11-27 01:05:10 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-19 21:32:41 +00:00
|
|
|
// printConstant - The LLVM Constant to C Constant converter.
|
|
|
|
void CWriter::printConstant(Constant *CPV) {
|
|
|
|
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
|
|
|
|
switch (CE->getOpcode()) {
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::ZExt:
|
|
|
|
case Instruction::SExt:
|
|
|
|
case Instruction::FPTrunc:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::FPToUI:
|
|
|
|
case Instruction::FPToSI:
|
|
|
|
case Instruction::PtrToInt:
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::BitCast:
|
|
|
|
Out << "(";
|
|
|
|
printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType());
|
2007-05-03 02:57:13 +00:00
|
|
|
if (CE->getOpcode() == Instruction::SExt &&
|
|
|
|
CE->getOperand(0)->getType() == Type::Int1Ty) {
|
2007-05-02 02:17:41 +00:00
|
|
|
// Make sure we really sext from bool here by subtracting from 0
|
|
|
|
Out << "0-";
|
|
|
|
}
|
2007-05-03 02:57:13 +00:00
|
|
|
printConstant(CE->getOperand(0));
|
|
|
|
if (CE->getType() == Type::Int1Ty &&
|
|
|
|
(CE->getOpcode() == Instruction::Trunc ||
|
|
|
|
CE->getOpcode() == Instruction::FPToUI ||
|
|
|
|
CE->getOpcode() == Instruction::FPToSI ||
|
|
|
|
CE->getOpcode() == Instruction::PtrToInt)) {
|
|
|
|
// Make sure we really truncate to bool here by anding with 1
|
|
|
|
Out << "&1u";
|
|
|
|
}
|
|
|
|
Out << ')';
|
2002-08-19 23:09:46 +00:00
|
|
|
return;
|
2007-05-03 02:57:13 +00:00
|
|
|
|
2002-08-19 23:09:46 +00:00
|
|
|
case Instruction::GetElementPtr:
|
2008-03-02 08:07:24 +00:00
|
|
|
Out << "(";
|
|
|
|
printGEPExpression(CE->getOperand(0), gep_type_begin(CPV),
|
|
|
|
gep_type_end(CPV));
|
|
|
|
Out << ")";
|
2002-08-19 23:09:46 +00:00
|
|
|
return;
|
2004-04-01 05:28:26 +00:00
|
|
|
case Instruction::Select:
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2004-04-01 05:28:26 +00:00
|
|
|
printConstant(CE->getOperand(0));
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '?';
|
2004-04-01 05:28:26 +00:00
|
|
|
printConstant(CE->getOperand(1));
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ':';
|
2004-04-01 05:28:26 +00:00
|
|
|
printConstant(CE->getOperand(2));
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2004-04-01 05:28:26 +00:00
|
|
|
return;
|
2002-08-19 23:09:46 +00:00
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::Sub:
|
2003-08-14 19:19:53 +00:00
|
|
|
case Instruction::Mul:
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::SDiv:
|
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::FDiv:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
|
|
|
case Instruction::FRem:
|
2004-12-29 04:00:09 +00:00
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::ICmp:
|
2003-11-22 05:02:56 +00:00
|
|
|
case Instruction::Shl:
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
|
|
|
case Instruction::AShr:
|
2006-10-26 06:17:40 +00:00
|
|
|
{
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2006-10-26 06:15:43 +00:00
|
|
|
bool NeedsClosingParens = printConstExprCast(CE);
|
|
|
|
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
|
2003-08-14 19:19:53 +00:00
|
|
|
switch (CE->getOpcode()) {
|
|
|
|
case Instruction::Add: Out << " + "; break;
|
|
|
|
case Instruction::Sub: Out << " - "; break;
|
|
|
|
case Instruction::Mul: Out << " * "; break;
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
|
|
|
case Instruction::FRem: Out << " % "; break;
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::SDiv:
|
|
|
|
case Instruction::FDiv: Out << " / "; break;
|
2004-12-29 04:00:09 +00:00
|
|
|
case Instruction::And: Out << " & "; break;
|
|
|
|
case Instruction::Or: Out << " | "; break;
|
|
|
|
case Instruction::Xor: Out << " ^ "; break;
|
2003-11-22 05:02:56 +00:00
|
|
|
case Instruction::Shl: Out << " << "; break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
|
|
|
case Instruction::AShr: Out << " >> "; break;
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::ICmp:
|
|
|
|
switch (CE->getPredicate()) {
|
|
|
|
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
|
|
|
case ICmpInst::ICMP_NE: Out << " != "; break;
|
|
|
|
case ICmpInst::ICMP_SLT:
|
|
|
|
case ICmpInst::ICMP_ULT: Out << " < "; break;
|
|
|
|
case ICmpInst::ICMP_SLE:
|
|
|
|
case ICmpInst::ICMP_ULE: Out << " <= "; break;
|
|
|
|
case ICmpInst::ICMP_SGT:
|
|
|
|
case ICmpInst::ICMP_UGT: Out << " > "; break;
|
|
|
|
case ICmpInst::ICMP_SGE:
|
|
|
|
case ICmpInst::ICMP_UGE: Out << " >= "; break;
|
|
|
|
default: assert(0 && "Illegal ICmp predicate");
|
|
|
|
}
|
|
|
|
break;
|
2003-08-14 19:19:53 +00:00
|
|
|
default: assert(0 && "Illegal opcode here!");
|
|
|
|
}
|
2006-10-26 06:15:43 +00:00
|
|
|
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
|
|
|
if (NeedsClosingParens)
|
|
|
|
Out << "))";
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2002-08-19 23:09:46 +00:00
|
|
|
return;
|
2006-10-26 06:17:40 +00:00
|
|
|
}
|
2007-01-08 06:58:32 +00:00
|
|
|
case Instruction::FCmp: {
|
|
|
|
Out << '(';
|
|
|
|
bool NeedsClosingParens = printConstExprCast(CE);
|
|
|
|
if (CE->getPredicate() == FCmpInst::FCMP_FALSE)
|
|
|
|
Out << "0";
|
|
|
|
else if (CE->getPredicate() == FCmpInst::FCMP_TRUE)
|
|
|
|
Out << "1";
|
|
|
|
else {
|
|
|
|
const char* op = 0;
|
|
|
|
switch (CE->getPredicate()) {
|
|
|
|
default: assert(0 && "Illegal FCmp predicate");
|
|
|
|
case FCmpInst::FCMP_ORD: op = "ord"; break;
|
|
|
|
case FCmpInst::FCMP_UNO: op = "uno"; break;
|
|
|
|
case FCmpInst::FCMP_UEQ: op = "ueq"; break;
|
|
|
|
case FCmpInst::FCMP_UNE: op = "une"; break;
|
|
|
|
case FCmpInst::FCMP_ULT: op = "ult"; break;
|
|
|
|
case FCmpInst::FCMP_ULE: op = "ule"; break;
|
|
|
|
case FCmpInst::FCMP_UGT: op = "ugt"; break;
|
|
|
|
case FCmpInst::FCMP_UGE: op = "uge"; break;
|
|
|
|
case FCmpInst::FCMP_OEQ: op = "oeq"; break;
|
|
|
|
case FCmpInst::FCMP_ONE: op = "one"; break;
|
|
|
|
case FCmpInst::FCMP_OLT: op = "olt"; break;
|
|
|
|
case FCmpInst::FCMP_OLE: op = "ole"; break;
|
|
|
|
case FCmpInst::FCMP_OGT: op = "ogt"; break;
|
|
|
|
case FCmpInst::FCMP_OGE: op = "oge"; break;
|
|
|
|
}
|
|
|
|
Out << "llvm_fcmp_" << op << "(";
|
|
|
|
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
|
|
|
|
Out << ", ";
|
|
|
|
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
if (NeedsClosingParens)
|
|
|
|
Out << "))";
|
|
|
|
Out << ')';
|
2007-12-21 23:33:44 +00:00
|
|
|
return;
|
2007-01-08 06:58:32 +00:00
|
|
|
}
|
2002-08-19 21:32:41 +00:00
|
|
|
default:
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "CWriter Error: Unhandled constant expression: "
|
|
|
|
<< *CE << "\n";
|
2002-08-19 21:32:41 +00:00
|
|
|
abort();
|
|
|
|
}
|
2004-10-16 18:12:13 +00:00
|
|
|
} else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
|
2004-10-17 17:48:59 +00:00
|
|
|
Out << "((";
|
2006-12-23 06:05:41 +00:00
|
|
|
printType(Out, CPV->getType()); // sign doesn't matter
|
2008-03-02 08:14:45 +00:00
|
|
|
Out << ")/*UNDEF*/";
|
|
|
|
if (!isa<VectorType>(CPV->getType())) {
|
|
|
|
Out << "0)";
|
|
|
|
} else {
|
|
|
|
Out << "{})";
|
|
|
|
}
|
2004-10-16 18:12:13 +00:00
|
|
|
return;
|
2002-08-19 21:32:41 +00:00
|
|
|
}
|
|
|
|
|
2007-01-08 08:00:00 +00:00
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
|
|
|
|
const Type* Ty = CI->getType();
|
2007-01-11 18:21:29 +00:00
|
|
|
if (Ty == Type::Int1Ty)
|
2008-03-02 03:16:38 +00:00
|
|
|
Out << (CI->getZExtValue() ? '1' : '0');
|
|
|
|
else if (Ty == Type::Int32Ty)
|
|
|
|
Out << CI->getZExtValue() << 'u';
|
|
|
|
else if (Ty->getPrimitiveSizeInBits() > 32)
|
|
|
|
Out << CI->getZExtValue() << "ull";
|
2007-01-11 12:24:14 +00:00
|
|
|
else {
|
|
|
|
Out << "((";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, Ty, false) << ')';
|
2007-01-11 12:24:14 +00:00
|
|
|
if (CI->isMinValue(true))
|
|
|
|
Out << CI->getZExtValue() << 'u';
|
|
|
|
else
|
|
|
|
Out << CI->getSExtValue();
|
2008-03-02 03:16:38 +00:00
|
|
|
Out << ')';
|
2007-01-11 12:24:14 +00:00
|
|
|
}
|
2007-01-08 08:00:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (CPV->getType()->getTypeID()) {
|
2002-08-19 21:32:41 +00:00
|
|
|
case Type::FloatTyID:
|
2007-09-17 00:38:27 +00:00
|
|
|
case Type::DoubleTyID:
|
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
case Type::PPC_FP128TyID:
|
|
|
|
case Type::FP128TyID: {
|
2002-09-20 23:26:33 +00:00
|
|
|
ConstantFP *FPC = cast<ConstantFP>(CPV);
|
2003-05-03 03:14:35 +00:00
|
|
|
std::map<const ConstantFP*, unsigned>::iterator I = FPConstantMap.find(FPC);
|
2002-09-20 23:26:33 +00:00
|
|
|
if (I != FPConstantMap.end()) {
|
|
|
|
// Because of FP precision problems we must load from a stack allocated
|
|
|
|
// value that holds the value in hex.
|
2007-09-17 00:38:27 +00:00
|
|
|
Out << "(*(" << (FPC->getType() == Type::FloatTy ? "float" :
|
|
|
|
FPC->getType() == Type::DoubleTy ? "double" :
|
|
|
|
"long double")
|
2005-02-14 18:52:35 +00:00
|
|
|
<< "*)&FPConstant" << I->second << ')';
|
2002-09-20 23:26:33 +00:00
|
|
|
} else {
|
2007-09-17 00:38:27 +00:00
|
|
|
assert(FPC->getType() == Type::FloatTy ||
|
|
|
|
FPC->getType() == Type::DoubleTy);
|
2007-09-06 18:13:44 +00:00
|
|
|
double V = FPC->getType() == Type::FloatTy ?
|
|
|
|
FPC->getValueAPF().convertToFloat() :
|
|
|
|
FPC->getValueAPF().convertToDouble();
|
|
|
|
if (IsNAN(V)) {
|
2004-07-21 03:15:26 +00:00
|
|
|
// The value is NaN
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2007-09-06 18:13:44 +00:00
|
|
|
// FIXME the actual NaN bits should be emitted.
|
2004-08-25 19:00:42 +00:00
|
|
|
// The prefix for a quiet NaN is 0x7FF8. For a signalling NaN,
|
|
|
|
// it's 0x7ff4.
|
|
|
|
const unsigned long QuietNaN = 0x7ff8UL;
|
2006-11-02 20:25:50 +00:00
|
|
|
//const unsigned long SignalNaN = 0x7ff4UL;
|
2004-08-25 19:00:42 +00:00
|
|
|
|
|
|
|
// We need to grab the first part of the FP #
|
|
|
|
char Buffer[100];
|
|
|
|
|
2007-09-06 18:13:44 +00:00
|
|
|
uint64_t ll = DoubleToBits(V);
|
2006-05-31 22:26:11 +00:00
|
|
|
sprintf(Buffer, "0x%llx", static_cast<long long>(ll));
|
2004-08-25 19:00:42 +00:00
|
|
|
|
|
|
|
std::string Num(&Buffer[0], &Buffer[6]);
|
|
|
|
unsigned long Val = strtoul(Num.c_str(), 0, 16);
|
|
|
|
|
2004-07-21 03:15:26 +00:00
|
|
|
if (FPC->getType() == Type::FloatTy)
|
2004-08-25 19:00:42 +00:00
|
|
|
Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "F(\""
|
|
|
|
<< Buffer << "\") /*nan*/ ";
|
2004-07-21 03:15:26 +00:00
|
|
|
else
|
2004-08-25 19:00:42 +00:00
|
|
|
Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "(\""
|
|
|
|
<< Buffer << "\") /*nan*/ ";
|
2007-09-06 18:13:44 +00:00
|
|
|
} else if (IsInf(V)) {
|
2004-07-21 03:15:26 +00:00
|
|
|
// The value is Inf
|
2007-09-06 18:13:44 +00:00
|
|
|
if (V < 0) Out << '-';
|
2004-08-25 19:00:42 +00:00
|
|
|
Out << "LLVM_INF" << (FPC->getType() == Type::FloatTy ? "F" : "")
|
|
|
|
<< " /*inf*/ ";
|
2004-07-21 03:15:26 +00:00
|
|
|
} else {
|
2004-08-25 19:37:26 +00:00
|
|
|
std::string Num;
|
2006-11-05 19:26:37 +00:00
|
|
|
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
|
2004-08-25 19:37:26 +00:00
|
|
|
// Print out the constant as a floating point number.
|
|
|
|
char Buffer[100];
|
2007-09-06 18:13:44 +00:00
|
|
|
sprintf(Buffer, "%a", V);
|
2004-08-25 19:37:26 +00:00
|
|
|
Num = Buffer;
|
|
|
|
#else
|
2007-09-06 18:13:44 +00:00
|
|
|
Num = ftostr(FPC->getValueAPF());
|
2004-08-25 19:37:26 +00:00
|
|
|
#endif
|
2007-09-06 18:13:44 +00:00
|
|
|
Out << Num;
|
2004-07-21 03:15:26 +00:00
|
|
|
}
|
2002-09-20 23:26:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-08-19 21:32:41 +00:00
|
|
|
|
|
|
|
case Type::ArrayTyID:
|
2008-03-02 05:46:57 +00:00
|
|
|
if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
|
2008-03-02 03:18:46 +00:00
|
|
|
printConstantArray(CA);
|
2008-03-02 03:16:38 +00:00
|
|
|
} else {
|
|
|
|
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
|
2004-02-15 05:54:27 +00:00
|
|
|
const ArrayType *AT = cast<ArrayType>(CPV->getType());
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '{';
|
2004-02-15 05:54:27 +00:00
|
|
|
if (AT->getNumElements()) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ' ';
|
2004-02-15 05:54:27 +00:00
|
|
|
Constant *CZ = Constant::getNullValue(AT->getElementType());
|
|
|
|
printConstant(CZ);
|
|
|
|
for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
printConstant(CZ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << " }";
|
|
|
|
}
|
2002-08-19 21:32:41 +00:00
|
|
|
break;
|
|
|
|
|
2007-02-15 02:26:10 +00:00
|
|
|
case Type::VectorTyID:
|
2008-03-02 03:29:50 +00:00
|
|
|
// Use C99 compound expression literal initializer syntax.
|
|
|
|
Out << "(";
|
|
|
|
printType(Out, CPV->getType());
|
|
|
|
Out << ")";
|
2008-03-02 05:46:57 +00:00
|
|
|
if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
|
2008-03-02 03:16:38 +00:00
|
|
|
printConstantVector(CV);
|
|
|
|
} else {
|
|
|
|
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
|
|
|
|
const VectorType *VT = cast<VectorType>(CPV->getType());
|
|
|
|
Out << "{ ";
|
|
|
|
Constant *CZ = Constant::getNullValue(VT->getElementType());
|
|
|
|
printConstant(CZ);
|
2008-03-02 03:18:46 +00:00
|
|
|
for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) {
|
2008-03-02 03:16:38 +00:00
|
|
|
Out << ", ";
|
2006-01-20 20:43:57 +00:00
|
|
|
printConstant(CZ);
|
|
|
|
}
|
|
|
|
Out << " }";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-02-15 05:54:27 +00:00
|
|
|
case Type::StructTyID:
|
2004-10-16 18:12:13 +00:00
|
|
|
if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) {
|
2004-02-15 05:54:27 +00:00
|
|
|
const StructType *ST = cast<StructType>(CPV->getType());
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '{';
|
2004-02-15 05:54:27 +00:00
|
|
|
if (ST->getNumElements()) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ' ';
|
2004-02-15 05:54:27 +00:00
|
|
|
printConstant(Constant::getNullValue(ST->getElementType(0)));
|
|
|
|
for (unsigned i = 1, e = ST->getNumElements(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
printConstant(Constant::getNullValue(ST->getElementType(i)));
|
|
|
|
}
|
2002-08-19 21:32:41 +00:00
|
|
|
}
|
2004-02-15 05:54:27 +00:00
|
|
|
Out << " }";
|
|
|
|
} else {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '{';
|
2004-02-15 05:54:27 +00:00
|
|
|
if (CPV->getNumOperands()) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ' ';
|
2004-02-15 05:54:27 +00:00
|
|
|
printConstant(cast<Constant>(CPV->getOperand(0)));
|
|
|
|
for (unsigned i = 1, e = CPV->getNumOperands(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
printConstant(cast<Constant>(CPV->getOperand(i)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << " }";
|
2002-08-19 21:32:41 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::PointerTyID:
|
2002-05-09 20:53:56 +00:00
|
|
|
if (isa<ConstantPointerNull>(CPV)) {
|
2003-06-02 03:10:53 +00:00
|
|
|
Out << "((";
|
2006-12-23 06:05:41 +00:00
|
|
|
printType(Out, CPV->getType()); // sign doesn't matter
|
2003-06-02 03:10:53 +00:00
|
|
|
Out << ")/*NULL*/0)";
|
2002-08-19 21:32:41 +00:00
|
|
|
break;
|
2004-07-18 00:44:37 +00:00
|
|
|
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) {
|
|
|
|
writeOperand(GV);
|
2002-08-19 21:32:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// FALL THROUGH
|
|
|
|
default:
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Unknown constant type: " << *CPV << "\n";
|
2002-08-19 21:32:41 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-26 06:15:43 +00:00
|
|
|
// Some constant expressions need to be casted back to the original types
|
|
|
|
// because their operands were casted to the expected type. This function takes
|
|
|
|
// care of detecting that case and printing the cast for the ConstantExpr.
|
|
|
|
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
|
2006-11-08 06:47:33 +00:00
|
|
|
bool NeedsExplicitCast = false;
|
2006-11-27 01:05:10 +00:00
|
|
|
const Type *Ty = CE->getOperand(0)->getType();
|
2006-12-23 06:05:41 +00:00
|
|
|
bool TypeIsSigned = false;
|
2006-10-26 06:15:43 +00:00
|
|
|
switch (CE->getOpcode()) {
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::UDiv: NeedsExplicitCast = true; break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::AShr:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::SRem:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break;
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::SExt:
|
2006-12-23 06:05:41 +00:00
|
|
|
Ty = CE->getType();
|
|
|
|
NeedsExplicitCast = true;
|
|
|
|
TypeIsSigned = true;
|
|
|
|
break;
|
|
|
|
case Instruction::ZExt:
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::FPTrunc:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::FPToUI:
|
|
|
|
case Instruction::FPToSI:
|
|
|
|
case Instruction::PtrToInt:
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::BitCast:
|
|
|
|
Ty = CE->getType();
|
|
|
|
NeedsExplicitCast = true;
|
|
|
|
break;
|
2006-10-26 06:15:43 +00:00
|
|
|
default: break;
|
|
|
|
}
|
2006-11-08 06:47:33 +00:00
|
|
|
if (NeedsExplicitCast) {
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << "((";
|
2007-01-15 02:27:26 +00:00
|
|
|
if (Ty->isInteger() && Ty != Type::Int1Ty)
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, Ty, TypeIsSigned);
|
2006-12-23 06:05:41 +00:00
|
|
|
else
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, Ty); // not integer, sign doesn't matter
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << ")(";
|
|
|
|
}
|
2006-11-08 06:47:33 +00:00
|
|
|
return NeedsExplicitCast;
|
2006-10-26 06:15:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print a constant assuming that it is the operand for a given Opcode. The
|
|
|
|
// opcodes that care about sign need to cast their operands to the expected
|
|
|
|
// type before the operation proceeds. This function does the casting.
|
|
|
|
void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
|
|
|
|
|
|
|
// Extract the operand's type, we'll need it.
|
|
|
|
const Type* OpTy = CPV->getType();
|
|
|
|
|
|
|
|
// Indicate whether to do the cast or not.
|
|
|
|
bool shouldCast = false;
|
2006-12-23 06:05:41 +00:00
|
|
|
bool typeIsSigned = false;
|
2006-10-26 06:15:43 +00:00
|
|
|
|
|
|
|
// Based on the Opcode for which this Constant is being written, determine
|
|
|
|
// the new type to which the operand should be casted by setting the value
|
2006-11-27 01:05:10 +00:00
|
|
|
// of OpTy. If we change OpTy, also set shouldCast to true so it gets
|
|
|
|
// casted below.
|
2006-10-26 06:15:43 +00:00
|
|
|
switch (Opcode) {
|
|
|
|
default:
|
|
|
|
// for most instructions, it doesn't matter
|
|
|
|
break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::UDiv:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
2006-12-23 06:05:41 +00:00
|
|
|
shouldCast = true;
|
2006-10-26 06:15:43 +00:00
|
|
|
break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::AShr:
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::SDiv:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::SRem:
|
2006-12-23 06:05:41 +00:00
|
|
|
shouldCast = true;
|
|
|
|
typeIsSigned = true;
|
2006-10-26 06:15:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-11-27 01:05:10 +00:00
|
|
|
// Write out the casted constant if we should, otherwise just write the
|
2006-10-26 06:15:43 +00:00
|
|
|
// operand.
|
|
|
|
if (shouldCast) {
|
|
|
|
Out << "((";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, OpTy, typeIsSigned);
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << ")";
|
|
|
|
printConstant(CPV);
|
|
|
|
Out << ")";
|
|
|
|
} else
|
2006-12-23 06:05:41 +00:00
|
|
|
printConstant(CPV);
|
2006-10-26 06:15:43 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 22:45:08 +00:00
|
|
|
std::string CWriter::GetValueName(const Value *Operand) {
|
|
|
|
std::string Name;
|
|
|
|
|
|
|
|
if (!isa<GlobalValue>(Operand) && Operand->getName() != "") {
|
|
|
|
std::string VarName;
|
|
|
|
|
|
|
|
Name = Operand->getName();
|
|
|
|
VarName.reserve(Name.capacity());
|
|
|
|
|
|
|
|
for (std::string::iterator I = Name.begin(), E = Name.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
char ch = *I;
|
|
|
|
|
|
|
|
if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
2008-02-28 20:26:04 +00:00
|
|
|
(ch >= '0' && ch <= '9') || ch == '_')) {
|
|
|
|
char buffer[5];
|
|
|
|
sprintf(buffer, "_%x_", ch);
|
|
|
|
VarName += buffer;
|
|
|
|
} else
|
2007-02-23 22:45:08 +00:00
|
|
|
VarName += ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
Name = "llvm_cbe_" + VarName;
|
|
|
|
} else {
|
|
|
|
Name = Mang->getValueName(Operand);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Name;
|
|
|
|
}
|
|
|
|
|
2002-08-19 21:32:41 +00:00
|
|
|
void CWriter::writeOperandInternal(Value *Operand) {
|
2002-08-19 23:09:46 +00:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(Operand))
|
2003-06-17 04:39:14 +00:00
|
|
|
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
|
2002-08-19 23:09:46 +00:00
|
|
|
// Should we inline this instruction to build a tree?
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2002-08-19 23:09:46 +00:00
|
|
|
visit(*I);
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2002-08-19 23:09:46 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-07-18 00:44:37 +00:00
|
|
|
Constant* CPV = dyn_cast<Constant>(Operand);
|
2007-02-23 22:45:08 +00:00
|
|
|
|
|
|
|
if (CPV && !isa<GlobalValue>(CPV))
|
2005-04-20 16:05:03 +00:00
|
|
|
printConstant(CPV);
|
2007-02-23 22:45:08 +00:00
|
|
|
else
|
|
|
|
Out << GetValueName(Operand);
|
2002-05-09 21:18:38 +00:00
|
|
|
}
|
|
|
|
|
2006-11-27 23:50:49 +00:00
|
|
|
void CWriter::writeOperandRaw(Value *Operand) {
|
|
|
|
Constant* CPV = dyn_cast<Constant>(Operand);
|
|
|
|
if (CPV && !isa<GlobalValue>(CPV)) {
|
|
|
|
printConstant(CPV);
|
|
|
|
} else {
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << GetValueName(Operand);
|
2006-11-27 23:50:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::writeOperand(Value *Operand) {
|
2008-03-02 08:07:24 +00:00
|
|
|
bool isAddressImplicit = isAddressExposed(Operand);
|
|
|
|
if (isAddressImplicit)
|
2006-11-27 01:05:10 +00:00
|
|
|
Out << "(&"; // Global variables are referenced as their addresses by llvm
|
2002-05-09 21:18:38 +00:00
|
|
|
|
|
|
|
writeOperandInternal(Operand);
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2008-03-02 08:07:24 +00:00
|
|
|
if (isAddressImplicit)
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 06:15:43 +00:00
|
|
|
// Some instructions need to have their result value casted back to the
|
|
|
|
// original types because their operands were casted to the expected type.
|
|
|
|
// This function takes care of detecting that case and printing the cast
|
|
|
|
// for the Instruction.
|
|
|
|
bool CWriter::writeInstructionCast(const Instruction &I) {
|
2006-11-27 01:05:10 +00:00
|
|
|
const Type *Ty = I.getOperand(0)->getType();
|
2006-10-26 06:15:43 +00:00
|
|
|
switch (I.getOpcode()) {
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::UDiv:
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << "((";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, Ty, false);
|
2006-12-23 06:05:41 +00:00
|
|
|
Out << ")(";
|
|
|
|
return true;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::AShr:
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::SRem:
|
2006-11-27 01:05:10 +00:00
|
|
|
case Instruction::SDiv:
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << "((";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, Ty, true);
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << ")(";
|
2006-12-23 06:05:41 +00:00
|
|
|
return true;
|
|
|
|
default: break;
|
2006-10-26 06:15:43 +00:00
|
|
|
}
|
2006-12-23 06:05:41 +00:00
|
|
|
return false;
|
2006-10-26 06:15:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write the operand with a cast to another type based on the Opcode being used.
|
|
|
|
// This will be used in cases where an instruction has specific type
|
|
|
|
// requirements (usually signedness) for its operands.
|
|
|
|
void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
|
|
|
|
|
|
|
// Extract the operand's type, we'll need it.
|
|
|
|
const Type* OpTy = Operand->getType();
|
|
|
|
|
|
|
|
// Indicate whether to do the cast or not.
|
|
|
|
bool shouldCast = false;
|
|
|
|
|
2006-12-23 06:05:41 +00:00
|
|
|
// Indicate whether the cast should be to a signed type or not.
|
|
|
|
bool castIsSigned = false;
|
|
|
|
|
2006-10-26 06:15:43 +00:00
|
|
|
// Based on the Opcode for which this Operand is being written, determine
|
|
|
|
// the new type to which the operand should be casted by setting the value
|
|
|
|
// of OpTy. If we change OpTy, also set shouldCast to true.
|
|
|
|
switch (Opcode) {
|
|
|
|
default:
|
|
|
|
// for most instructions, it doesn't matter
|
|
|
|
break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::UDiv:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::URem: // Cast to unsigned first
|
|
|
|
shouldCast = true;
|
|
|
|
castIsSigned = false;
|
2006-10-26 06:15:43 +00:00
|
|
|
break;
|
2007-09-22 20:16:48 +00:00
|
|
|
case Instruction::GetElementPtr:
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::AShr:
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::SDiv:
|
2006-12-23 06:05:41 +00:00
|
|
|
case Instruction::SRem: // Cast to signed first
|
|
|
|
shouldCast = true;
|
|
|
|
castIsSigned = true;
|
2006-10-26 06:15:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write out the casted operand if we should, otherwise just write the
|
|
|
|
// operand.
|
|
|
|
if (shouldCast) {
|
|
|
|
Out << "((";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
printSimpleType(Out, OpTy, castIsSigned);
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << ")";
|
2007-05-03 02:57:13 +00:00
|
|
|
writeOperand(Operand);
|
2006-10-26 06:15:43 +00:00
|
|
|
Out << ")";
|
|
|
|
} else
|
|
|
|
writeOperand(Operand);
|
2006-12-23 06:05:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write the operand with a cast to another type based on the icmp predicate
|
|
|
|
// being used.
|
2007-09-15 06:51:03 +00:00
|
|
|
void CWriter::writeOperandWithCast(Value* Operand, const ICmpInst &Cmp) {
|
|
|
|
// This has to do a cast to ensure the operand has the right signedness.
|
|
|
|
// Also, if the operand is a pointer, we make sure to cast to an integer when
|
|
|
|
// doing the comparison both for signedness and so that the C compiler doesn't
|
|
|
|
// optimize things like "p < NULL" to false (p may contain an integer value
|
|
|
|
// f.e.).
|
|
|
|
bool shouldCast = Cmp.isRelational();
|
2006-12-23 06:05:41 +00:00
|
|
|
|
|
|
|
// Write out the casted operand if we should, otherwise just write the
|
|
|
|
// operand.
|
2007-09-15 06:51:03 +00:00
|
|
|
if (!shouldCast) {
|
2006-12-23 06:05:41 +00:00
|
|
|
writeOperand(Operand);
|
2007-09-15 06:51:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should this be a signed comparison? If so, convert to signed.
|
|
|
|
bool castIsSigned = Cmp.isSignedPredicate();
|
|
|
|
|
|
|
|
// If the operand was a pointer, convert to a large integer type.
|
|
|
|
const Type* OpTy = Operand->getType();
|
|
|
|
if (isa<PointerType>(OpTy))
|
|
|
|
OpTy = TD->getIntPtrType();
|
|
|
|
|
|
|
|
Out << "((";
|
|
|
|
printSimpleType(Out, OpTy, castIsSigned);
|
|
|
|
Out << ")";
|
|
|
|
writeOperand(Operand);
|
|
|
|
Out << ")";
|
2006-10-26 06:15:43 +00:00
|
|
|
}
|
|
|
|
|
2003-06-28 17:15:12 +00:00
|
|
|
// generateCompilerSpecificCode - This is where we add conditional compilation
|
|
|
|
// directives to cater to specific compilers as need be.
|
|
|
|
//
|
2003-11-16 22:06:14 +00:00
|
|
|
static void generateCompilerSpecificCode(std::ostream& Out) {
|
2006-03-07 22:58:23 +00:00
|
|
|
// Alloca is hard to get, and we don't want to include stdlib.h here.
|
2003-06-28 17:15:12 +00:00
|
|
|
Out << "/* get a declaration for alloca */\n"
|
2006-06-02 18:54:01 +00:00
|
|
|
<< "#if defined(__CYGWIN__) || defined(__MINGW32__)\n"
|
2007-04-17 09:20:00 +00:00
|
|
|
<< "#define alloca(x) __builtin_alloca((x))\n"
|
|
|
|
<< "#define _alloca(x) __builtin_alloca((x))\n"
|
2005-01-23 04:32:47 +00:00
|
|
|
<< "#elif defined(__APPLE__)\n"
|
2003-02-12 20:45:00 +00:00
|
|
|
<< "extern void *__builtin_alloca(unsigned long);\n"
|
|
|
|
<< "#define alloca(x) __builtin_alloca(x)\n"
|
2006-12-10 23:12:42 +00:00
|
|
|
<< "#define longjmp _longjmp\n"
|
|
|
|
<< "#define setjmp _setjmp\n"
|
2004-12-10 05:44:45 +00:00
|
|
|
<< "#elif defined(__sun__)\n"
|
|
|
|
<< "#if defined(__sparcv9)\n"
|
|
|
|
<< "extern void *__builtin_alloca(unsigned long);\n"
|
|
|
|
<< "#else\n"
|
|
|
|
<< "extern void *__builtin_alloca(unsigned int);\n"
|
|
|
|
<< "#endif\n"
|
|
|
|
<< "#define alloca(x) __builtin_alloca(x)\n"
|
2008-01-12 06:46:09 +00:00
|
|
|
<< "#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)\n"
|
2004-10-06 04:21:52 +00:00
|
|
|
<< "#define alloca(x) __builtin_alloca(x)\n"
|
2007-03-28 23:08:37 +00:00
|
|
|
<< "#elif defined(_MSC_VER)\n"
|
2007-03-29 17:42:21 +00:00
|
|
|
<< "#define inline _inline\n"
|
2007-03-28 23:08:37 +00:00
|
|
|
<< "#define alloca(x) _alloca(x)\n"
|
|
|
|
<< "#else\n"
|
2003-02-12 20:45:00 +00:00
|
|
|
<< "#include <alloca.h>\n"
|
|
|
|
<< "#endif\n\n";
|
2003-06-28 17:15:12 +00:00
|
|
|
|
|
|
|
// We output GCC specific attributes to preserve 'linkonce'ness on globals.
|
|
|
|
// If we aren't being compiled with GCC, just drop these attributes.
|
2003-06-28 17:53:05 +00:00
|
|
|
Out << "#ifndef __GNUC__ /* Can only support \"linkonce\" vars with GCC */\n"
|
2003-06-28 17:15:12 +00:00
|
|
|
<< "#define __attribute__(X)\n"
|
2003-12-11 00:24:36 +00:00
|
|
|
<< "#endif\n\n";
|
|
|
|
|
|
|
|
// On Mac OS X, "external weak" is spelled "__attribute__((weak_import))".
|
|
|
|
Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n"
|
|
|
|
<< "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n"
|
|
|
|
<< "#elif defined(__GNUC__)\n"
|
|
|
|
<< "#define __EXTERNAL_WEAK__ __attribute__((weak))\n"
|
|
|
|
<< "#else\n"
|
|
|
|
<< "#define __EXTERNAL_WEAK__\n"
|
|
|
|
<< "#endif\n\n";
|
|
|
|
|
|
|
|
// For now, turn off the weak linkage attribute on Mac OS X. (See above.)
|
|
|
|
Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n"
|
|
|
|
<< "#define __ATTRIBUTE_WEAK__\n"
|
|
|
|
<< "#elif defined(__GNUC__)\n"
|
|
|
|
<< "#define __ATTRIBUTE_WEAK__ __attribute__((weak))\n"
|
|
|
|
<< "#else\n"
|
|
|
|
<< "#define __ATTRIBUTE_WEAK__\n"
|
|
|
|
<< "#endif\n\n";
|
2004-07-21 03:15:26 +00:00
|
|
|
|
2007-01-12 19:20:47 +00:00
|
|
|
// Add hidden visibility support. FIXME: APPLE_CC?
|
|
|
|
Out << "#if defined(__GNUC__)\n"
|
|
|
|
<< "#define __HIDDEN__ __attribute__((visibility(\"hidden\")))\n"
|
|
|
|
<< "#endif\n\n";
|
|
|
|
|
2004-07-21 03:15:26 +00:00
|
|
|
// Define NaN and Inf as GCC builtins if using GCC, as 0 otherwise
|
|
|
|
// From the GCC documentation:
|
2005-04-20 16:05:03 +00:00
|
|
|
//
|
2004-07-21 03:15:26 +00:00
|
|
|
// double __builtin_nan (const char *str)
|
|
|
|
//
|
|
|
|
// This is an implementation of the ISO C99 function nan.
|
|
|
|
//
|
|
|
|
// Since ISO C99 defines this function in terms of strtod, which we do
|
|
|
|
// not implement, a description of the parsing is in order. The string is
|
|
|
|
// parsed as by strtol; that is, the base is recognized by leading 0 or
|
|
|
|
// 0x prefixes. The number parsed is placed in the significand such that
|
|
|
|
// the least significant bit of the number is at the least significant
|
|
|
|
// bit of the significand. The number is truncated to fit the significand
|
|
|
|
// field provided. The significand is forced to be a quiet NaN.
|
|
|
|
//
|
|
|
|
// This function, if given a string literal, is evaluated early enough
|
|
|
|
// that it is considered a compile-time constant.
|
|
|
|
//
|
|
|
|
// float __builtin_nanf (const char *str)
|
|
|
|
//
|
|
|
|
// Similar to __builtin_nan, except the return type is float.
|
|
|
|
//
|
|
|
|
// double __builtin_inf (void)
|
|
|
|
//
|
|
|
|
// Similar to __builtin_huge_val, except a warning is generated if the
|
|
|
|
// target floating-point format does not support infinities. This
|
|
|
|
// function is suitable for implementing the ISO C99 macro INFINITY.
|
|
|
|
//
|
|
|
|
// float __builtin_inff (void)
|
|
|
|
//
|
|
|
|
// Similar to __builtin_inf, except the return type is float.
|
|
|
|
Out << "#ifdef __GNUC__\n"
|
2004-08-25 19:00:42 +00:00
|
|
|
<< "#define LLVM_NAN(NanStr) __builtin_nan(NanStr) /* Double */\n"
|
|
|
|
<< "#define LLVM_NANF(NanStr) __builtin_nanf(NanStr) /* Float */\n"
|
|
|
|
<< "#define LLVM_NANS(NanStr) __builtin_nans(NanStr) /* Double */\n"
|
|
|
|
<< "#define LLVM_NANSF(NanStr) __builtin_nansf(NanStr) /* Float */\n"
|
|
|
|
<< "#define LLVM_INF __builtin_inf() /* Double */\n"
|
|
|
|
<< "#define LLVM_INFF __builtin_inff() /* Float */\n"
|
2006-02-13 22:22:42 +00:00
|
|
|
<< "#define LLVM_PREFETCH(addr,rw,locality) "
|
|
|
|
"__builtin_prefetch(addr,rw,locality)\n"
|
2006-03-07 22:58:23 +00:00
|
|
|
<< "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n"
|
|
|
|
<< "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n"
|
2006-07-28 20:58:47 +00:00
|
|
|
<< "#define LLVM_ASM __asm__\n"
|
2004-07-21 03:15:26 +00:00
|
|
|
<< "#else\n"
|
2004-08-25 19:00:42 +00:00
|
|
|
<< "#define LLVM_NAN(NanStr) ((double)0.0) /* Double */\n"
|
|
|
|
<< "#define LLVM_NANF(NanStr) 0.0F /* Float */\n"
|
|
|
|
<< "#define LLVM_NANS(NanStr) ((double)0.0) /* Double */\n"
|
|
|
|
<< "#define LLVM_NANSF(NanStr) 0.0F /* Float */\n"
|
|
|
|
<< "#define LLVM_INF ((double)0.0) /* Double */\n"
|
|
|
|
<< "#define LLVM_INFF 0.0F /* Float */\n"
|
2005-05-06 06:58:42 +00:00
|
|
|
<< "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n"
|
2006-03-07 22:58:23 +00:00
|
|
|
<< "#define __ATTRIBUTE_CTOR__\n"
|
|
|
|
<< "#define __ATTRIBUTE_DTOR__\n"
|
2006-07-28 20:58:47 +00:00
|
|
|
<< "#define LLVM_ASM(X)\n"
|
2005-05-06 06:58:42 +00:00
|
|
|
<< "#endif\n\n";
|
2007-05-13 22:19:27 +00:00
|
|
|
|
|
|
|
Out << "#if __GNUC__ < 4 /* Old GCC's, or compilers not GCC */ \n"
|
|
|
|
<< "#define __builtin_stack_save() 0 /* not implemented */\n"
|
|
|
|
<< "#define __builtin_stack_restore(X) /* noop */\n"
|
|
|
|
<< "#endif\n\n";
|
2005-05-06 06:58:42 +00:00
|
|
|
|
|
|
|
// Output target-specific code that should be inserted into main.
|
|
|
|
Out << "#define CODE_FOR_MAIN() /* Any target-specific code for main()*/\n";
|
2003-02-12 20:45:00 +00:00
|
|
|
}
|
|
|
|
|
2006-03-07 22:58:23 +00:00
|
|
|
/// FindStaticTors - Given a static ctor/dtor list, unpack its contents into
|
|
|
|
/// the StaticTors set.
|
|
|
|
static void FindStaticTors(GlobalVariable *GV, std::set<Function*> &StaticTors){
|
|
|
|
ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
|
|
|
|
if (!InitList) return;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
|
|
|
|
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
|
|
|
|
if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
|
|
|
|
|
|
|
|
if (CS->getOperand(1)->isNullValue())
|
|
|
|
return; // Found a null terminator, exit printing.
|
|
|
|
Constant *FP = CS->getOperand(1);
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
|
2006-11-27 01:05:10 +00:00
|
|
|
if (CE->isCast())
|
2006-03-07 22:58:23 +00:00
|
|
|
FP = CE->getOperand(0);
|
|
|
|
if (Function *F = dyn_cast<Function>(FP))
|
|
|
|
StaticTors.insert(F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum SpecialGlobalClass {
|
|
|
|
NotSpecial = 0,
|
|
|
|
GlobalCtors, GlobalDtors,
|
|
|
|
NotPrinted
|
|
|
|
};
|
|
|
|
|
|
|
|
/// getGlobalVariableClass - If this is a global that is specially recognized
|
|
|
|
/// by LLVM, return a code that indicates how we should handle it.
|
|
|
|
static SpecialGlobalClass getGlobalVariableClass(const GlobalVariable *GV) {
|
|
|
|
// If this is a global ctors/dtors list, handle it now.
|
|
|
|
if (GV->hasAppendingLinkage() && GV->use_empty()) {
|
|
|
|
if (GV->getName() == "llvm.global_ctors")
|
|
|
|
return GlobalCtors;
|
|
|
|
else if (GV->getName() == "llvm.global_dtors")
|
|
|
|
return GlobalDtors;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, it it is other metadata, don't print it. This catches things
|
|
|
|
// like debug information.
|
|
|
|
if (GV->getSection() == "llvm.metadata")
|
|
|
|
return NotPrinted;
|
|
|
|
|
|
|
|
return NotSpecial;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
bool CWriter::doInitialization(Module &M) {
|
|
|
|
// Initialize
|
|
|
|
TheModule = &M;
|
2004-05-09 04:30:20 +00:00
|
|
|
|
2007-01-29 17:51:02 +00:00
|
|
|
TD = new TargetData(&M);
|
|
|
|
IL = new IntrinsicLowering(*TD);
|
|
|
|
IL->AddPrototypes(M);
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
// Ensure that all structure types have names...
|
|
|
|
Mang = new Mangler(M);
|
2005-11-10 21:39:29 +00:00
|
|
|
Mang->markCharUnacceptable('.');
|
2003-11-16 22:06:14 +00:00
|
|
|
|
2006-03-07 22:58:23 +00:00
|
|
|
// Keep track of which functions are static ctors/dtors so they can have
|
|
|
|
// an attribute added to their prototypes.
|
|
|
|
std::set<Function*> StaticCtors, StaticDtors;
|
|
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
switch (getGlobalVariableClass(I)) {
|
|
|
|
default: break;
|
|
|
|
case GlobalCtors:
|
|
|
|
FindStaticTors(I, StaticCtors);
|
|
|
|
break;
|
|
|
|
case GlobalDtors:
|
|
|
|
FindStaticTors(I, StaticDtors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-09 02:28:59 +00:00
|
|
|
// get declaration for alloca
|
2003-02-12 20:45:00 +00:00
|
|
|
Out << "/* Provide Declarations */\n";
|
2003-11-16 22:06:14 +00:00
|
|
|
Out << "#include <stdarg.h>\n"; // Varargs support
|
|
|
|
Out << "#include <setjmp.h>\n"; // Unwind support
|
2003-06-28 17:15:12 +00:00
|
|
|
generateCompilerSpecificCode(Out);
|
2003-11-16 22:06:14 +00:00
|
|
|
|
2003-06-02 03:10:53 +00:00
|
|
|
// Provide a definition for `bool' if not compiling with a C++ compiler.
|
|
|
|
Out << "\n"
|
2002-08-25 20:00:08 +00:00
|
|
|
<< "#ifndef __cplusplus\ntypedef unsigned char bool;\n#endif\n"
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2002-09-20 23:26:33 +00:00
|
|
|
<< "\n\n/* Support for floating point constants */\n"
|
|
|
|
<< "typedef unsigned long long ConstantDoubleTy;\n"
|
2002-11-07 19:43:59 +00:00
|
|
|
<< "typedef unsigned int ConstantFloatTy;\n"
|
2007-09-17 00:38:27 +00:00
|
|
|
<< "typedef struct { unsigned long long f1; unsigned short f2; "
|
|
|
|
"unsigned short pad[3]; } ConstantFP80Ty;\n"
|
2007-10-15 01:05:37 +00:00
|
|
|
// This is used for both kinds of 128-bit long double; meaning differs.
|
2007-09-17 00:38:27 +00:00
|
|
|
<< "typedef struct { unsigned long long f1; unsigned long long f2; }"
|
|
|
|
" ConstantFP128Ty;\n"
|
2002-08-19 21:48:40 +00:00
|
|
|
<< "\n\n/* Global Declarations */\n";
|
|
|
|
|
|
|
|
// First output all the declarations for the program, because C requires
|
|
|
|
// Functions & globals to be declared before they are used.
|
|
|
|
//
|
2002-05-09 02:28:59 +00:00
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
// Loop over the symbol table, emitting all named constants...
|
2007-01-06 07:24:44 +00:00
|
|
|
printModuleTypes(M.getTypeSymbolTable());
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2002-08-19 21:48:40 +00:00
|
|
|
// Global variable declarations...
|
2005-03-15 04:54:21 +00:00
|
|
|
if (!M.global_empty()) {
|
2002-09-17 11:50:38 +00:00
|
|
|
Out << "\n/* External Global Variable Declarations */\n";
|
2006-02-13 22:22:42 +00:00
|
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E; ++I) {
|
2007-04-12 18:42:08 +00:00
|
|
|
|
|
|
|
if (I->hasExternalLinkage() || I->hasExternalWeakLinkage())
|
2002-09-17 11:50:38 +00:00
|
|
|
Out << "extern ";
|
2007-04-12 18:42:08 +00:00
|
|
|
else if (I->hasDLLImportLinkage())
|
2006-09-14 18:23:27 +00:00
|
|
|
Out << "__declspec(dllimport) ";
|
2007-04-12 18:42:08 +00:00
|
|
|
else
|
|
|
|
continue; // Internal Global
|
|
|
|
|
|
|
|
// Thread Local Storage
|
|
|
|
if (I->isThreadLocal())
|
|
|
|
Out << "__thread ";
|
|
|
|
|
|
|
|
printType(Out, I->getType()->getElementType(), false, GetValueName(I));
|
|
|
|
|
|
|
|
if (I->hasExternalWeakLinkage())
|
|
|
|
Out << " __EXTERNAL_WEAK__";
|
|
|
|
Out << ";\n";
|
2002-08-19 21:48:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function declarations
|
2006-03-07 22:58:23 +00:00
|
|
|
Out << "\n/* Function Declarations */\n";
|
2005-08-23 20:22:50 +00:00
|
|
|
Out << "double fmod(double, double);\n"; // Support for FP rem
|
|
|
|
Out << "float fmodf(float, float);\n";
|
2007-09-17 00:38:27 +00:00
|
|
|
Out << "long double fmodl(long double, long double);\n";
|
2005-08-23 20:22:50 +00:00
|
|
|
|
2006-03-07 22:58:23 +00:00
|
|
|
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
|
|
|
|
// Don't print declarations for intrinsic functions.
|
2007-12-03 20:06:50 +00:00
|
|
|
if (!I->isIntrinsic() && I->getName() != "setjmp" &&
|
2006-10-22 09:58:21 +00:00
|
|
|
I->getName() != "longjmp" && I->getName() != "_setjmp") {
|
2006-12-01 00:25:12 +00:00
|
|
|
if (I->hasExternalWeakLinkage())
|
|
|
|
Out << "extern ";
|
2006-03-07 22:58:23 +00:00
|
|
|
printFunctionSignature(I, true);
|
|
|
|
if (I->hasWeakLinkage() || I->hasLinkOnceLinkage())
|
|
|
|
Out << " __ATTRIBUTE_WEAK__";
|
2006-12-01 00:25:12 +00:00
|
|
|
if (I->hasExternalWeakLinkage())
|
|
|
|
Out << " __EXTERNAL_WEAK__";
|
2006-03-07 22:58:23 +00:00
|
|
|
if (StaticCtors.count(I))
|
|
|
|
Out << " __ATTRIBUTE_CTOR__";
|
|
|
|
if (StaticDtors.count(I))
|
|
|
|
Out << " __ATTRIBUTE_DTOR__";
|
2007-01-12 19:20:47 +00:00
|
|
|
if (I->hasHiddenVisibility())
|
|
|
|
Out << " __HIDDEN__";
|
2006-07-28 20:58:47 +00:00
|
|
|
|
|
|
|
if (I->hasName() && I->getName()[0] == 1)
|
|
|
|
Out << " LLVM_ASM(\"" << I->getName().c_str()+1 << "\")";
|
|
|
|
|
2006-03-07 22:58:23 +00:00
|
|
|
Out << ";\n";
|
2002-08-20 16:55:48 +00:00
|
|
|
}
|
2002-08-19 21:48:40 +00:00
|
|
|
}
|
2002-05-09 15:18:52 +00:00
|
|
|
|
2003-06-25 04:52:09 +00:00
|
|
|
// Output the global variable declarations
|
2005-03-15 04:54:21 +00:00
|
|
|
if (!M.global_empty()) {
|
2003-06-25 04:52:09 +00:00
|
|
|
Out << "\n\n/* Global Variable Declarations */\n";
|
2006-02-13 22:22:42 +00:00
|
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E; ++I)
|
2007-01-30 20:08:39 +00:00
|
|
|
if (!I->isDeclaration()) {
|
2006-03-07 22:58:23 +00:00
|
|
|
// Ignore special globals, such as debug info.
|
|
|
|
if (getGlobalVariableClass(I))
|
|
|
|
continue;
|
2007-04-12 18:42:08 +00:00
|
|
|
|
2004-12-03 17:19:10 +00:00
|
|
|
if (I->hasInternalLinkage())
|
|
|
|
Out << "static ";
|
|
|
|
else
|
|
|
|
Out << "extern ";
|
2007-04-12 18:42:08 +00:00
|
|
|
|
|
|
|
// Thread Local Storage
|
|
|
|
if (I->isThreadLocal())
|
|
|
|
Out << "__thread ";
|
|
|
|
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, I->getType()->getElementType(), false,
|
2007-02-23 22:45:08 +00:00
|
|
|
GetValueName(I));
|
2003-11-03 17:32:38 +00:00
|
|
|
|
|
|
|
if (I->hasLinkOnceLinkage())
|
|
|
|
Out << " __attribute__((common))";
|
|
|
|
else if (I->hasWeakLinkage())
|
2003-12-11 00:24:36 +00:00
|
|
|
Out << " __ATTRIBUTE_WEAK__";
|
2006-12-01 00:25:12 +00:00
|
|
|
else if (I->hasExternalWeakLinkage())
|
|
|
|
Out << " __EXTERNAL_WEAK__";
|
2007-01-12 19:20:47 +00:00
|
|
|
if (I->hasHiddenVisibility())
|
|
|
|
Out << " __HIDDEN__";
|
2002-10-28 19:05:12 +00:00
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-17 11:50:38 +00:00
|
|
|
// Output the global variable definitions and contents...
|
2005-03-15 04:54:21 +00:00
|
|
|
if (!M.global_empty()) {
|
2002-09-17 11:50:38 +00:00
|
|
|
Out << "\n\n/* Global Variable Definitions and Initialization */\n";
|
2006-02-13 22:22:42 +00:00
|
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E; ++I)
|
2007-01-30 20:08:39 +00:00
|
|
|
if (!I->isDeclaration()) {
|
2006-03-07 22:58:23 +00:00
|
|
|
// Ignore special globals, such as debug info.
|
|
|
|
if (getGlobalVariableClass(I))
|
|
|
|
continue;
|
2007-04-12 18:42:08 +00:00
|
|
|
|
2002-10-16 20:08:47 +00:00
|
|
|
if (I->hasInternalLinkage())
|
|
|
|
Out << "static ";
|
2006-09-14 18:23:27 +00:00
|
|
|
else if (I->hasDLLImportLinkage())
|
|
|
|
Out << "__declspec(dllimport) ";
|
|
|
|
else if (I->hasDLLExportLinkage())
|
|
|
|
Out << "__declspec(dllexport) ";
|
2007-04-12 18:42:08 +00:00
|
|
|
|
|
|
|
// Thread Local Storage
|
|
|
|
if (I->isThreadLocal())
|
|
|
|
Out << "__thread ";
|
|
|
|
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, I->getType()->getElementType(), false,
|
2007-02-23 22:45:08 +00:00
|
|
|
GetValueName(I));
|
2003-06-28 17:08:36 +00:00
|
|
|
if (I->hasLinkOnceLinkage())
|
|
|
|
Out << " __attribute__((common))";
|
2003-10-16 18:29:00 +00:00
|
|
|
else if (I->hasWeakLinkage())
|
2003-12-11 00:24:36 +00:00
|
|
|
Out << " __ATTRIBUTE_WEAK__";
|
2003-11-03 17:35:00 +00:00
|
|
|
|
2007-01-12 19:20:47 +00:00
|
|
|
if (I->hasHiddenVisibility())
|
|
|
|
Out << " __HIDDEN__";
|
|
|
|
|
2003-11-03 17:35:00 +00:00
|
|
|
// If the initializer is not null, emit the initializer. If it is null,
|
|
|
|
// we try to avoid emitting large amounts of zeros. The problem with
|
|
|
|
// this, however, occurs when the variable has weak linkage. In this
|
|
|
|
// case, the assembler will complain about the variable being both weak
|
|
|
|
// and common, so we disable this optimization.
|
2004-02-20 05:49:22 +00:00
|
|
|
if (!I->getInitializer()->isNullValue()) {
|
2003-06-06 07:10:24 +00:00
|
|
|
Out << " = " ;
|
|
|
|
writeOperand(I->getInitializer());
|
2004-02-20 05:49:22 +00:00
|
|
|
} else if (I->hasWeakLinkage()) {
|
|
|
|
// We have to specify an initializer, but it doesn't have to be
|
|
|
|
// complete. If the value is an aggregate, print out { 0 }, and let
|
|
|
|
// the compiler figure out the rest of the zeros.
|
|
|
|
Out << " = " ;
|
|
|
|
if (isa<StructType>(I->getInitializer()->getType()) ||
|
2006-01-20 20:43:57 +00:00
|
|
|
isa<ArrayType>(I->getInitializer()->getType()) ||
|
2007-02-15 02:26:10 +00:00
|
|
|
isa<VectorType>(I->getInitializer()->getType())) {
|
2004-02-20 05:49:22 +00:00
|
|
|
Out << "{ 0 }";
|
|
|
|
} else {
|
|
|
|
// Just print it out normally.
|
|
|
|
writeOperand(I->getInitializer());
|
|
|
|
}
|
2003-06-06 07:10:24 +00:00
|
|
|
}
|
2002-10-16 20:08:47 +00:00
|
|
|
Out << ";\n";
|
2002-08-19 21:48:40 +00:00
|
|
|
}
|
2002-05-09 15:18:52 +00:00
|
|
|
}
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
if (!M.empty())
|
2002-08-19 21:48:40 +00:00
|
|
|
Out << "\n\n/* Function Bodies */\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
|
|
|
|
// Emit some helper functions for dealing with FCMP instruction's
|
|
|
|
// predicates
|
|
|
|
Out << "static inline int llvm_fcmp_ord(double X, double Y) { ";
|
|
|
|
Out << "return X == X && Y == Y; }\n";
|
|
|
|
Out << "static inline int llvm_fcmp_uno(double X, double Y) { ";
|
|
|
|
Out << "return X != X || Y != Y; }\n";
|
|
|
|
Out << "static inline int llvm_fcmp_ueq(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X == Y || llvm_fcmp_uno(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_une(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X != Y; }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_ult(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X < Y || llvm_fcmp_uno(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_ugt(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X > Y || llvm_fcmp_uno(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_ule(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X <= Y || llvm_fcmp_uno(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_uge(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X >= Y || llvm_fcmp_uno(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_oeq(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X == Y ; }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_one(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X != Y && llvm_fcmp_ord(X, Y); }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_olt(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X < Y ; }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_ogt(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X > Y ; }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_ole(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X <= Y ; }\n";
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << "static inline int llvm_fcmp_oge(double X, double Y) { ";
|
2007-01-08 08:00:00 +00:00
|
|
|
Out << "return X >= Y ; }\n";
|
2004-02-13 23:00:29 +00:00
|
|
|
return false;
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
|
2003-10-12 04:36:29 +00:00
|
|
|
/// Output all floating point constants that cannot be printed accurately...
|
2004-05-09 06:20:51 +00:00
|
|
|
void CWriter::printFloatingPointConstants(Function &F) {
|
2003-10-12 04:36:29 +00:00
|
|
|
// Scan the module for floating point constants. If any FP constant is used
|
|
|
|
// in the function, we want to redirect it here so that we do not depend on
|
|
|
|
// the precision of the printed form, unless the printed form preserves
|
|
|
|
// precision.
|
|
|
|
//
|
2004-05-09 06:20:51 +00:00
|
|
|
static unsigned FPCounter = 0;
|
|
|
|
for (constant_iterator I = constant_begin(&F), E = constant_end(&F);
|
|
|
|
I != E; ++I)
|
|
|
|
if (const ConstantFP *FPC = dyn_cast<ConstantFP>(*I))
|
|
|
|
if (!isFPCSafeToPrint(FPC) && // Do not put in FPConstantMap if safe.
|
|
|
|
!FPConstantMap.count(FPC)) {
|
|
|
|
FPConstantMap[FPC] = FPCounter; // Number the FP constants
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
if (FPC->getType() == Type::DoubleTy) {
|
2007-09-06 18:13:44 +00:00
|
|
|
double Val = FPC->getValueAPF().convertToDouble();
|
2007-09-12 03:30:33 +00:00
|
|
|
uint64_t i = FPC->getValueAPF().convertToAPInt().getZExtValue();
|
2004-05-09 06:20:51 +00:00
|
|
|
Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
|
2007-09-11 18:32:33 +00:00
|
|
|
<< " = 0x" << std::hex << i << std::dec
|
2004-05-09 06:20:51 +00:00
|
|
|
<< "ULL; /* " << Val << " */\n";
|
|
|
|
} else if (FPC->getType() == Type::FloatTy) {
|
2007-09-06 18:13:44 +00:00
|
|
|
float Val = FPC->getValueAPF().convertToFloat();
|
2007-09-12 03:30:33 +00:00
|
|
|
uint32_t i = (uint32_t)FPC->getValueAPF().convertToAPInt().
|
|
|
|
getZExtValue();
|
2004-05-09 06:20:51 +00:00
|
|
|
Out << "static const ConstantFloatTy FPConstant" << FPCounter++
|
2007-09-11 18:32:33 +00:00
|
|
|
<< " = 0x" << std::hex << i << std::dec
|
2004-05-09 06:20:51 +00:00
|
|
|
<< "U; /* " << Val << " */\n";
|
2007-09-17 00:38:27 +00:00
|
|
|
} else if (FPC->getType() == Type::X86_FP80Ty) {
|
2007-09-26 23:20:33 +00:00
|
|
|
// api needed to prevent premature destruction
|
|
|
|
APInt api = FPC->getValueAPF().convertToAPInt();
|
|
|
|
const uint64_t *p = api.getRawData();
|
2007-09-17 00:38:27 +00:00
|
|
|
Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
|
|
|
|
<< " = { 0x" << std::hex
|
|
|
|
<< ((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16)
|
|
|
|
<< ", 0x" << (uint16_t)(p[0] >> 48) << ",0,0,0"
|
|
|
|
<< "}; /* Long double constant */\n" << std::dec;
|
2007-10-15 01:05:37 +00:00
|
|
|
} else if (FPC->getType() == Type::PPC_FP128Ty) {
|
|
|
|
APInt api = FPC->getValueAPF().convertToAPInt();
|
|
|
|
const uint64_t *p = api.getRawData();
|
|
|
|
Out << "static const ConstantFP128Ty FPConstant" << FPCounter++
|
|
|
|
<< " = { 0x" << std::hex
|
|
|
|
<< p[0] << ", 0x" << p[1]
|
|
|
|
<< "}; /* Long double constant */\n" << std::dec;
|
|
|
|
|
2004-05-09 06:20:51 +00:00
|
|
|
} else
|
|
|
|
assert(0 && "Unknown float type!");
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '\n';
|
2004-05-09 06:20:51 +00:00
|
|
|
}
|
2003-10-12 04:36:29 +00:00
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2002-09-20 15:12:13 +00:00
|
|
|
/// printSymbolTable - Run through symbol table looking for type names. If a
|
2006-01-20 20:43:57 +00:00
|
|
|
/// type name is found, emit its declaration...
|
2002-09-20 14:56:54 +00:00
|
|
|
///
|
2007-01-06 07:24:44 +00:00
|
|
|
void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
|
2006-12-11 20:39:15 +00:00
|
|
|
Out << "/* Helper union for bitcasts */\n";
|
|
|
|
Out << "typedef union {\n";
|
2006-12-31 05:55:36 +00:00
|
|
|
Out << " unsigned int Int32;\n";
|
|
|
|
Out << " unsigned long long Int64;\n";
|
2006-12-12 00:11:08 +00:00
|
|
|
Out << " float Float;\n";
|
|
|
|
Out << " double Double;\n";
|
2006-12-11 20:39:15 +00:00
|
|
|
Out << "} llvmBitCastUnion;\n";
|
|
|
|
|
2005-03-06 02:28:23 +00:00
|
|
|
// We are only interested in the type plane of the symbol table.
|
2007-01-06 07:24:44 +00:00
|
|
|
TypeSymbolTable::const_iterator I = TST.begin();
|
|
|
|
TypeSymbolTable::const_iterator End = TST.end();
|
2005-03-06 02:28:23 +00:00
|
|
|
|
|
|
|
// If there are no type names, exit early.
|
|
|
|
if (I == End) return;
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2002-09-20 15:18:30 +00:00
|
|
|
// Print out forward declarations for structure types before anything else!
|
|
|
|
Out << "/* Structure forward decls */\n";
|
2007-01-16 18:02:45 +00:00
|
|
|
for (; I != End; ++I) {
|
|
|
|
std::string Name = "struct l_" + Mang->makeNameProper(I->first);
|
|
|
|
Out << Name << ";\n";
|
|
|
|
TypeNames.insert(std::make_pair(I->second, Name));
|
|
|
|
}
|
2002-09-20 15:18:30 +00:00
|
|
|
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '\n';
|
2002-09-20 15:18:30 +00:00
|
|
|
|
2007-01-16 07:22:23 +00:00
|
|
|
// Now we can print out typedefs. Above, we guaranteed that this can only be
|
2007-01-16 18:02:45 +00:00
|
|
|
// for struct or opaque types.
|
2002-09-20 15:18:30 +00:00
|
|
|
Out << "/* Typedefs */\n";
|
2007-01-06 07:24:44 +00:00
|
|
|
for (I = TST.begin(); I != End; ++I) {
|
2005-11-10 18:53:25 +00:00
|
|
|
std::string Name = "l_" + Mang->makeNameProper(I->first);
|
2004-05-09 06:20:51 +00:00
|
|
|
Out << "typedef ";
|
2007-01-16 18:02:45 +00:00
|
|
|
printType(Out, I->second, false, Name);
|
2004-05-09 06:20:51 +00:00
|
|
|
Out << ";\n";
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '\n';
|
2002-05-09 14:40:11 +00:00
|
|
|
|
2002-09-20 15:05:40 +00:00
|
|
|
// Keep track of which structures have been printed so far...
|
|
|
|
std::set<const StructType *> StructPrinted;
|
|
|
|
|
2002-09-14 21:36:24 +00:00
|
|
|
// Loop over all structures then push them into the stack so they are
|
|
|
|
// printed in the correct order.
|
2002-09-20 15:12:13 +00:00
|
|
|
//
|
2002-09-20 15:18:30 +00:00
|
|
|
Out << "/* Structure contents */\n";
|
2007-01-06 07:24:44 +00:00
|
|
|
for (I = TST.begin(); I != End; ++I)
|
2002-09-20 15:12:13 +00:00
|
|
|
if (const StructType *STy = dyn_cast<StructType>(I->second))
|
2003-11-02 01:29:27 +00:00
|
|
|
// Only print out used types!
|
2004-05-09 06:20:51 +00:00
|
|
|
printContainedStructs(STy, StructPrinted);
|
2002-09-14 21:36:24 +00:00
|
|
|
}
|
2002-05-09 20:14:10 +00:00
|
|
|
|
2002-09-14 21:36:24 +00:00
|
|
|
// Push the struct onto the stack and recursively push all structs
|
|
|
|
// this one depends on.
|
2006-01-20 20:43:57 +00:00
|
|
|
//
|
2007-02-15 03:39:18 +00:00
|
|
|
// TODO: Make this work properly with vector types
|
2006-01-20 20:43:57 +00:00
|
|
|
//
|
2002-09-20 15:05:40 +00:00
|
|
|
void CWriter::printContainedStructs(const Type *Ty,
|
|
|
|
std::set<const StructType*> &StructPrinted){
|
2006-01-20 18:57:03 +00:00
|
|
|
// Don't walk through pointers.
|
2007-01-15 02:27:26 +00:00
|
|
|
if (isa<PointerType>(Ty) || Ty->isPrimitiveType() || Ty->isInteger()) return;
|
2006-01-20 18:57:03 +00:00
|
|
|
|
|
|
|
// Print all contained types first.
|
|
|
|
for (Type::subtype_iterator I = Ty->subtype_begin(),
|
|
|
|
E = Ty->subtype_end(); I != E; ++I)
|
|
|
|
printContainedStructs(*I, StructPrinted);
|
|
|
|
|
2003-07-09 17:33:50 +00:00
|
|
|
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
|
2006-01-20 18:57:03 +00:00
|
|
|
// Check to see if we have already printed this struct.
|
|
|
|
if (StructPrinted.insert(STy).second) {
|
|
|
|
// Print structure type out.
|
2005-04-20 16:05:03 +00:00
|
|
|
std::string Name = TypeNames[STy];
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, STy, false, Name, true);
|
2002-09-20 15:18:30 +00:00
|
|
|
Out << ";\n\n";
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
2002-09-14 21:36:24 +00:00
|
|
|
}
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2002-08-20 16:55:48 +00:00
|
|
|
void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
|
2007-01-28 13:31:35 +00:00
|
|
|
/// isStructReturn - Should this function actually return a struct by-value?
|
2008-03-03 21:46:28 +00:00
|
|
|
bool isStructReturn = F->hasStructRetAttr();
|
2006-05-23 23:39:48 +00:00
|
|
|
|
2003-06-25 04:52:09 +00:00
|
|
|
if (F->hasInternalLinkage()) Out << "static ";
|
2006-09-14 18:23:27 +00:00
|
|
|
if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) ";
|
|
|
|
if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) ";
|
2006-09-17 20:25:45 +00:00
|
|
|
switch (F->getCallingConv()) {
|
|
|
|
case CallingConv::X86_StdCall:
|
|
|
|
Out << "__stdcall ";
|
|
|
|
break;
|
|
|
|
case CallingConv::X86_FastCall:
|
|
|
|
Out << "__fastcall ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
// Loop over the arguments, printing them...
|
2002-05-09 02:28:59 +00:00
|
|
|
const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
|
2007-11-27 13:23:08 +00:00
|
|
|
const ParamAttrsList *PAL = F->getParamAttrs();
|
2005-04-20 16:05:03 +00:00
|
|
|
|
|
|
|
std::stringstream FunctionInnards;
|
|
|
|
|
2002-11-18 20:55:50 +00:00
|
|
|
// Print out the name...
|
2007-02-23 22:45:08 +00:00
|
|
|
FunctionInnards << GetValueName(F) << '(';
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
bool PrintedArg = false;
|
2007-01-30 20:08:39 +00:00
|
|
|
if (!F->isDeclaration()) {
|
2005-03-15 04:54:21 +00:00
|
|
|
if (!F->arg_empty()) {
|
2006-05-23 23:39:48 +00:00
|
|
|
Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
|
2008-01-11 03:07:46 +00:00
|
|
|
unsigned Idx = 1;
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
// If this is a struct-return function, don't print the hidden
|
|
|
|
// struct-return argument.
|
2007-01-28 13:31:35 +00:00
|
|
|
if (isStructReturn) {
|
2006-05-23 23:39:48 +00:00
|
|
|
assert(I != E && "Invalid struct return function!");
|
|
|
|
++I;
|
2008-01-11 03:07:46 +00:00
|
|
|
++Idx;
|
2006-05-23 23:39:48 +00:00
|
|
|
}
|
|
|
|
|
2003-05-03 03:14:35 +00:00
|
|
|
std::string ArgName;
|
2006-05-23 23:39:48 +00:00
|
|
|
for (; I != E; ++I) {
|
|
|
|
if (PrintedArg) FunctionInnards << ", ";
|
2002-08-20 16:55:48 +00:00
|
|
|
if (I->hasName() || !Prototype)
|
2007-02-23 22:45:08 +00:00
|
|
|
ArgName = GetValueName(I);
|
2005-04-20 16:05:03 +00:00
|
|
|
else
|
2002-08-20 16:55:48 +00:00
|
|
|
ArgName = "";
|
2008-01-11 03:07:46 +00:00
|
|
|
const Type *ArgTy = I->getType();
|
2008-01-11 09:12:49 +00:00
|
|
|
if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
|
|
|
|
ArgTy = cast<PointerType>(ArgTy)->getElementType();
|
2008-03-02 08:07:24 +00:00
|
|
|
ByValParams.insert(I);
|
2008-01-11 09:12:49 +00:00
|
|
|
}
|
2008-01-11 03:07:46 +00:00
|
|
|
printType(FunctionInnards, ArgTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt),
|
2007-01-07 03:24:48 +00:00
|
|
|
ArgName);
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedArg = true;
|
2007-01-07 03:24:48 +00:00
|
|
|
++Idx;
|
2002-05-09 15:18:52 +00:00
|
|
|
}
|
|
|
|
}
|
2002-05-08 18:09:58 +00:00
|
|
|
} else {
|
2006-05-23 23:39:48 +00:00
|
|
|
// Loop over the arguments, printing them.
|
|
|
|
FunctionType::param_iterator I = FT->param_begin(), E = FT->param_end();
|
2008-01-11 23:10:11 +00:00
|
|
|
unsigned Idx = 1;
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
// If this is a struct-return function, don't print the hidden
|
|
|
|
// struct-return argument.
|
2007-01-28 13:31:35 +00:00
|
|
|
if (isStructReturn) {
|
2006-05-23 23:39:48 +00:00
|
|
|
assert(I != E && "Invalid struct return function!");
|
|
|
|
++I;
|
2008-01-11 23:10:11 +00:00
|
|
|
++Idx;
|
2006-05-23 23:39:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (; I != E; ++I) {
|
|
|
|
if (PrintedArg) FunctionInnards << ", ";
|
2008-01-11 23:10:11 +00:00
|
|
|
const Type *ArgTy = *I;
|
|
|
|
if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
|
|
|
|
assert(isa<PointerType>(ArgTy));
|
|
|
|
ArgTy = cast<PointerType>(ArgTy)->getElementType();
|
|
|
|
}
|
|
|
|
printType(FunctionInnards, ArgTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt));
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedArg = true;
|
2007-01-07 03:24:48 +00:00
|
|
|
++Idx;
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-20 22:32:30 +00:00
|
|
|
// Finish printing arguments... if this is a vararg function, print the ...,
|
|
|
|
// unless there are no known types, in which case, we just emit ().
|
|
|
|
//
|
2006-05-23 23:39:48 +00:00
|
|
|
if (FT->isVarArg() && PrintedArg) {
|
|
|
|
if (PrintedArg) FunctionInnards << ", ";
|
2003-06-25 04:52:09 +00:00
|
|
|
FunctionInnards << "..."; // Output varargs portion of signature!
|
2006-05-23 23:39:48 +00:00
|
|
|
} else if (!FT->isVarArg() && !PrintedArg) {
|
2003-11-26 00:09:17 +00:00
|
|
|
FunctionInnards << "void"; // ret() -> ret(void) in C.
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
2005-02-14 18:52:35 +00:00
|
|
|
FunctionInnards << ')';
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
// Get the return tpe for the function.
|
|
|
|
const Type *RetTy;
|
2007-01-28 13:31:35 +00:00
|
|
|
if (!isStructReturn)
|
2006-05-23 23:39:48 +00:00
|
|
|
RetTy = F->getReturnType();
|
|
|
|
else {
|
|
|
|
// If this is a struct-return function, print the struct-return type.
|
|
|
|
RetTy = cast<PointerType>(FT->getParamType(0))->getElementType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print out the return type and the signature built above.
|
2007-01-09 06:38:06 +00:00
|
|
|
printType(Out, RetTy,
|
2007-11-27 13:23:08 +00:00
|
|
|
/*isSigned=*/ PAL && PAL->paramHasAttr(0, ParamAttr::SExt),
|
2007-01-07 03:24:48 +00:00
|
|
|
FunctionInnards.str());
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2006-12-17 20:24:50 +00:00
|
|
|
static inline bool isFPIntBitCast(const Instruction &I) {
|
|
|
|
if (!isa<BitCastInst>(I))
|
|
|
|
return false;
|
|
|
|
const Type *SrcTy = I.getOperand(0)->getType();
|
|
|
|
const Type *DstTy = I.getType();
|
2007-01-15 02:27:26 +00:00
|
|
|
return (SrcTy->isFloatingPoint() && DstTy->isInteger()) ||
|
|
|
|
(DstTy->isFloatingPoint() && SrcTy->isInteger());
|
2006-12-17 20:24:50 +00:00
|
|
|
}
|
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
void CWriter::printFunction(Function &F) {
|
2007-01-28 13:31:35 +00:00
|
|
|
/// isStructReturn - Should this function actually return a struct by-value?
|
2008-03-03 21:46:28 +00:00
|
|
|
bool isStructReturn = F.hasStructRetAttr();
|
2007-01-28 13:31:35 +00:00
|
|
|
|
2004-02-13 23:00:29 +00:00
|
|
|
printFunctionSignature(&F, false);
|
2002-05-09 15:49:41 +00:00
|
|
|
Out << " {\n";
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
// If this is a struct return function, handle the result with magic.
|
2007-01-28 13:31:35 +00:00
|
|
|
if (isStructReturn) {
|
2006-05-23 23:39:48 +00:00
|
|
|
const Type *StructTy =
|
|
|
|
cast<PointerType>(F.arg_begin()->getType())->getElementType();
|
|
|
|
Out << " ";
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, StructTy, false, "StructReturn");
|
2006-05-23 23:39:48 +00:00
|
|
|
Out << "; /* Struct return temporary */\n";
|
|
|
|
|
|
|
|
Out << " ";
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, F.arg_begin()->getType(), false,
|
2007-02-23 22:45:08 +00:00
|
|
|
GetValueName(F.arg_begin()));
|
2006-05-23 23:39:48 +00:00
|
|
|
Out << " = &StructReturn;\n";
|
|
|
|
}
|
2002-05-09 15:49:41 +00:00
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
bool PrintedVar = false;
|
|
|
|
|
2002-05-09 20:39:03 +00:00
|
|
|
// print local variable information for the function
|
2006-12-17 18:50:51 +00:00
|
|
|
for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
|
2004-04-27 15:13:33 +00:00
|
|
|
if (const AllocaInst *AI = isDirectAlloca(&*I)) {
|
2003-06-17 04:39:14 +00:00
|
|
|
Out << " ";
|
2007-02-23 22:45:08 +00:00
|
|
|
printType(Out, AI->getAllocatedType(), false, GetValueName(AI));
|
2005-01-31 06:19:57 +00:00
|
|
|
Out << "; /* Address-exposed local */\n";
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedVar = true;
|
2004-04-27 15:13:33 +00:00
|
|
|
} else if (I->getType() != Type::VoidTy && !isInlinableInst(*I)) {
|
2002-05-09 02:28:59 +00:00
|
|
|
Out << " ";
|
2007-02-23 22:45:08 +00:00
|
|
|
printType(Out, I->getType(), false, GetValueName(&*I));
|
2002-05-09 02:28:59 +00:00
|
|
|
Out << ";\n";
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2003-05-03 07:11:00 +00:00
|
|
|
if (isa<PHINode>(*I)) { // Print out PHI node temporaries as well...
|
|
|
|
Out << " ";
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, I->getType(), false,
|
2007-02-23 22:45:08 +00:00
|
|
|
GetValueName(&*I)+"__PHI_TEMPORARY");
|
2003-05-03 07:11:00 +00:00
|
|
|
Out << ";\n";
|
|
|
|
}
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedVar = true;
|
2006-12-17 18:50:51 +00:00
|
|
|
}
|
|
|
|
// We need a temporary for the BitCast to use so it can pluck a value out
|
2006-12-23 06:05:41 +00:00
|
|
|
// of a union to do the BitCast. This is separate from the need for a
|
2006-12-17 18:50:51 +00:00
|
|
|
// variable to hold the result of the BitCast.
|
2006-12-17 20:24:50 +00:00
|
|
|
if (isFPIntBitCast(*I)) {
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << " llvmBitCastUnion " << GetValueName(&*I)
|
2006-12-11 20:39:15 +00:00
|
|
|
<< "__BITCAST_TEMPORARY;\n";
|
2006-12-17 18:50:51 +00:00
|
|
|
PrintedVar = true;
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
2006-12-17 18:50:51 +00:00
|
|
|
}
|
2002-09-20 23:26:33 +00:00
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
if (PrintedVar)
|
|
|
|
Out << '\n';
|
2002-09-20 23:26:33 +00:00
|
|
|
|
2004-12-13 21:52:52 +00:00
|
|
|
if (F.hasExternalLinkage() && F.getName() == "main")
|
2005-05-06 06:58:42 +00:00
|
|
|
Out << " CODE_FOR_MAIN();\n";
|
2004-12-13 21:52:52 +00:00
|
|
|
|
2002-05-09 02:28:59 +00:00
|
|
|
// print the basic blocks
|
2004-02-13 23:00:29 +00:00
|
|
|
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
|
2004-05-09 20:41:32 +00:00
|
|
|
if (Loop *L = LI->getLoopFor(BB)) {
|
|
|
|
if (L->getHeader() == BB && L->getParentLoop() == 0)
|
|
|
|
printLoop(L);
|
|
|
|
} else {
|
|
|
|
printBasicBlock(BB);
|
|
|
|
}
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
Out << "}\n\n";
|
|
|
|
}
|
2002-05-09 15:49:41 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
void CWriter::printLoop(Loop *L) {
|
|
|
|
Out << " do { /* Syntactic loop '" << L->getHeader()->getName()
|
|
|
|
<< "' to make GCC happy */\n";
|
|
|
|
for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) {
|
|
|
|
BasicBlock *BB = L->getBlocks()[i];
|
|
|
|
Loop *BBLoop = LI->getLoopFor(BB);
|
|
|
|
if (BBLoop == L)
|
|
|
|
printBasicBlock(BB);
|
|
|
|
else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L)
|
2005-04-20 16:05:03 +00:00
|
|
|
printLoop(BBLoop);
|
2004-05-09 20:41:32 +00:00
|
|
|
}
|
|
|
|
Out << " } while (1); /* end of syntactic loop '"
|
|
|
|
<< L->getHeader()->getName() << "' */\n";
|
|
|
|
}
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
void CWriter::printBasicBlock(BasicBlock *BB) {
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
// Don't print the label for the basic block if there are no uses, or if
|
|
|
|
// the only terminator use is the predecessor basic block's terminator.
|
|
|
|
// We have to scan the use list because PHI nodes use basic blocks too but
|
|
|
|
// do not require a label to be generated.
|
|
|
|
//
|
|
|
|
bool NeedsLabel = false;
|
|
|
|
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
|
|
|
|
if (isGotoCodeNecessary(*PI, BB)) {
|
|
|
|
NeedsLabel = true;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2007-02-23 22:45:08 +00:00
|
|
|
if (NeedsLabel) Out << GetValueName(BB) << ":\n";
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
// Output all of the instructions in the basic block...
|
|
|
|
for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E;
|
|
|
|
++II) {
|
|
|
|
if (!isInlinableInst(*II) && !isDirectAlloca(II)) {
|
2006-11-27 23:50:49 +00:00
|
|
|
if (II->getType() != Type::VoidTy && !isInlineAsm(*II))
|
2004-05-09 20:41:32 +00:00
|
|
|
outputLValue(II);
|
|
|
|
else
|
|
|
|
Out << " ";
|
|
|
|
visit(*II);
|
|
|
|
Out << ";\n";
|
2002-05-09 21:18:38 +00:00
|
|
|
}
|
2002-05-09 15:49:41 +00:00
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
// Don't emit prefix or suffix for the terminator...
|
|
|
|
visit(*BB->getTerminator());
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
// Specific Instruction type classes... note that all of the casts are
|
2003-08-18 14:43:39 +00:00
|
|
|
// necessary because we use the instruction classes as opaque types...
|
2002-05-09 20:53:56 +00:00
|
|
|
//
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitReturnInst(ReturnInst &I) {
|
2006-05-23 23:39:48 +00:00
|
|
|
// If this is a struct return function, return the temporary struct.
|
2008-03-03 21:46:28 +00:00
|
|
|
bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr();
|
2007-01-28 13:31:35 +00:00
|
|
|
|
|
|
|
if (isStructReturn) {
|
2006-05-23 23:39:48 +00:00
|
|
|
Out << " return StructReturn;\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
// Don't output a void return if this is the last basic block in the function
|
2005-04-20 16:05:03 +00:00
|
|
|
if (I.getNumOperands() == 0 &&
|
2002-06-25 15:57:03 +00:00
|
|
|
&*--I.getParent()->getParent()->end() == I.getParent() &&
|
|
|
|
!I.getParent()->size() == 1) {
|
2002-05-09 20:53:56 +00:00
|
|
|
return;
|
2002-05-21 18:05:19 +00:00
|
|
|
}
|
2002-05-09 03:50:42 +00:00
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " return";
|
2002-06-25 15:57:03 +00:00
|
|
|
if (I.getNumOperands()) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ' ';
|
2002-06-25 15:57:03 +00:00
|
|
|
writeOperand(I.getOperand(0));
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
|
2003-04-22 20:19:52 +00:00
|
|
|
void CWriter::visitSwitchInst(SwitchInst &SI) {
|
2004-05-09 03:42:48 +00:00
|
|
|
|
2003-04-22 20:19:52 +00:00
|
|
|
Out << " switch (";
|
|
|
|
writeOperand(SI.getOperand(0));
|
2003-04-23 19:15:13 +00:00
|
|
|
Out << ") {\n default:\n";
|
2004-10-25 18:30:09 +00:00
|
|
|
printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2);
|
2003-04-23 19:15:13 +00:00
|
|
|
printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2);
|
2003-04-22 20:19:52 +00:00
|
|
|
Out << ";\n";
|
|
|
|
for (unsigned i = 2, e = SI.getNumOperands(); i != e; i += 2) {
|
|
|
|
Out << " case ";
|
|
|
|
writeOperand(SI.getOperand(i));
|
|
|
|
Out << ":\n";
|
|
|
|
BasicBlock *Succ = cast<BasicBlock>(SI.getOperand(i+1));
|
2004-10-25 18:30:09 +00:00
|
|
|
printPHICopiesForSuccessor (SI.getParent(), Succ, 2);
|
2003-04-22 20:19:52 +00:00
|
|
|
printBranchToBlock(SI.getParent(), Succ, 2);
|
2005-03-19 17:35:11 +00:00
|
|
|
if (Function::iterator(Succ) == next(Function::iterator(SI.getParent())))
|
2003-04-22 20:19:52 +00:00
|
|
|
Out << " break;\n";
|
|
|
|
}
|
|
|
|
Out << " }\n";
|
|
|
|
}
|
|
|
|
|
2004-10-16 18:12:13 +00:00
|
|
|
void CWriter::visitUnreachableInst(UnreachableInst &I) {
|
2004-10-17 23:49:11 +00:00
|
|
|
Out << " /*UNREACHABLE*/;\n";
|
2004-10-16 18:12:13 +00:00
|
|
|
}
|
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
bool CWriter::isGotoCodeNecessary(BasicBlock *From, BasicBlock *To) {
|
|
|
|
/// FIXME: This should be reenabled, but loop reordering safe!!
|
|
|
|
return true;
|
2003-06-28 17:53:05 +00:00
|
|
|
|
2005-03-18 16:12:37 +00:00
|
|
|
if (next(Function::iterator(From)) != Function::iterator(To))
|
|
|
|
return true; // Not the direct successor, we need a goto.
|
2003-04-22 20:19:52 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
//isa<SwitchInst>(From->getTerminator())
|
2003-09-08 18:54:55 +00:00
|
|
|
|
2004-05-09 20:41:32 +00:00
|
|
|
if (LI->getLoopFor(From) != LI->getLoopFor(To))
|
|
|
|
return true;
|
2002-05-09 20:53:56 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-10-20 14:38:39 +00:00
|
|
|
void CWriter::printPHICopiesForSuccessor (BasicBlock *CurBlock,
|
2005-04-20 16:05:03 +00:00
|
|
|
BasicBlock *Successor,
|
2004-10-20 14:38:39 +00:00
|
|
|
unsigned Indent) {
|
|
|
|
for (BasicBlock::iterator I = Successor->begin(); isa<PHINode>(I); ++I) {
|
|
|
|
PHINode *PN = cast<PHINode>(I);
|
|
|
|
// Now we have to do the printing.
|
|
|
|
Value *IV = PN->getIncomingValueForBlock(CurBlock);
|
|
|
|
if (!isa<UndefValue>(IV)) {
|
|
|
|
Out << std::string(Indent, ' ');
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << " " << GetValueName(I) << "__PHI_TEMPORARY = ";
|
2004-10-20 14:38:39 +00:00
|
|
|
writeOperand(IV);
|
|
|
|
Out << "; /* for PHI node */\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ,
|
2003-06-28 17:53:05 +00:00
|
|
|
unsigned Indent) {
|
2004-05-09 20:41:32 +00:00
|
|
|
if (isGotoCodeNecessary(CurBB, Succ)) {
|
2003-05-03 03:14:35 +00:00
|
|
|
Out << std::string(Indent, ' ') << " goto ";
|
2002-05-09 20:53:56 +00:00
|
|
|
writeOperand(Succ);
|
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-11 22:34:13 +00:00
|
|
|
// Branch instruction printing - Avoid printing out a branch to a basic block
|
|
|
|
// that immediately succeeds the current one.
|
2002-05-09 20:53:56 +00:00
|
|
|
//
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitBranchInst(BranchInst &I) {
|
2004-05-09 03:42:48 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
if (I.isConditional()) {
|
2003-10-12 08:12:58 +00:00
|
|
|
if (isGotoCodeNecessary(I.getParent(), I.getSuccessor(0))) {
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " if (";
|
2002-06-25 15:57:03 +00:00
|
|
|
writeOperand(I.getCondition());
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << ") {\n";
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2004-10-20 14:38:39 +00:00
|
|
|
printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(0), 2);
|
2002-06-25 15:57:03 +00:00
|
|
|
printBranchToBlock(I.getParent(), I.getSuccessor(0), 2);
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2003-10-12 08:12:58 +00:00
|
|
|
if (isGotoCodeNecessary(I.getParent(), I.getSuccessor(1))) {
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " } else {\n";
|
2004-10-20 14:38:39 +00:00
|
|
|
printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(1), 2);
|
2002-06-25 15:57:03 +00:00
|
|
|
printBranchToBlock(I.getParent(), I.getSuccessor(1), 2);
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
} else {
|
2003-08-18 14:43:39 +00:00
|
|
|
// First goto not necessary, assume second one is...
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " if (!";
|
2002-06-25 15:57:03 +00:00
|
|
|
writeOperand(I.getCondition());
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << ") {\n";
|
|
|
|
|
2004-10-20 14:38:39 +00:00
|
|
|
printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(1), 2);
|
2002-06-25 15:57:03 +00:00
|
|
|
printBranchToBlock(I.getParent(), I.getSuccessor(1), 2);
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Out << " }\n";
|
2002-05-09 03:50:42 +00:00
|
|
|
} else {
|
2004-10-20 14:38:39 +00:00
|
|
|
printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(0), 0);
|
2002-06-25 15:57:03 +00:00
|
|
|
printBranchToBlock(I.getParent(), I.getSuccessor(0), 0);
|
2002-05-09 02:28:59 +00:00
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << "\n";
|
|
|
|
}
|
2002-05-09 03:50:42 +00:00
|
|
|
|
2003-05-03 07:11:00 +00:00
|
|
|
// PHI nodes get copied into temporary values at the end of predecessor basic
|
|
|
|
// blocks. We now need to copy these temporary values into the REAL value for
|
|
|
|
// the PHI.
|
|
|
|
void CWriter::visitPHINode(PHINode &I) {
|
|
|
|
writeOperand(&I);
|
|
|
|
Out << "__PHI_TEMPORARY";
|
|
|
|
}
|
|
|
|
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitBinaryOperator(Instruction &I) {
|
2002-05-09 20:53:56 +00:00
|
|
|
// binary instructions, shift instructions, setCond instructions.
|
2003-04-23 19:09:22 +00:00
|
|
|
assert(!isa<PointerType>(I.getType()));
|
2003-06-23 20:00:51 +00:00
|
|
|
|
|
|
|
// We must cast the results of binary operations which might be promoted.
|
|
|
|
bool needsCast = false;
|
2006-12-31 05:55:36 +00:00
|
|
|
if ((I.getType() == Type::Int8Ty) || (I.getType() == Type::Int16Ty)
|
2003-06-25 03:05:33 +00:00
|
|
|
|| (I.getType() == Type::FloatTy)) {
|
2003-06-23 20:00:51 +00:00
|
|
|
needsCast = true;
|
|
|
|
Out << "((";
|
2007-01-09 17:09:09 +00:00
|
|
|
printType(Out, I.getType(), false);
|
2003-06-23 20:00:51 +00:00
|
|
|
Out << ")(";
|
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2005-03-03 21:12:04 +00:00
|
|
|
// If this is a negation operation, print it out as such. For FP, we don't
|
|
|
|
// want to print "-0.0 - X".
|
|
|
|
if (BinaryOperator::isNeg(&I)) {
|
2005-07-14 19:41:16 +00:00
|
|
|
Out << "-(";
|
2005-03-03 21:12:04 +00:00
|
|
|
writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
|
2005-07-14 19:41:16 +00:00
|
|
|
Out << ")";
|
2006-11-02 01:53:59 +00:00
|
|
|
} else if (I.getOpcode() == Instruction::FRem) {
|
2005-08-23 20:22:50 +00:00
|
|
|
// Output a call to fmod/fmodf instead of emitting a%b
|
|
|
|
if (I.getType() == Type::FloatTy)
|
|
|
|
Out << "fmodf(";
|
2007-09-17 00:38:27 +00:00
|
|
|
else if (I.getType() == Type::DoubleTy)
|
2005-08-23 20:22:50 +00:00
|
|
|
Out << "fmod(";
|
2007-09-17 00:38:27 +00:00
|
|
|
else // all 3 flavors of long double
|
|
|
|
Out << "fmodl(";
|
2005-08-23 20:22:50 +00:00
|
|
|
writeOperand(I.getOperand(0));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ")";
|
2005-03-03 21:12:04 +00:00
|
|
|
} else {
|
2006-10-26 06:15:43 +00:00
|
|
|
|
|
|
|
// Write out the cast of the instruction's value back to the proper type
|
|
|
|
// if necessary.
|
|
|
|
bool NeedsClosingParens = writeInstructionCast(I);
|
|
|
|
|
|
|
|
// Certain instructions require the operand to be forced to a specific type
|
|
|
|
// so we use writeOperandWithCast here instead of writeOperand. Similarly
|
|
|
|
// below for operand 1
|
|
|
|
writeOperandWithCast(I.getOperand(0), I.getOpcode());
|
2005-03-03 21:12:04 +00:00
|
|
|
|
|
|
|
switch (I.getOpcode()) {
|
2007-02-02 02:16:23 +00:00
|
|
|
case Instruction::Add: Out << " + "; break;
|
|
|
|
case Instruction::Sub: Out << " - "; break;
|
|
|
|
case Instruction::Mul: Out << " * "; break;
|
2006-11-02 01:53:59 +00:00
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
2007-02-02 02:16:23 +00:00
|
|
|
case Instruction::FRem: Out << " % "; break;
|
2006-10-26 06:15:43 +00:00
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::SDiv:
|
2007-02-02 02:16:23 +00:00
|
|
|
case Instruction::FDiv: Out << " / "; break;
|
|
|
|
case Instruction::And: Out << " & "; break;
|
|
|
|
case Instruction::Or: Out << " | "; break;
|
|
|
|
case Instruction::Xor: Out << " ^ "; break;
|
2005-03-03 21:12:04 +00:00
|
|
|
case Instruction::Shl : Out << " << "; break;
|
2006-11-08 06:47:33 +00:00
|
|
|
case Instruction::LShr:
|
|
|
|
case Instruction::AShr: Out << " >> "; break;
|
2006-12-07 22:21:48 +00:00
|
|
|
default: cerr << "Invalid operator type!" << I; abort();
|
2005-03-03 21:12:04 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 06:15:43 +00:00
|
|
|
writeOperandWithCast(I.getOperand(1), I.getOpcode());
|
|
|
|
if (NeedsClosingParens)
|
|
|
|
Out << "))";
|
2005-03-03 21:12:04 +00:00
|
|
|
}
|
2003-06-23 20:00:51 +00:00
|
|
|
|
|
|
|
if (needsCast) {
|
|
|
|
Out << "))";
|
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2006-12-23 06:05:41 +00:00
|
|
|
void CWriter::visitICmpInst(ICmpInst &I) {
|
|
|
|
// We must cast the results of icmp which might be promoted.
|
|
|
|
bool needsCast = false;
|
|
|
|
|
|
|
|
// Write out the cast of the instruction's value back to the proper type
|
|
|
|
// if necessary.
|
|
|
|
bool NeedsClosingParens = writeInstructionCast(I);
|
|
|
|
|
|
|
|
// Certain icmp predicate require the operand to be forced to a specific type
|
|
|
|
// so we use writeOperandWithCast here instead of writeOperand. Similarly
|
|
|
|
// below for operand 1
|
2007-09-15 06:51:03 +00:00
|
|
|
writeOperandWithCast(I.getOperand(0), I);
|
2006-12-23 06:05:41 +00:00
|
|
|
|
|
|
|
switch (I.getPredicate()) {
|
|
|
|
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
|
|
|
case ICmpInst::ICMP_NE: Out << " != "; break;
|
|
|
|
case ICmpInst::ICMP_ULE:
|
|
|
|
case ICmpInst::ICMP_SLE: Out << " <= "; break;
|
|
|
|
case ICmpInst::ICMP_UGE:
|
|
|
|
case ICmpInst::ICMP_SGE: Out << " >= "; break;
|
|
|
|
case ICmpInst::ICMP_ULT:
|
|
|
|
case ICmpInst::ICMP_SLT: Out << " < "; break;
|
|
|
|
case ICmpInst::ICMP_UGT:
|
|
|
|
case ICmpInst::ICMP_SGT: Out << " > "; break;
|
|
|
|
default: cerr << "Invalid icmp predicate!" << I; abort();
|
|
|
|
}
|
|
|
|
|
2007-09-15 06:51:03 +00:00
|
|
|
writeOperandWithCast(I.getOperand(1), I);
|
2006-12-23 06:05:41 +00:00
|
|
|
if (NeedsClosingParens)
|
|
|
|
Out << "))";
|
|
|
|
|
|
|
|
if (needsCast) {
|
|
|
|
Out << "))";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWriter::visitFCmpInst(FCmpInst &I) {
|
2007-01-08 06:58:32 +00:00
|
|
|
if (I.getPredicate() == FCmpInst::FCMP_FALSE) {
|
|
|
|
Out << "0";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (I.getPredicate() == FCmpInst::FCMP_TRUE) {
|
|
|
|
Out << "1";
|
|
|
|
return;
|
|
|
|
}
|
2006-12-23 06:05:41 +00:00
|
|
|
|
2007-01-08 06:58:32 +00:00
|
|
|
const char* op = 0;
|
2006-12-23 06:05:41 +00:00
|
|
|
switch (I.getPredicate()) {
|
2007-01-08 06:58:32 +00:00
|
|
|
default: assert(0 && "Illegal FCmp predicate");
|
|
|
|
case FCmpInst::FCMP_ORD: op = "ord"; break;
|
|
|
|
case FCmpInst::FCMP_UNO: op = "uno"; break;
|
|
|
|
case FCmpInst::FCMP_UEQ: op = "ueq"; break;
|
|
|
|
case FCmpInst::FCMP_UNE: op = "une"; break;
|
|
|
|
case FCmpInst::FCMP_ULT: op = "ult"; break;
|
|
|
|
case FCmpInst::FCMP_ULE: op = "ule"; break;
|
|
|
|
case FCmpInst::FCMP_UGT: op = "ugt"; break;
|
|
|
|
case FCmpInst::FCMP_UGE: op = "uge"; break;
|
|
|
|
case FCmpInst::FCMP_OEQ: op = "oeq"; break;
|
|
|
|
case FCmpInst::FCMP_ONE: op = "one"; break;
|
|
|
|
case FCmpInst::FCMP_OLT: op = "olt"; break;
|
|
|
|
case FCmpInst::FCMP_OLE: op = "ole"; break;
|
|
|
|
case FCmpInst::FCMP_OGT: op = "ogt"; break;
|
|
|
|
case FCmpInst::FCMP_OGE: op = "oge"; break;
|
2006-12-23 06:05:41 +00:00
|
|
|
}
|
2007-01-08 06:58:32 +00:00
|
|
|
|
|
|
|
Out << "llvm_fcmp_" << op << "(";
|
|
|
|
// Write the first operand
|
|
|
|
writeOperand(I.getOperand(0));
|
|
|
|
Out << ", ";
|
2006-12-23 06:05:41 +00:00
|
|
|
// Write the second operand
|
|
|
|
writeOperand(I.getOperand(1));
|
2007-01-08 06:58:32 +00:00
|
|
|
Out << ")";
|
2006-12-23 06:05:41 +00:00
|
|
|
}
|
|
|
|
|
2006-12-11 20:39:15 +00:00
|
|
|
static const char * getFloatBitCastField(const Type *Ty) {
|
|
|
|
switch (Ty->getTypeID()) {
|
|
|
|
default: assert(0 && "Invalid Type");
|
2006-12-31 05:55:36 +00:00
|
|
|
case Type::FloatTyID: return "Float";
|
|
|
|
case Type::DoubleTyID: return "Double";
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-12 07:05:14 +00:00
|
|
|
case Type::IntegerTyID: {
|
|
|
|
unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
|
|
|
|
if (NumBits <= 32)
|
|
|
|
return "Int32";
|
|
|
|
else
|
|
|
|
return "Int64";
|
|
|
|
}
|
2006-12-11 20:39:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitCastInst(CastInst &I) {
|
2006-11-27 01:05:10 +00:00
|
|
|
const Type *DstTy = I.getType();
|
|
|
|
const Type *SrcTy = I.getOperand(0)->getType();
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2006-12-17 20:24:50 +00:00
|
|
|
if (isFPIntBitCast(I)) {
|
2006-12-11 20:39:15 +00:00
|
|
|
// These int<->float and long<->double casts need to be handled specially
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
2006-12-11 20:39:15 +00:00
|
|
|
<< getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
|
|
|
|
writeOperand(I.getOperand(0));
|
2007-02-23 22:45:08 +00:00
|
|
|
Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
2006-12-11 20:39:15 +00:00
|
|
|
<< getFloatBitCastField(I.getType());
|
|
|
|
} else {
|
|
|
|
printCast(I.getOpcode(), SrcTy, DstTy);
|
2007-05-03 02:57:13 +00:00
|
|
|
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::Int1Ty) {
|
2006-12-11 20:39:15 +00:00
|
|
|
// Make sure we really get a sext from bool by subtracing the bool from 0
|
|
|
|
Out << "0-";
|
|
|
|
}
|
2007-05-03 02:57:13 +00:00
|
|
|
writeOperand(I.getOperand(0));
|
|
|
|
if (DstTy == Type::Int1Ty &&
|
|
|
|
(I.getOpcode() == Instruction::Trunc ||
|
|
|
|
I.getOpcode() == Instruction::FPToUI ||
|
|
|
|
I.getOpcode() == Instruction::FPToSI ||
|
|
|
|
I.getOpcode() == Instruction::PtrToInt)) {
|
|
|
|
// Make sure we really get a trunc to bool by anding the operand with 1
|
|
|
|
Out << "&1u";
|
|
|
|
}
|
2006-11-27 01:05:10 +00:00
|
|
|
}
|
2007-05-03 02:57:13 +00:00
|
|
|
Out << ')';
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2004-03-12 05:52:14 +00:00
|
|
|
void CWriter::visitSelectInst(SelectInst &I) {
|
|
|
|
Out << "((";
|
|
|
|
writeOperand(I.getCondition());
|
|
|
|
Out << ") ? (";
|
|
|
|
writeOperand(I.getTrueValue());
|
|
|
|
Out << ") : (";
|
|
|
|
writeOperand(I.getFalseValue());
|
2005-04-20 16:05:03 +00:00
|
|
|
Out << "))";
|
2004-03-12 05:52:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-09 04:30:20 +00:00
|
|
|
void CWriter::lowerIntrinsics(Function &F) {
|
2007-04-12 21:00:45 +00:00
|
|
|
// This is used to keep track of intrinsics that get generated to a lowered
|
|
|
|
// function. We must generate the prototypes before the function body which
|
|
|
|
// will only be expanded on first use (by the loop below).
|
|
|
|
std::vector<Function*> prototypesToGen;
|
|
|
|
|
|
|
|
// Examine all the instructions in this function to find the intrinsics that
|
|
|
|
// need to be lowered.
|
2007-04-13 22:52:03 +00:00
|
|
|
for (Function::iterator BB = F.begin(), EE = F.end(); BB != EE; ++BB)
|
2004-05-09 04:30:20 +00:00
|
|
|
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
|
|
|
|
if (CallInst *CI = dyn_cast<CallInst>(I++))
|
|
|
|
if (Function *F = CI->getCalledFunction())
|
|
|
|
switch (F->getIntrinsicID()) {
|
|
|
|
case Intrinsic::not_intrinsic:
|
2008-02-16 14:46:26 +00:00
|
|
|
case Intrinsic::memory_barrier:
|
2004-05-09 04:30:20 +00:00
|
|
|
case Intrinsic::vastart:
|
|
|
|
case Intrinsic::vacopy:
|
|
|
|
case Intrinsic::vaend:
|
|
|
|
case Intrinsic::returnaddress:
|
|
|
|
case Intrinsic::frameaddress:
|
|
|
|
case Intrinsic::setjmp:
|
|
|
|
case Intrinsic::longjmp:
|
2005-02-28 19:29:46 +00:00
|
|
|
case Intrinsic::prefetch:
|
2006-03-08 19:31:15 +00:00
|
|
|
case Intrinsic::dbg_stoppoint:
|
2007-10-02 17:43:59 +00:00
|
|
|
case Intrinsic::powi:
|
2008-03-02 08:47:13 +00:00
|
|
|
case Intrinsic::x86_sse_cmp_ss:
|
|
|
|
case Intrinsic::x86_sse_cmp_ps:
|
|
|
|
case Intrinsic::x86_sse2_cmp_sd:
|
|
|
|
case Intrinsic::x86_sse2_cmp_pd:
|
2008-03-02 08:54:27 +00:00
|
|
|
case Intrinsic::ppc_altivec_lvsl:
|
2008-03-02 08:47:13 +00:00
|
|
|
// We directly implement these intrinsics
|
2004-05-09 04:30:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
2006-03-13 23:09:05 +00:00
|
|
|
// If this is an intrinsic that directly corresponds to a GCC
|
|
|
|
// builtin, we handle it.
|
|
|
|
const char *BuiltinName = "";
|
|
|
|
#define GET_GCC_BUILTIN_NAME
|
|
|
|
#include "llvm/Intrinsics.gen"
|
|
|
|
#undef GET_GCC_BUILTIN_NAME
|
|
|
|
// If we handle it, don't lower it.
|
|
|
|
if (BuiltinName[0]) break;
|
|
|
|
|
2004-05-09 04:30:20 +00:00
|
|
|
// All other intrinsic calls we must lower.
|
2005-03-18 16:12:37 +00:00
|
|
|
Instruction *Before = 0;
|
2005-04-20 16:05:03 +00:00
|
|
|
if (CI != &BB->front())
|
2005-03-18 16:12:37 +00:00
|
|
|
Before = prior(BasicBlock::iterator(CI));
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2007-01-29 17:51:02 +00:00
|
|
|
IL->LowerIntrinsicCall(CI);
|
2004-05-09 04:30:20 +00:00
|
|
|
if (Before) { // Move iterator to instruction after call
|
|
|
|
I = Before; ++I;
|
|
|
|
} else {
|
|
|
|
I = BB->begin();
|
2004-02-14 00:31:10 +00:00
|
|
|
}
|
2007-04-12 21:00:45 +00:00
|
|
|
// If the intrinsic got lowered to another call, and that call has
|
|
|
|
// a definition then we need to make sure its prototype is emitted
|
|
|
|
// before any calls to it.
|
|
|
|
if (CallInst *Call = dyn_cast<CallInst>(I))
|
|
|
|
if (Function *NewF = Call->getCalledFunction())
|
|
|
|
if (!NewF->isDeclaration())
|
|
|
|
prototypesToGen.push_back(NewF);
|
|
|
|
|
2006-03-13 23:09:05 +00:00
|
|
|
break;
|
2004-05-09 04:30:20 +00:00
|
|
|
}
|
2004-02-14 00:31:10 +00:00
|
|
|
|
2007-04-12 21:00:45 +00:00
|
|
|
// We may have collected some prototypes to emit in the loop above.
|
|
|
|
// Emit them now, before the function that uses them is emitted. But,
|
|
|
|
// be careful not to emit them twice.
|
|
|
|
std::vector<Function*>::iterator I = prototypesToGen.begin();
|
|
|
|
std::vector<Function*>::iterator E = prototypesToGen.end();
|
|
|
|
for ( ; I != E; ++I) {
|
2007-04-12 21:57:15 +00:00
|
|
|
if (intrinsicPrototypesAlreadyGenerated.insert(*I).second) {
|
2007-04-12 21:00:45 +00:00
|
|
|
Out << '\n';
|
|
|
|
printFunctionSignature(*I, true);
|
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-02-14 00:31:10 +00:00
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitCallInst(CallInst &I) {
|
2006-11-27 23:50:49 +00:00
|
|
|
//check if we have inline asm
|
|
|
|
if (isInlineAsm(I)) {
|
|
|
|
visitInlineAsm(I);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-03-13 23:09:05 +00:00
|
|
|
bool WroteCallee = false;
|
|
|
|
|
2003-05-08 18:41:45 +00:00
|
|
|
// Handle intrinsic function calls first...
|
|
|
|
if (Function *F = I.getCalledFunction())
|
2008-03-02 08:29:41 +00:00
|
|
|
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
|
|
|
|
if (visitBuiltinCall(I, ID, WroteCallee))
|
2008-02-16 14:46:26 +00:00
|
|
|
return;
|
2003-05-08 18:41:45 +00:00
|
|
|
|
2004-11-13 22:21:56 +00:00
|
|
|
Value *Callee = I.getCalledValue();
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2007-01-28 13:31:35 +00:00
|
|
|
const PointerType *PTy = cast<PointerType>(Callee->getType());
|
|
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
// If this is a call to a struct-return function, assign to the first
|
|
|
|
// parameter instead of passing it to the call.
|
2007-11-27 13:23:08 +00:00
|
|
|
const ParamAttrsList *PAL = I.getParamAttrs();
|
2008-01-12 18:53:07 +00:00
|
|
|
bool hasByVal = I.hasByValArgument();
|
2008-03-03 21:46:28 +00:00
|
|
|
bool isStructRet = I.hasStructRetAttr();
|
2006-05-23 23:39:48 +00:00
|
|
|
if (isStructRet) {
|
2008-03-02 08:07:24 +00:00
|
|
|
writeOperandDeref(I.getOperand(1));
|
2008-01-11 23:10:11 +00:00
|
|
|
Out << " = ";
|
2006-05-23 23:39:48 +00:00
|
|
|
}
|
|
|
|
|
2005-05-06 06:53:07 +00:00
|
|
|
if (I.isTailCall()) Out << " /*tail*/ ";
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
if (!WroteCallee) {
|
|
|
|
// If this is an indirect call to a struct return function, we need to cast
|
2008-01-12 18:53:07 +00:00
|
|
|
// the pointer. Ditto for indirect calls with byval arguments.
|
|
|
|
bool NeedsCast = (hasByVal || isStructRet) && !isa<Function>(Callee);
|
2006-05-23 23:39:48 +00:00
|
|
|
|
|
|
|
// GCC is a real PITA. It does not permit codegening casts of functions to
|
|
|
|
// function pointers if they are in a call (it generates a trap instruction
|
|
|
|
// instead!). We work around this by inserting a cast to void* in between
|
|
|
|
// the function and the function pointer cast. Unfortunately, we can't just
|
|
|
|
// form the constant expression here, because the folder will immediately
|
|
|
|
// nuke it.
|
|
|
|
//
|
|
|
|
// Note finally, that this is completely unsafe. ANSI C does not guarantee
|
|
|
|
// that void* and function pointers have the same size. :( To deal with this
|
|
|
|
// in the common case, we handle casts where the number of arguments passed
|
|
|
|
// match exactly.
|
|
|
|
//
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee))
|
2006-11-27 01:05:10 +00:00
|
|
|
if (CE->isCast())
|
2006-05-23 23:39:48 +00:00
|
|
|
if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) {
|
|
|
|
NeedsCast = true;
|
|
|
|
Callee = RF;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedsCast) {
|
|
|
|
// Ok, just cast the pointer type.
|
|
|
|
Out << "((";
|
2008-01-12 18:53:07 +00:00
|
|
|
if (isStructRet)
|
2007-11-27 13:23:08 +00:00
|
|
|
printStructReturnPointerFunctionType(Out, PAL,
|
2006-05-23 23:39:48 +00:00
|
|
|
cast<PointerType>(I.getCalledValue()->getType()));
|
2008-01-12 18:53:07 +00:00
|
|
|
else if (hasByVal)
|
|
|
|
printType(Out, I.getCalledValue()->getType(), false, "", true, PAL);
|
|
|
|
else
|
|
|
|
printType(Out, I.getCalledValue()->getType());
|
2006-05-23 23:39:48 +00:00
|
|
|
Out << ")(void*)";
|
|
|
|
}
|
|
|
|
writeOperand(Callee);
|
|
|
|
if (NeedsCast) Out << ')';
|
|
|
|
}
|
2005-04-20 16:05:03 +00:00
|
|
|
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2004-11-13 22:21:56 +00:00
|
|
|
unsigned NumDeclaredParams = FTy->getNumParams();
|
|
|
|
|
2006-05-23 23:39:48 +00:00
|
|
|
CallSite::arg_iterator AI = I.op_begin()+1, AE = I.op_end();
|
|
|
|
unsigned ArgNo = 0;
|
|
|
|
if (isStructRet) { // Skip struct return argument.
|
|
|
|
++AI;
|
|
|
|
++ArgNo;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrintedArg = false;
|
2008-01-11 23:10:11 +00:00
|
|
|
for (; AI != AE; ++AI, ++ArgNo) {
|
2006-05-23 23:39:48 +00:00
|
|
|
if (PrintedArg) Out << ", ";
|
|
|
|
if (ArgNo < NumDeclaredParams &&
|
|
|
|
(*AI)->getType() != FTy->getParamType(ArgNo)) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2007-01-07 03:24:48 +00:00
|
|
|
printType(Out, FTy->getParamType(ArgNo),
|
2008-01-11 23:10:11 +00:00
|
|
|
/*isSigned=*/PAL && PAL->paramHasAttr(ArgNo+1, ParamAttr::SExt));
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2004-11-13 22:21:56 +00:00
|
|
|
}
|
2008-01-11 23:10:11 +00:00
|
|
|
// Check if the argument is expected to be passed by value.
|
2008-03-02 08:07:24 +00:00
|
|
|
if (I.paramHasAttr(ArgNo+1, ParamAttr::ByVal))
|
|
|
|
writeOperandDeref(*AI);
|
|
|
|
else
|
|
|
|
writeOperand(*AI);
|
2006-05-23 23:39:48 +00:00
|
|
|
PrintedArg = true;
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2005-04-20 16:05:03 +00:00
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
|
2008-03-02 08:29:41 +00:00
|
|
|
/// visitBuiltinCall - Handle the call to the specified builtin. Returns true
|
|
|
|
/// if the entire call is handled, return false it it wasn't handled, and
|
|
|
|
/// optionally set 'WroteCallee' if the callee has already been printed out.
|
|
|
|
bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID,
|
|
|
|
bool &WroteCallee) {
|
|
|
|
switch (ID) {
|
|
|
|
default: {
|
|
|
|
// If this is an intrinsic that directly corresponds to a GCC
|
|
|
|
// builtin, we emit it here.
|
|
|
|
const char *BuiltinName = "";
|
|
|
|
Function *F = I.getCalledFunction();
|
|
|
|
#define GET_GCC_BUILTIN_NAME
|
|
|
|
#include "llvm/Intrinsics.gen"
|
|
|
|
#undef GET_GCC_BUILTIN_NAME
|
|
|
|
assert(BuiltinName[0] && "Unknown LLVM intrinsic!");
|
|
|
|
|
|
|
|
Out << BuiltinName;
|
|
|
|
WroteCallee = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
case Intrinsic::memory_barrier:
|
|
|
|
Out << "__sync_syncronize()";
|
|
|
|
return true;
|
|
|
|
case Intrinsic::vastart:
|
|
|
|
Out << "0; ";
|
|
|
|
|
|
|
|
Out << "va_start(*(va_list*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", ";
|
|
|
|
// Output the last argument to the enclosing function.
|
|
|
|
if (I.getParent()->getParent()->arg_empty()) {
|
|
|
|
cerr << "The C backend does not currently support zero "
|
|
|
|
<< "argument varargs functions, such as '"
|
|
|
|
<< I.getParent()->getParent()->getName() << "'!\n";
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
writeOperand(--I.getParent()->getParent()->arg_end());
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::vaend:
|
|
|
|
if (!isa<ConstantPointerNull>(I.getOperand(1))) {
|
|
|
|
Out << "0; va_end(*(va_list*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ')';
|
|
|
|
} else {
|
|
|
|
Out << "va_end(*(va_list*)0)";
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
case Intrinsic::vacopy:
|
|
|
|
Out << "0; ";
|
|
|
|
Out << "va_copy(*(va_list*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", *(va_list*)";
|
|
|
|
writeOperand(I.getOperand(2));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::returnaddress:
|
|
|
|
Out << "__builtin_return_address(";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::frameaddress:
|
|
|
|
Out << "__builtin_frame_address(";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::powi:
|
|
|
|
Out << "__builtin_powi(";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(2));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::setjmp:
|
|
|
|
Out << "setjmp(*(jmp_buf*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::longjmp:
|
|
|
|
Out << "longjmp(*(jmp_buf*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(2));
|
|
|
|
Out << ')';
|
|
|
|
return true;
|
|
|
|
case Intrinsic::prefetch:
|
|
|
|
Out << "LLVM_PREFETCH((const void *)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(2));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(3));
|
|
|
|
Out << ")";
|
|
|
|
return true;
|
|
|
|
case Intrinsic::stacksave:
|
|
|
|
// Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save()
|
|
|
|
// to work around GCC bugs (see PR1809).
|
|
|
|
Out << "0; *((void**)&" << GetValueName(&I)
|
|
|
|
<< ") = __builtin_stack_save()";
|
|
|
|
return true;
|
|
|
|
case Intrinsic::dbg_stoppoint: {
|
|
|
|
// If we use writeOperand directly we get a "u" suffix which is rejected
|
|
|
|
// by gcc.
|
|
|
|
DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
|
|
|
|
Out << "\n#line "
|
|
|
|
<< SPI.getLine()
|
|
|
|
<< " \"" << SPI.getDirectory()
|
|
|
|
<< SPI.getFileName() << "\"\n";
|
|
|
|
return true;
|
|
|
|
}
|
2008-03-02 08:47:13 +00:00
|
|
|
case Intrinsic::x86_sse_cmp_ss:
|
|
|
|
case Intrinsic::x86_sse_cmp_ps:
|
|
|
|
case Intrinsic::x86_sse2_cmp_sd:
|
|
|
|
case Intrinsic::x86_sse2_cmp_pd:
|
|
|
|
Out << '(';
|
|
|
|
printType(Out, I.getType());
|
|
|
|
Out << ')';
|
|
|
|
// Multiple GCC builtins multiplex onto this intrinsic.
|
|
|
|
switch (cast<ConstantInt>(I.getOperand(3))->getZExtValue()) {
|
|
|
|
default: assert(0 && "Invalid llvm.x86.sse.cmp!");
|
|
|
|
case 0: Out << "__builtin_ia32_cmpeq"; break;
|
|
|
|
case 1: Out << "__builtin_ia32_cmplt"; break;
|
|
|
|
case 2: Out << "__builtin_ia32_cmple"; break;
|
|
|
|
case 3: Out << "__builtin_ia32_cmpunord"; break;
|
|
|
|
case 4: Out << "__builtin_ia32_cmpneq"; break;
|
|
|
|
case 5: Out << "__builtin_ia32_cmpnlt"; break;
|
|
|
|
case 6: Out << "__builtin_ia32_cmpnle"; break;
|
|
|
|
case 7: Out << "__builtin_ia32_cmpord"; break;
|
|
|
|
}
|
|
|
|
if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd)
|
|
|
|
Out << 'p';
|
|
|
|
else
|
|
|
|
Out << 's';
|
|
|
|
if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps)
|
|
|
|
Out << 's';
|
|
|
|
else
|
|
|
|
Out << 'd';
|
|
|
|
|
|
|
|
Out << "(";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(2));
|
|
|
|
Out << ")";
|
|
|
|
return true;
|
2008-03-02 08:54:27 +00:00
|
|
|
case Intrinsic::ppc_altivec_lvsl:
|
|
|
|
Out << '(';
|
|
|
|
printType(Out, I.getType());
|
|
|
|
Out << ')';
|
|
|
|
Out << "__builtin_altivec_lvsl(0, (void*)";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << ")";
|
|
|
|
return true;
|
2008-03-02 08:29:41 +00:00
|
|
|
}
|
|
|
|
}
|
2006-11-27 23:50:49 +00:00
|
|
|
|
|
|
|
//This converts the llvm constraint string to something gcc is expecting.
|
|
|
|
//TODO: work out platform independent constraints and factor those out
|
2006-11-28 19:56:02 +00:00
|
|
|
// of the per target tables
|
|
|
|
// handle multiple constraint codes
|
2006-11-28 19:53:36 +00:00
|
|
|
std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) {
|
2006-11-27 23:50:49 +00:00
|
|
|
|
|
|
|
assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
|
|
|
|
|
|
|
|
const char** table = 0;
|
2006-11-28 19:53:36 +00:00
|
|
|
|
|
|
|
//Grab the translation table from TargetAsmInfo if it exists
|
|
|
|
if (!TAsm) {
|
|
|
|
std::string E;
|
2007-10-17 21:28:48 +00:00
|
|
|
const TargetMachineRegistry::entry* Match =
|
2006-11-28 19:53:36 +00:00
|
|
|
TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, E);
|
|
|
|
if (Match) {
|
|
|
|
//Per platform Target Machines don't exist, so create it
|
|
|
|
// this must be done only once
|
|
|
|
const TargetMachine* TM = Match->CtorFn(*TheModule, "");
|
|
|
|
TAsm = TM->getTargetAsmInfo();
|
|
|
|
}
|
2006-11-27 23:50:49 +00:00
|
|
|
}
|
2006-11-28 19:53:36 +00:00
|
|
|
if (TAsm)
|
|
|
|
table = TAsm->getAsmCBE();
|
|
|
|
|
|
|
|
//Search the translation table if it exists
|
|
|
|
for (int i = 0; table && table[i]; i += 2)
|
2006-11-27 23:50:49 +00:00
|
|
|
if (c.Codes[0] == table[i])
|
|
|
|
return table[i+1];
|
|
|
|
|
2006-11-28 22:25:32 +00:00
|
|
|
//default is identity
|
|
|
|
return c.Codes[0];
|
2006-11-27 23:50:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: import logic from AsmPrinter.cpp
|
2006-11-28 19:53:36 +00:00
|
|
|
static std::string gccifyAsm(std::string asmstr) {
|
2006-11-27 23:50:49 +00:00
|
|
|
for (std::string::size_type i = 0; i != asmstr.size(); ++i)
|
|
|
|
if (asmstr[i] == '\n')
|
|
|
|
asmstr.replace(i, 1, "\\n");
|
|
|
|
else if (asmstr[i] == '\t')
|
|
|
|
asmstr.replace(i, 1, "\\t");
|
|
|
|
else if (asmstr[i] == '$') {
|
|
|
|
if (asmstr[i + 1] == '{') {
|
|
|
|
std::string::size_type a = asmstr.find_first_of(':', i + 1);
|
|
|
|
std::string::size_type b = asmstr.find_first_of('}', i + 1);
|
|
|
|
std::string n = "%" +
|
|
|
|
asmstr.substr(a + 1, b - a - 1) +
|
|
|
|
asmstr.substr(i + 2, a - i - 2);
|
|
|
|
asmstr.replace(i, b - i + 1, n);
|
|
|
|
i += n.size() - 1;
|
|
|
|
} else
|
|
|
|
asmstr.replace(i, 1, "%");
|
|
|
|
}
|
|
|
|
else if (asmstr[i] == '%')//grr
|
|
|
|
{ asmstr.replace(i, 1, "%%"); ++i;}
|
|
|
|
|
|
|
|
return asmstr;
|
|
|
|
}
|
|
|
|
|
2006-11-28 19:56:02 +00:00
|
|
|
//TODO: assumptions about what consume arguments from the call are likely wrong
|
|
|
|
// handle communitivity
|
2006-11-27 23:50:49 +00:00
|
|
|
void CWriter::visitInlineAsm(CallInst &CI) {
|
|
|
|
InlineAsm* as = cast<InlineAsm>(CI.getOperand(0));
|
|
|
|
std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
|
|
|
|
std::vector<std::pair<std::string, Value*> > Input;
|
|
|
|
std::vector<std::pair<std::string, Value*> > Output;
|
|
|
|
std::string Clobber;
|
|
|
|
int count = CI.getType() == Type::VoidTy ? 1 : 0;
|
|
|
|
for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
|
|
|
|
E = Constraints.end(); I != E; ++I) {
|
|
|
|
assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
|
|
|
|
std::string c =
|
2006-11-28 19:53:36 +00:00
|
|
|
InterpretASMConstraint(*I);
|
2006-11-27 23:50:49 +00:00
|
|
|
switch(I->Type) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unknown asm constraint");
|
|
|
|
break;
|
|
|
|
case InlineAsm::isInput: {
|
|
|
|
if (c.size()) {
|
|
|
|
Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI));
|
|
|
|
++count; //consume arg
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case InlineAsm::isOutput: {
|
|
|
|
if (c.size()) {
|
|
|
|
Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c),
|
|
|
|
count ? CI.getOperand(count) : &CI));
|
|
|
|
++count; //consume arg
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case InlineAsm::isClobber: {
|
|
|
|
if (c.size())
|
|
|
|
Clobber += ",\"" + c + "\"";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//fix up the asm string for gcc
|
2006-11-28 19:53:36 +00:00
|
|
|
std::string asmstr = gccifyAsm(as->getAsmString());
|
2006-11-27 23:50:49 +00:00
|
|
|
|
|
|
|
Out << "__asm__ volatile (\"" << asmstr << "\"\n";
|
|
|
|
Out << " :";
|
2008-03-02 08:07:24 +00:00
|
|
|
for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(),
|
2006-11-27 23:50:49 +00:00
|
|
|
E = Output.end(); I != E; ++I) {
|
|
|
|
Out << "\"" << I->first << "\"(";
|
|
|
|
writeOperandRaw(I->second);
|
|
|
|
Out << ")";
|
|
|
|
if (I + 1 != E)
|
|
|
|
Out << ",";
|
|
|
|
}
|
|
|
|
Out << "\n :";
|
|
|
|
for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(),
|
|
|
|
E = Input.end(); I != E; ++I) {
|
|
|
|
Out << "\"" << I->first << "\"(";
|
|
|
|
writeOperandRaw(I->second);
|
|
|
|
Out << ")";
|
|
|
|
if (I + 1 != E)
|
|
|
|
Out << ",";
|
|
|
|
}
|
2006-11-28 23:07:32 +00:00
|
|
|
if (Clobber.size())
|
|
|
|
Out << "\n :" << Clobber.substr(1);
|
|
|
|
Out << ")";
|
2006-11-27 23:50:49 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitMallocInst(MallocInst &I) {
|
2004-02-13 23:18:48 +00:00
|
|
|
assert(0 && "lowerallocations pass didn't work!");
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitAllocaInst(AllocaInst &I) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '(';
|
2002-11-18 20:55:50 +00:00
|
|
|
printType(Out, I.getType());
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << ") alloca(sizeof(";
|
2002-11-18 20:55:50 +00:00
|
|
|
printType(Out, I.getType()->getElementType());
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2002-06-25 15:57:03 +00:00
|
|
|
if (I.isArrayAllocation()) {
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " * " ;
|
2002-06-25 15:57:03 +00:00
|
|
|
writeOperand(I.getOperand(0));
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ')';
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitFreeInst(FreeInst &I) {
|
2004-02-13 23:18:48 +00:00
|
|
|
assert(0 && "lowerallocations pass didn't work!");
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2008-03-02 08:07:24 +00:00
|
|
|
void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I,
|
|
|
|
gep_type_iterator E) {
|
|
|
|
|
|
|
|
// If there are no indices, just print out the pointer.
|
2002-05-09 21:18:38 +00:00
|
|
|
if (I == E) {
|
2008-03-02 08:07:24 +00:00
|
|
|
writeOperand(Ptr);
|
2002-08-19 23:09:46 +00:00
|
|
|
return;
|
2002-05-09 21:18:38 +00:00
|
|
|
}
|
2008-03-02 08:07:24 +00:00
|
|
|
|
|
|
|
// Find out if the last index is into a vector. If so, we have to print this
|
|
|
|
// specially. Since vectors can't have elements of indexable type, only the
|
|
|
|
// last index could possibly be of a vector element.
|
|
|
|
const VectorType *LastIndexIsVector = 0;
|
|
|
|
{
|
|
|
|
for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI)
|
|
|
|
LastIndexIsVector = dyn_cast<VectorType>(*TmpI);
|
2002-09-25 20:29:26 +00:00
|
|
|
}
|
2008-03-02 08:07:24 +00:00
|
|
|
|
|
|
|
Out << "(";
|
|
|
|
|
|
|
|
// If the last index is into a vector, we can't print it as &a[i][j] because
|
|
|
|
// we can't index into a vector with j in GCC. Instead, emit this as
|
|
|
|
// (((float*)&a[i])+j)
|
|
|
|
if (LastIndexIsVector) {
|
|
|
|
Out << "((";
|
|
|
|
printType(Out, PointerType::getUnqual(LastIndexIsVector->getElementType()));
|
|
|
|
Out << ")(";
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << '&';
|
2002-09-25 20:29:26 +00:00
|
|
|
|
2008-03-02 08:07:24 +00:00
|
|
|
// If the first index is 0 (very typical) we can do a number of
|
|
|
|
// simplifications to clean up the code.
|
|
|
|
Value *FirstOp = I.getOperand();
|
|
|
|
if (!isa<Constant>(FirstOp) || !cast<Constant>(FirstOp)->isNullValue()) {
|
|
|
|
// First index isn't simple, print it the hard way.
|
|
|
|
writeOperand(Ptr);
|
|
|
|
} else {
|
|
|
|
++I; // Skip the zero index.
|
|
|
|
|
|
|
|
// Okay, emit the first operand. If Ptr is something that is already address
|
|
|
|
// exposed, like a global, avoid emitting (&foo)[0], just emit foo instead.
|
|
|
|
if (isAddressExposed(Ptr)) {
|
|
|
|
writeOperandInternal(Ptr);
|
|
|
|
} else if (I != E && isa<StructType>(*I)) {
|
|
|
|
// If we didn't already emit the first operand, see if we can print it as
|
|
|
|
// P->f instead of "P[0].f"
|
|
|
|
writeOperand(Ptr);
|
|
|
|
Out << "->field" << cast<ConstantInt>(I.getOperand())->getZExtValue();
|
|
|
|
++I; // eat the struct index as well.
|
|
|
|
} else {
|
|
|
|
// Instead of emitting P[0][1], emit (*P)[1], which is more idiomatic.
|
|
|
|
Out << "(*";
|
|
|
|
writeOperand(Ptr);
|
|
|
|
Out << ")";
|
2003-11-25 20:49:55 +00:00
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
2002-08-22 22:48:55 +00:00
|
|
|
|
2008-03-02 08:07:24 +00:00
|
|
|
for (; I != E; ++I) {
|
2003-11-25 20:49:55 +00:00
|
|
|
if (isa<StructType>(*I)) {
|
2006-10-20 07:07:24 +00:00
|
|
|
Out << ".field" << cast<ConstantInt>(I.getOperand())->getZExtValue();
|
2008-03-02 08:07:24 +00:00
|
|
|
} else if (!isa<VectorType>(*I)) {
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << '[';
|
2007-09-22 20:16:48 +00:00
|
|
|
writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
|
2005-02-14 18:52:35 +00:00
|
|
|
Out << ']';
|
2008-03-02 08:07:24 +00:00
|
|
|
} else {
|
|
|
|
// If the last index is into a vector, then print it out as "+j)". This
|
|
|
|
// works with the 'LastIndexIsVector' code above.
|
|
|
|
if (isa<Constant>(I.getOperand()) &&
|
|
|
|
cast<Constant>(I.getOperand())->isNullValue()) {
|
|
|
|
Out << "))"; // avoid "+0".
|
|
|
|
} else {
|
|
|
|
Out << ")+(";
|
|
|
|
writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
|
|
|
|
Out << "))";
|
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
2008-03-02 08:07:24 +00:00
|
|
|
}
|
|
|
|
Out << ")";
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-01 21:25:59 +00:00
|
|
|
void CWriter::writeMemoryAccess(Value *Operand, const Type *OperandType,
|
|
|
|
bool IsVolatile, unsigned Alignment) {
|
|
|
|
|
|
|
|
bool IsUnaligned = Alignment &&
|
|
|
|
Alignment < TD->getABITypeAlignment(OperandType);
|
|
|
|
|
|
|
|
if (!IsUnaligned)
|
|
|
|
Out << '*';
|
|
|
|
if (IsVolatile || IsUnaligned) {
|
2005-02-15 05:52:14 +00:00
|
|
|
Out << "((";
|
2008-02-01 21:25:59 +00:00
|
|
|
if (IsUnaligned)
|
|
|
|
Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {";
|
|
|
|
printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*");
|
|
|
|
if (IsUnaligned) {
|
|
|
|
Out << "; } ";
|
|
|
|
if (IsVolatile) Out << "volatile ";
|
|
|
|
Out << "*";
|
|
|
|
}
|
2005-09-27 20:52:44 +00:00
|
|
|
Out << ")";
|
2005-02-14 16:47:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-01 21:25:59 +00:00
|
|
|
writeOperand(Operand);
|
2005-02-14 16:47:52 +00:00
|
|
|
|
2008-02-01 21:25:59 +00:00
|
|
|
if (IsVolatile || IsUnaligned) {
|
2005-03-08 00:26:08 +00:00
|
|
|
Out << ')';
|
2008-02-01 21:25:59 +00:00
|
|
|
if (IsUnaligned)
|
|
|
|
Out << "->data";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWriter::visitLoadInst(LoadInst &I) {
|
|
|
|
writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(),
|
|
|
|
I.getAlignment());
|
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitStoreInst(StoreInst &I) {
|
2008-02-01 21:25:59 +00:00
|
|
|
writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(),
|
|
|
|
I.isVolatile(), I.getAlignment());
|
2002-05-09 20:53:56 +00:00
|
|
|
Out << " = ";
|
2007-03-03 16:33:33 +00:00
|
|
|
Value *Operand = I.getOperand(0);
|
|
|
|
Constant *BitMask = 0;
|
|
|
|
if (const IntegerType* ITy = dyn_cast<IntegerType>(Operand->getType()))
|
|
|
|
if (!ITy->isPowerOf2ByteWidth())
|
|
|
|
// We have a bit width that doesn't match an even power-of-2 byte
|
|
|
|
// size. Consequently we must & the value with the type's bit mask
|
|
|
|
BitMask = ConstantInt::get(ITy, ITy->getBitMask());
|
|
|
|
if (BitMask)
|
|
|
|
Out << "((";
|
|
|
|
writeOperand(Operand);
|
|
|
|
if (BitMask) {
|
|
|
|
Out << ") & ";
|
|
|
|
printConstant(BitMask);
|
|
|
|
Out << ")";
|
|
|
|
}
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 15:57:03 +00:00
|
|
|
void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) {
|
2008-03-02 08:07:24 +00:00
|
|
|
printGEPExpression(I.getPointerOperand(), gep_type_begin(I),
|
|
|
|
gep_type_end(I));
|
2002-05-09 20:53:56 +00:00
|
|
|
}
|
2002-05-08 18:09:58 +00:00
|
|
|
|
2003-10-18 05:57:43 +00:00
|
|
|
void CWriter::visitVAArgInst(VAArgInst &I) {
|
2005-06-18 18:34:52 +00:00
|
|
|
Out << "va_arg(*(va_list*)";
|
2003-05-08 18:41:45 +00:00
|
|
|
writeOperand(I.getOperand(0));
|
2005-06-18 18:34:52 +00:00
|
|
|
Out << ", ";
|
2003-11-03 01:01:59 +00:00
|
|
|
printType(Out, I.getType());
|
2005-06-18 18:34:52 +00:00
|
|
|
Out << ");\n ";
|
2003-05-08 18:41:45 +00:00
|
|
|
}
|
|
|
|
|
2008-03-02 03:52:39 +00:00
|
|
|
void CWriter::visitInsertElementInst(InsertElementInst &I) {
|
|
|
|
const Type *EltTy = I.getType()->getElementType();
|
|
|
|
writeOperand(I.getOperand(0));
|
|
|
|
Out << ";\n ";
|
|
|
|
Out << "((";
|
|
|
|
printType(Out, PointerType::getUnqual(EltTy));
|
|
|
|
Out << ")(&" << GetValueName(&I) << "))[";
|
|
|
|
writeOperand(I.getOperand(2));
|
2008-03-02 08:10:16 +00:00
|
|
|
Out << "] = (";
|
|
|
|
writeOperand(I.getOperand(1));
|
2008-03-02 03:52:39 +00:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2008-03-02 03:57:08 +00:00
|
|
|
void CWriter::visitExtractElementInst(ExtractElementInst &I) {
|
|
|
|
// We know that our operand is not inlined.
|
|
|
|
Out << "((";
|
|
|
|
const Type *EltTy =
|
|
|
|
cast<VectorType>(I.getOperand(0)->getType())->getElementType();
|
|
|
|
printType(Out, PointerType::getUnqual(EltTy));
|
|
|
|
Out << ")(&" << GetValueName(I.getOperand(0)) << "))[";
|
|
|
|
writeOperand(I.getOperand(1));
|
|
|
|
Out << "]";
|
|
|
|
}
|
|
|
|
|
2008-03-02 05:41:07 +00:00
|
|
|
void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|
|
|
Out << "(";
|
|
|
|
printType(Out, SVI.getType());
|
|
|
|
Out << "){ ";
|
|
|
|
const VectorType *VT = SVI.getType();
|
|
|
|
unsigned NumElts = VT->getNumElements();
|
|
|
|
const Type *EltTy = VT->getElementType();
|
|
|
|
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i) {
|
|
|
|
if (i) Out << ", ";
|
|
|
|
int SrcVal = SVI.getMaskValue(i);
|
|
|
|
if ((unsigned)SrcVal >= NumElts*2) {
|
|
|
|
Out << " 0/*undef*/ ";
|
|
|
|
} else {
|
|
|
|
Value *Op = SVI.getOperand((unsigned)SrcVal >= NumElts);
|
|
|
|
if (isa<Instruction>(Op)) {
|
|
|
|
// Do an extractelement of this value from the appropriate input.
|
|
|
|
Out << "((";
|
|
|
|
printType(Out, PointerType::getUnqual(EltTy));
|
|
|
|
Out << ")(&" << GetValueName(Op)
|
|
|
|
<< "))[" << (SrcVal & NumElts-1) << "]";
|
|
|
|
} else if (isa<ConstantAggregateZero>(Op) || isa<UndefValue>(Op)) {
|
|
|
|
Out << "0";
|
|
|
|
} else {
|
|
|
|
printConstant(cast<ConstantVector>(Op)->getOperand(SrcVal & NumElts-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << "}";
|
|
|
|
}
|
2008-03-02 03:57:08 +00:00
|
|
|
|
2008-03-02 03:52:39 +00:00
|
|
|
|
2002-05-08 18:09:58 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// External Interface declaration
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-09-04 04:14:57 +00:00
|
|
|
bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM,
|
|
|
|
std::ostream &o,
|
|
|
|
CodeGenFileType FileType,
|
|
|
|
bool Fast) {
|
2005-06-25 02:48:37 +00:00
|
|
|
if (FileType != TargetMachine::AssemblyFile) return true;
|
|
|
|
|
2008-01-07 01:30:38 +00:00
|
|
|
PM.add(createGCLoweringPass());
|
2005-03-03 01:04:50 +00:00
|
|
|
PM.add(createLowerAllocationsPass(true));
|
2004-02-13 23:00:29 +00:00
|
|
|
PM.add(createLowerInvokePass());
|
2005-11-02 17:42:58 +00:00
|
|
|
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
|
2006-02-13 22:22:42 +00:00
|
|
|
PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
|
2006-03-23 05:43:16 +00:00
|
|
|
PM.add(new CWriter(o));
|
2008-01-07 01:30:38 +00:00
|
|
|
PM.add(createCollectorMetadataDeleter());
|
2004-02-13 23:18:48 +00:00
|
|
|
return false;
|
|
|
|
}
|