//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
-#include "llvm/ParameterAttributes.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/InlineAsm.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/ConstantsScanner.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Transforms/Scalar.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/System/Host.h"
#include "llvm/Config/config.h"
#include <algorithm>
#include <sstream>
using namespace llvm;
-namespace {
+extern "C" void LLVMInitializeCBackendTarget() {
// Register the target.
- RegisterTarget<CTargetMachine> X("c", " C backend");
+ RegisterTargetMachine<CTargetMachine> X(TheCBackendTarget);
+}
+namespace {
+ class CBEMCAsmInfo : public MCAsmInfo {
+ public:
+ CBEMCAsmInfo() {
+ GlobalPrefix = "";
+ PrivateGlobalPrefix = "";
+ }
+ };
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
/// any unnamed structure types that are used by the program, and merges
/// external functions with the same name.
public:
static char ID;
CBackendNameAllUsedStructsAndMergeFunctions()
- : ModulePass((intptr_t)&ID) {}
+ : ModulePass(&ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<FindUsedTypes>();
}
/// 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> {
- std::ostream &Out;
+ formatted_raw_ostream &Out;
IntrinsicLowering *IL;
Mangler *Mang;
LoopInfo *LI;
const Module *TheModule;
- const TargetAsmInfo* TAsm;
+ const MCAsmInfo* TAsm;
const TargetData* TD;
std::map<const Type *, std::string> TypeNames;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
+ std::set<const Argument*> ByValParams;
+ unsigned FPCounter;
+ unsigned OpaqueCounter;
+ DenseMap<const Value*, unsigned> AnonValueNumbers;
+ unsigned NextAnonValueNumber;
public:
static char ID;
- CWriter(std::ostream &o)
- : FunctionPass((intptr_t)&ID), Out(o), IL(0), Mang(0), LI(0),
- TheModule(0), TAsm(0), TD(0) {}
+ explicit CWriter(formatted_raw_ostream &o)
+ : FunctionPass(&ID), Out(o), IL(0), Mang(0), LI(0),
+ TheModule(0), TAsm(0), TD(0), OpaqueCounter(0), NextAnonValueNumber(0) {
+ FPCounter = 0;
+ }
virtual const char *getPassName() const { return "C backend"; }
virtual bool doInitialization(Module &M);
bool runOnFunction(Function &F) {
+ // Do not codegen any 'available_externally' functions at all, they have
+ // definitions outside the translation unit.
+ if (F.hasAvailableExternallyLinkage())
+ return false;
+
LI = &getAnalysis<LoopInfo>();
// Get rid of intrinsics we can't handle.
printFloatingPointConstants(F);
printFunction(F);
- FPConstantMap.clear();
return false;
}
virtual bool doFinalization(Module &M) {
// Free memory...
+ delete IL;
+ delete TD;
delete Mang;
+ FPConstantMap.clear();
TypeNames.clear();
+ ByValParams.clear();
+ intrinsicPrototypesAlreadyGenerated.clear();
return false;
}
+ raw_ostream &printType(formatted_raw_ostream &Out,
+ const Type *Ty,
+ bool isSigned = false,
+ const std::string &VariableName = "",
+ bool IgnoreName = false,
+ const AttrListPtr &PAL = AttrListPtr());
std::ostream &printType(std::ostream &Out, const Type *Ty,
- bool isSigned = false,
- const std::string &VariableName = "",
- bool IgnoreName = false);
+ bool isSigned = false,
+ const std::string &VariableName = "",
+ bool IgnoreName = false,
+ const AttrListPtr &PAL = AttrListPtr());
+ raw_ostream &printSimpleType(formatted_raw_ostream &Out,
+ const Type *Ty,
+ bool isSigned,
+ const std::string &NameSoFar = "");
std::ostream &printSimpleType(std::ostream &Out, const Type *Ty,
- bool isSigned,
- const std::string &NameSoFar = "");
+ bool isSigned,
+ const std::string &NameSoFar = "");
- void printStructReturnPointerFunctionType(std::ostream &Out,
+ void printStructReturnPointerFunctionType(formatted_raw_ostream &Out,
+ const AttrListPtr &PAL,
const PointerType *Ty);
+
+ /// 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 << ")";
+ }
+ }
- void writeOperand(Value *Operand);
- void writeOperandRaw(Value *Operand);
- void writeOperandInternal(Value *Operand);
+ void writeOperand(Value *Operand, bool Static = false);
+ void writeInstComputationInline(Instruction &I);
+ void writeOperandInternal(Value *Operand, bool Static = false);
void writeOperandWithCast(Value* Operand, unsigned Opcode);
- void writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate);
+ void writeOperandWithCast(Value* Operand, const ICmpInst &I);
bool writeInstructionCast(const Instruction &I);
+ void writeMemoryAccess(Value *Operand, const Type *OperandType,
+ bool IsVolatile, unsigned Alignment);
+
private :
std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c);
void printModule(Module *M);
void printModuleTypes(const TypeSymbolTable &ST);
- void printContainedStructs(const Type *Ty, std::set<const StructType *> &);
+ void printContainedStructs(const Type *Ty, std::set<const Type *> &);
void printFloatingPointConstants(Function &F);
+ void printFloatingPointConstants(const Constant *C);
void printFunctionSignature(const Function *F, bool Prototype);
void printFunction(Function &);
void printLoop(Loop *L);
void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
- void printConstant(Constant *CPV);
+ void printConstant(Constant *CPV, bool Static);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
- bool printConstExprCast(const ConstantExpr *CE);
- void printConstantArray(ConstantArray *CPA);
- void printConstantVector(ConstantVector *CP);
-
+ bool printConstExprCast(const ConstantExpr *CE, bool Static);
+ void printConstantArray(ConstantArray *CPA, bool Static);
+ void printConstantVector(ConstantVector *CV, bool Static);
+
+ /// 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);
+ }
+
// 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
// Must be an expression, must be used exactly once. If it is dead, we
// emit it inline where it would go.
- if (I.getType() == Type::VoidTy || !I.hasOneUse() ||
+ if (I.getType() == Type::getVoidTy(I.getContext()) || !I.hasOneUse() ||
isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I) ||
- isa<LoadInst>(I) || isa<VAArgInst>(I))
+ isa<LoadInst>(I) || isa<VAArgInst>(I) || isa<InsertElementInst>(I) ||
+ isa<InsertValueInst>(I))
// Don't inline a load across a store or other bad things!
return false;
- // Must not be used in inline asm
- if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false;
+ // 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;
+ }
// Only inline instruction it if it's use is in the same BB as the inst.
return I.getParent() == cast<Instruction>(I.use_back())->getParent();
void visitReturnInst(ReturnInst &I);
void visitBranchInst(BranchInst &I);
void visitSwitchInst(SwitchInst &I);
+ void visitIndirectBrInst(IndirectBrInst &I);
void visitInvokeInst(InvokeInst &I) {
- assert(0 && "Lowerinvoke pass didn't work!");
+ llvm_unreachable("Lowerinvoke pass didn't work!");
}
void visitUnwindInst(UnwindInst &I) {
- assert(0 && "Lowerinvoke pass didn't work!");
+ llvm_unreachable("Lowerinvoke pass didn't work!");
}
void visitUnreachableInst(UnreachableInst &I);
void visitSelectInst(SelectInst &I);
void visitCallInst (CallInst &I);
void visitInlineAsm(CallInst &I);
+ bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee);
- void visitMallocInst(MallocInst &I);
void visitAllocaInst(AllocaInst &I);
- void visitFreeInst (FreeInst &I);
void visitLoadInst (LoadInst &I);
void visitStoreInst (StoreInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
void visitVAArgInst (VAArgInst &I);
+
+ void visitInsertElementInst(InsertElementInst &I);
+ void visitExtractElementInst(ExtractElementInst &I);
+ void visitShuffleVectorInst(ShuffleVectorInst &SVI);
+
+ void visitInsertValueInst(InsertValueInst &I);
+ void visitExtractValueInst(ExtractValueInst &I);
void visitInstruction(Instruction &I) {
- cerr << "C Writer does not know about " << I;
- abort();
+#ifndef NDEBUG
+ errs() << "C Writer does not know about " << I;
+#endif
+ llvm_unreachable(0);
}
void outputLValue(Instruction *I) {
BasicBlock *Successor, unsigned Indent);
void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock,
unsigned Indent);
- void printIndexingExpression(Value *Ptr, gep_type_iterator I,
- gep_type_iterator E);
+ void printGEPExpression(Value *Ptr, gep_type_iterator I,
+ gep_type_iterator E, bool Static);
std::string GetValueName(const Value *Operand);
};
char CWriter::ID = 0;
+
+static std::string CBEMangle(const std::string &S) {
+ std::string Result;
+
+ for (unsigned i = 0, e = S.size(); i != e; ++i)
+ if (isalnum(S[i]) || S[i] == '_') {
+ Result += S[i];
+ } else {
+ Result += '_';
+ Result += 'A'+(S[i]&15);
+ Result += 'A'+((S[i]>>4)&15);
+ Result += '_';
+ }
+ return Result;
+}
+
+
/// 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.
TI != TE; ) {
TypeSymbolTable::iterator I = TI++;
- // If this isn't a struct type, remove it from our set of types to name.
- // This simplifies emission later.
- if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second)) {
+ // If this isn't a struct or array type, remove it from our set of types
+ // to name. This simplifies emission later.
+ if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second) &&
+ !isa<ArrayType>(I->second)) {
TST.remove(I);
} else {
// If this is not used, remove it from the symbol table.
unsigned RenameCounter = 0;
for (std::set<const Type *>::const_iterator I = UT.begin(), E = UT.end();
I != E; ++I)
- if (const StructType *ST = dyn_cast<StructType>(*I)) {
- while (M.addTypeName("unnamed"+utostr(RenameCounter), ST))
+ if (isa<StructType>(*I) || isa<ArrayType>(*I)) {
+ while (M.addTypeName("unnamed"+utostr(RenameCounter), *I))
++RenameCounter;
Changed = true;
}
/// 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,
+void CWriter::printStructReturnPointerFunctionType(formatted_raw_ostream &Out,
+ const AttrListPtr &PAL,
const PointerType *TheTy) {
const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
std::stringstream FunctionInnards;
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
const Type *RetTy = cast<PointerType>(I->get())->getElementType();
unsigned Idx = 1;
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
- for (++I; I != E; ++I) {
+ for (++I, ++Idx; I != E; ++I, ++Idx) {
if (PrintedType)
FunctionInnards << ", ";
- printType(FunctionInnards, *I,
- /*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt), "");
+ const Type *ArgTy = *I;
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), "");
PrintedType = true;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, RetTy,
- /*isSigned=*/Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt), tstr);
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr);
+}
+
+raw_ostream &
+CWriter::printSimpleType(formatted_raw_ostream &Out, const Type *Ty,
+ bool isSigned,
+ const std::string &NameSoFar) {
+ assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || isa<VectorType>(Ty)) &&
+ "Invalid type for printSimpleType");
+ switch (Ty->getTypeID()) {
+ 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 if (NumBits <= 64)
+ return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar;
+ else {
+ assert(NumBits <= 128 && "Bit widths > 128 not implemented yet");
+ return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar;
+ }
+ }
+ case Type::FloatTyID: return Out << "float " << NameSoFar;
+ case Type::DoubleTyID: return Out << "double " << NameSoFar;
+ // 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;
+
+ case Type::VectorTyID: {
+ const VectorType *VTy = cast<VectorType>(Ty);
+ return printSimpleType(Out, VTy->getElementType(), isSigned,
+ " __attribute__((vector_size(" +
+ utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar);
+ }
+
+ default:
+#ifndef NDEBUG
+ errs() << "Unknown primitive type: " << *Ty << "\n";
+#endif
+ llvm_unreachable(0);
+ }
}
std::ostream &
CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned,
- const std::string &NameSoFar) {
- assert((Ty->isPrimitiveType() || Ty->isInteger()) &&
+ const std::string &NameSoFar) {
+ assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || isa<VectorType>(Ty)) &&
"Invalid type for printSimpleType");
switch (Ty->getTypeID()) {
case Type::VoidTyID: return Out << "void " << NameSoFar;
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");
+ else if (NumBits <= 64)
return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar;
+ else {
+ assert(NumBits <= 128 && "Bit widths > 128 not implemented yet");
+ return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar;
}
}
case Type::FloatTyID: return Out << "float " << NameSoFar;
case Type::DoubleTyID: return Out << "double " << NameSoFar;
- default :
- cerr << "Unknown primitive type: " << *Ty << "\n";
- abort();
- }
-}
-
-#define IMPL_SIGN_EXTENSION(OpTy, Func) { \
- const IntegerType* IntTy = cast<IntegerType>(OpTy); \
- unsigned BitWidth = IntTy->getBitWidth(); \
- if (BitWidth != 8 && BitWidth != 16 && BitWidth != 32 && \
- BitWidth != 64 && BitWidth != 128) { \
- const char * Suffix; \
- if (BitWidth <=32)\
- Suffix = "U"; \
- else \
- Suffix = "ULL"; \
- Out << "("; \
- Func; \
- Out << " & (1" << Suffix << " << " << BitWidth - 1 << " ) ? "; \
- Func; \
- Out << " | " << (~IntTy->getBitMask()) << Suffix << " : "; \
- Func; \
- Out << " & " << IntTy->getBitMask() << Suffix; \
- Out << ")";\
- } \
- else \
- Func; \
- }
+ // 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;
+
+ case Type::VectorTyID: {
+ const VectorType *VTy = cast<VectorType>(Ty);
+ return printSimpleType(Out, VTy->getElementType(), isSigned,
+ " __attribute__((vector_size(" +
+ utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar);
+ }
+
+ default:
+#ifndef NDEBUG
+ errs() << "Unknown primitive type: " << *Ty << "\n";
+#endif
+ llvm_unreachable(0);
+ }
+}
// Pass the Type* and the variable name and this prints out the variable
// declaration.
//
-std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
- bool isSigned, const std::string &NameSoFar,
- bool IgnoreName) {
- if (Ty->isPrimitiveType() || Ty->isInteger()) {
+raw_ostream &CWriter::printType(formatted_raw_ostream &Out,
+ const Type *Ty,
+ bool isSigned, const std::string &NameSoFar,
+ bool IgnoreName, const AttrListPtr &PAL) {
+ if (Ty->isPrimitiveType() || Ty->isIntegerTy() || isa<VectorType>(Ty)) {
printSimpleType(Out, Ty, isSigned, NameSoFar);
return Out;
}
const FunctionType *FTy = cast<FunctionType>(Ty);
std::stringstream FunctionInnards;
FunctionInnards << " (" << NameSoFar << ") (";
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
unsigned Idx = 1;
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
+ const Type *ArgTy = *I;
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
if (I != FTy->param_begin())
FunctionInnards << ", ";
- printType(FunctionInnards, *I,
- /*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt), "");
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), "");
++Idx;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, FTy->getReturnType(),
- /*isSigned=*/Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt), tstr);
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr);
return Out;
}
case Type::StructTyID: {
printType(Out, *I, false, "field" + utostr(Idx++));
Out << ";\n";
}
- return Out << '}';
+ Out << '}';
+ if (STy->isPacked())
+ Out << " __attribute__ ((packed))";
+ return Out;
}
case Type::PointerTyID: {
isa<VectorType>(PTy->getElementType()))
ptrName = "(" + ptrName + ")";
+ if (!PAL.isEmpty())
+ // Must be a function ptr cast!
+ return printType(Out, PTy->getElementType(), false, ptrName, true, PAL);
return printType(Out, PTy->getElementType(), false, ptrName);
}
const ArrayType *ATy = cast<ArrayType>(Ty);
unsigned NumElements = ATy->getNumElements();
if (NumElements == 0) NumElements = 1;
- return printType(Out, ATy->getElementType(), false,
- NameSoFar + "[" + utostr(NumElements) + "]");
+ // Arrays are wrapped in structs to allow them to have normal
+ // value semantics (avoiding the array "decay").
+ Out << NameSoFar << " { ";
+ printType(Out, ATy->getElementType(), false,
+ "array[" + utostr(NumElements) + "]");
+ return Out << "; }";
}
- case Type::VectorTyID: {
- const VectorType *PTy = cast<VectorType>(Ty);
- unsigned NumElements = PTy->getNumElements();
+ case Type::OpaqueTyID: {
+ std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
+ assert(TypeNames.find(Ty) == TypeNames.end());
+ TypeNames[Ty] = TyName;
+ return Out << TyName << ' ' << NameSoFar;
+ }
+ default:
+ llvm_unreachable("Unhandled case in getTypeProps!");
+ }
+
+ return Out;
+}
+
+// Pass the Type* and the variable name and this prints out the variable
+// declaration.
+//
+std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
+ bool isSigned, const std::string &NameSoFar,
+ bool IgnoreName, const AttrListPtr &PAL) {
+ if (Ty->isPrimitiveType() || Ty->isIntegerTy() || isa<VectorType>(Ty)) {
+ printSimpleType(Out, Ty, isSigned, NameSoFar);
+ return Out;
+ }
+
+ // Check to see if the type is named.
+ if (!IgnoreName || isa<OpaqueType>(Ty)) {
+ std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
+ if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar;
+ }
+
+ switch (Ty->getTypeID()) {
+ case Type::FunctionTyID: {
+ const FunctionType *FTy = cast<FunctionType>(Ty);
+ std::stringstream FunctionInnards;
+ FunctionInnards << " (" << NameSoFar << ") (";
+ unsigned Idx = 1;
+ for (FunctionType::param_iterator I = FTy->param_begin(),
+ E = FTy->param_end(); I != E; ++I) {
+ const Type *ArgTy = *I;
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
+ if (I != FTy->param_begin())
+ FunctionInnards << ", ";
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), "");
+ ++Idx;
+ }
+ if (FTy->isVarArg()) {
+ if (FTy->getNumParams())
+ FunctionInnards << ", ...";
+ } else if (!FTy->getNumParams()) {
+ FunctionInnards << "void";
+ }
+ FunctionInnards << ')';
+ std::string tstr = FunctionInnards.str();
+ printType(Out, FTy->getReturnType(),
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr);
+ return Out;
+ }
+ case Type::StructTyID: {
+ const StructType *STy = cast<StructType>(Ty);
+ Out << NameSoFar + " {\n";
+ unsigned Idx = 0;
+ for (StructType::element_iterator I = STy->element_begin(),
+ E = STy->element_end(); I != E; ++I) {
+ Out << " ";
+ printType(Out, *I, false, "field" + utostr(Idx++));
+ Out << ";\n";
+ }
+ Out << '}';
+ if (STy->isPacked())
+ Out << " __attribute__ ((packed))";
+ return Out;
+ }
+
+ case Type::PointerTyID: {
+ const PointerType *PTy = cast<PointerType>(Ty);
+ std::string ptrName = "*" + NameSoFar;
+
+ if (isa<ArrayType>(PTy->getElementType()) ||
+ isa<VectorType>(PTy->getElementType()))
+ ptrName = "(" + ptrName + ")";
+
+ if (!PAL.isEmpty())
+ // Must be a function ptr cast!
+ return printType(Out, PTy->getElementType(), false, ptrName, true, PAL);
+ return printType(Out, PTy->getElementType(), false, ptrName);
+ }
+
+ case Type::ArrayTyID: {
+ const ArrayType *ATy = cast<ArrayType>(Ty);
+ unsigned NumElements = ATy->getNumElements();
if (NumElements == 0) NumElements = 1;
- return printType(Out, PTy->getElementType(), false,
- NameSoFar + "[" + utostr(NumElements) + "]");
+ // Arrays are wrapped in structs to allow them to have normal
+ // value semantics (avoiding the array "decay").
+ Out << NameSoFar << " { ";
+ printType(Out, ATy->getElementType(), false,
+ "array[" + utostr(NumElements) + "]");
+ return Out << "; }";
}
case Type::OpaqueTyID: {
- static int Count = 0;
- std::string TyName = "struct opaque_" + itostr(Count++);
+ std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
assert(TypeNames.find(Ty) == TypeNames.end());
TypeNames[Ty] = TyName;
return Out << TyName << ' ' << NameSoFar;
}
default:
- assert(0 && "Unhandled case in getTypeProps!");
- abort();
+ llvm_unreachable("Unhandled case in getTypeProps!");
}
return Out;
}
-void CWriter::printConstantArray(ConstantArray *CPA) {
+void CWriter::printConstantArray(ConstantArray *CPA, bool Static) {
// 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.
//
const Type *ETy = CPA->getType()->getElementType();
- bool isString = (ETy == Type::Int8Ty || ETy == Type::Int8Ty);
+ bool isString = (ETy == Type::getInt8Ty(CPA->getContext()) ||
+ ETy == Type::getInt8Ty(CPA->getContext()));
// Make sure the last character is a null char, as automatically added by C
if (isString && (CPA->getNumOperands() == 0 ||
if (isprint(C) && (!LastWasHex || !isxdigit(C))) {
LastWasHex = false;
if (C == '"' || C == '\\')
- Out << "\\" << C;
+ Out << "\\" << (char)C;
else
- Out << C;
+ Out << (char)C;
} else {
LastWasHex = false;
switch (C) {
Out << '{';
if (CPA->getNumOperands()) {
Out << ' ';
- printConstant(cast<Constant>(CPA->getOperand(0)));
+ printConstant(cast<Constant>(CPA->getOperand(0)), Static);
for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) {
Out << ", ";
- printConstant(cast<Constant>(CPA->getOperand(i)));
+ printConstant(cast<Constant>(CPA->getOperand(i)), Static);
}
}
Out << " }";
}
}
-void CWriter::printConstantVector(ConstantVector *CP) {
+void CWriter::printConstantVector(ConstantVector *CP, bool Static) {
Out << '{';
if (CP->getNumOperands()) {
Out << ' ';
- printConstant(cast<Constant>(CP->getOperand(0)));
+ printConstant(cast<Constant>(CP->getOperand(0)), Static);
for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) {
Out << ", ";
- printConstant(cast<Constant>(CP->getOperand(i)));
+ printConstant(cast<Constant>(CP->getOperand(i)), Static);
}
}
Out << " }";
// only deal in IEEE FP).
//
static bool isFPCSafeToPrint(const ConstantFP *CFP) {
+ bool ignored;
+ // Do long doubles in hex for now.
+ if (CFP->getType() != Type::getFloatTy(CFP->getContext()) &&
+ CFP->getType() != Type::getDoubleTy(CFP->getContext()))
+ return false;
+ APFloat APF = APFloat(CFP->getValueAPF()); // copy
+ if (CFP->getType() == Type::getFloatTy(CFP->getContext()))
+ APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
char Buffer[100];
- sprintf(Buffer, "%a", CFP->getValue());
-
+ sprintf(Buffer, "%a", APF.convertToDouble());
if (!strncmp(Buffer, "0x", 2) ||
!strncmp(Buffer, "-0x", 3) ||
!strncmp(Buffer, "+0x", 3))
- return atof(Buffer) == CFP->getValue();
+ return APF.bitwiseIsEqual(APFloat(atof(Buffer)));
return false;
#else
- std::string StrVal = ftostr(CFP->getValue());
+ std::string StrVal = ftostr(APF);
while (StrVal[0] == ' ')
StrVal.erase(StrVal.begin());
((StrVal[0] == '-' || StrVal[0] == '+') &&
(StrVal[1] >= '0' && StrVal[1] <= '9')))
// Reparse stringized version!
- return atof(StrVal.c_str()) == CFP->getValue();
+ return APF.bitwiseIsEqual(APFloat(atof(StrVal.c_str())));
return false;
#endif
}
Out << ')';
break;
default:
- assert(0 && "Invalid cast opcode");
+ llvm_unreachable("Invalid cast opcode");
}
// Print the source type cast
case Instruction::FPToUI:
break; // These don't need a source cast.
default:
- assert(0 && "Invalid cast opcode");
+ llvm_unreachable("Invalid cast opcode");
break;
}
}
// printConstant - The LLVM Constant to C Constant converter.
-void CWriter::printConstant(Constant *CPV) {
+void CWriter::printConstant(Constant *CPV, bool Static) {
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
switch (CE->getOpcode()) {
case Instruction::Trunc:
case Instruction::BitCast:
Out << "(";
printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType());
- if (CE->getOpcode() == Instruction::Trunc ||
- CE->getOpcode() == Instruction::FPToUI ||
- CE->getOpcode() == Instruction::FPToSI ||
- CE->getOpcode() == Instruction::PtrToInt) {
- if (const IntegerType* IntTy = dyn_cast<IntegerType>(CE->getType())) {
- uint64_t BitMask = IntTy->getBitMask();
- printConstant(CE->getOperand(0));
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- }
- else if (CE->getOpcode() == Instruction::SExt &&
- CE->getOperand(0)->getType() == Type::Int1Ty) {
+ if (CE->getOpcode() == Instruction::SExt &&
+ CE->getOperand(0)->getType() == Type::getInt1Ty(CPV->getContext())) {
// Make sure we really sext from bool here by subtracting from 0
Out << "0-";
- printConstant(CE->getOperand(0));
}
- else if (CE->getOpcode() == Instruction::SExt &&
- CE->getOperand(0)->getType()->getTypeID() == Type::IntegerTyID) {
- IMPL_SIGN_EXTENSION(CE->getOperand(0)->getType(),
- printConstant(CE->getOperand(0)));
- }
- else if (CE->getOpcode() == Instruction::ZExt &&
- CE->getOperand(0)->getType()->getTypeID() == Type::IntegerTyID){
- const IntegerType* IntTy =
- cast<IntegerType>(CE->getOperand(0)->getType());
- uint64_t BitMask = IntTy->getBitMask();
- writeOperand(CE->getOperand(0));
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- else
- printConstant(CE->getOperand(0));
- Out << ")";
+ printConstant(CE->getOperand(0), Static);
+ if (CE->getType() == Type::getInt1Ty(CPV->getContext()) &&
+ (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 << ')';
return;
+
case Instruction::GetElementPtr:
- Out << "(&(";
- printIndexingExpression(CE->getOperand(0), gep_type_begin(CPV),
- gep_type_end(CPV));
- Out << "))";
+ Out << "(";
+ printGEPExpression(CE->getOperand(0), gep_type_begin(CPV),
+ gep_type_end(CPV), Static);
+ Out << ")";
return;
case Instruction::Select:
Out << '(';
- printConstant(CE->getOperand(0));
+ printConstant(CE->getOperand(0), Static);
Out << '?';
- printConstant(CE->getOperand(1));
+ printConstant(CE->getOperand(1), Static);
Out << ':';
- printConstant(CE->getOperand(2));
+ printConstant(CE->getOperand(2), Static);
Out << ')';
return;
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
case Instruction::AShr:
{
Out << '(';
- bool NeedsClosingParens = printConstExprCast(CE);
+ bool NeedsClosingParens = printConstExprCast(CE, Static);
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
switch (CE->getOpcode()) {
- case Instruction::Add: Out << " + "; break;
- case Instruction::Sub: Out << " - "; break;
- case Instruction::Mul: Out << " * "; break;
+ case Instruction::Add:
+ case Instruction::FAdd: Out << " + "; break;
+ case Instruction::Sub:
+ case Instruction::FSub: Out << " - "; break;
+ case Instruction::Mul:
+ case Instruction::FMul: Out << " * "; break;
case Instruction::URem:
case Instruction::SRem:
case Instruction::FRem: Out << " % "; break;
case ICmpInst::ICMP_UGT: Out << " > "; break;
case ICmpInst::ICMP_SGE:
case ICmpInst::ICMP_UGE: Out << " >= "; break;
- default: assert(0 && "Illegal ICmp predicate");
+ default: llvm_unreachable("Illegal ICmp predicate");
}
break;
- default: assert(0 && "Illegal opcode here!");
+ default: llvm_unreachable("Illegal opcode here!");
}
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
if (NeedsClosingParens)
}
case Instruction::FCmp: {
Out << '(';
- bool NeedsClosingParens = printConstExprCast(CE);
+ bool NeedsClosingParens = printConstExprCast(CE, Static);
if (CE->getPredicate() == FCmpInst::FCMP_FALSE)
Out << "0";
else if (CE->getPredicate() == FCmpInst::FCMP_TRUE)
else {
const char* op = 0;
switch (CE->getPredicate()) {
- default: assert(0 && "Illegal FCmp predicate");
+ default: llvm_unreachable("Illegal FCmp predicate");
case FCmpInst::FCMP_ORD: op = "ord"; break;
case FCmpInst::FCMP_UNO: op = "uno"; break;
case FCmpInst::FCMP_UEQ: op = "ueq"; break;
if (NeedsClosingParens)
Out << "))";
Out << ')';
+ return;
}
default:
- cerr << "CWriter Error: Unhandled constant expression: "
+#ifndef NDEBUG
+ errs() << "CWriter Error: Unhandled constant expression: "
<< *CE << "\n";
- abort();
+#endif
+ llvm_unreachable(0);
}
- } else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
+ } else if (isa<UndefValue>(CPV) && CPV->getType()->isSingleValueType()) {
Out << "((";
printType(Out, CPV->getType()); // sign doesn't matter
- Out << ")/*UNDEF*/0)";
+ Out << ")/*UNDEF*/";
+ if (!isa<VectorType>(CPV->getType())) {
+ Out << "0)";
+ } else {
+ Out << "{})";
+ }
return;
}
if (ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
const Type* Ty = CI->getType();
- if (Ty == Type::Int1Ty)
- Out << (CI->getZExtValue() ? '1' : '0') ;
+ if (Ty == Type::getInt1Ty(CPV->getContext()))
+ Out << (CI->getZExtValue() ? '1' : '0');
+ else if (Ty == Type::getInt32Ty(CPV->getContext()))
+ Out << CI->getZExtValue() << 'u';
+ else if (Ty->getPrimitiveSizeInBits() > 32)
+ Out << CI->getZExtValue() << "ull";
else {
Out << "((";
printSimpleType(Out, Ty, false) << ')';
Out << CI->getZExtValue() << 'u';
else
Out << CI->getSExtValue();
- if (Ty->getPrimitiveSizeInBits() > 32)
- Out << "ll";
Out << ')';
}
return;
switch (CPV->getType()->getTypeID()) {
case Type::FloatTyID:
- case Type::DoubleTyID: {
+ case Type::DoubleTyID:
+ case Type::X86_FP80TyID:
+ case Type::PPC_FP128TyID:
+ case Type::FP128TyID: {
ConstantFP *FPC = cast<ConstantFP>(CPV);
std::map<const ConstantFP*, unsigned>::iterator I = FPConstantMap.find(FPC);
if (I != FPConstantMap.end()) {
// Because of FP precision problems we must load from a stack allocated
// value that holds the value in hex.
- Out << "(*(" << (FPC->getType() == Type::FloatTy ? "float" : "double")
+ Out << "(*(" << (FPC->getType() == Type::getFloatTy(CPV->getContext()) ?
+ "float" :
+ FPC->getType() == Type::getDoubleTy(CPV->getContext()) ?
+ "double" :
+ "long double")
<< "*)&FPConstant" << I->second << ')';
} else {
- if (IsNAN(FPC->getValue())) {
+ double V;
+ if (FPC->getType() == Type::getFloatTy(CPV->getContext()))
+ V = FPC->getValueAPF().convertToFloat();
+ else if (FPC->getType() == Type::getDoubleTy(CPV->getContext()))
+ V = FPC->getValueAPF().convertToDouble();
+ else {
+ // Long double. Convert the number to double, discarding precision.
+ // This is not awesome, but it at least makes the CBE output somewhat
+ // useful.
+ APFloat Tmp = FPC->getValueAPF();
+ bool LosesInfo;
+ Tmp.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &LosesInfo);
+ V = Tmp.convertToDouble();
+ }
+
+ if (IsNAN(V)) {
// The value is NaN
+ // FIXME the actual NaN bits should be emitted.
// The prefix for a quiet NaN is 0x7FF8. For a signalling NaN,
// it's 0x7ff4.
const unsigned long QuietNaN = 0x7ff8UL;
// We need to grab the first part of the FP #
char Buffer[100];
- uint64_t ll = DoubleToBits(FPC->getValue());
+ uint64_t ll = DoubleToBits(V);
sprintf(Buffer, "0x%llx", static_cast<long long>(ll));
std::string Num(&Buffer[0], &Buffer[6]);
unsigned long Val = strtoul(Num.c_str(), 0, 16);
- if (FPC->getType() == Type::FloatTy)
+ if (FPC->getType() == Type::getFloatTy(FPC->getContext()))
Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "F(\""
<< Buffer << "\") /*nan*/ ";
else
Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "(\""
<< Buffer << "\") /*nan*/ ";
- } else if (IsInf(FPC->getValue())) {
+ } else if (IsInf(V)) {
// The value is Inf
- if (FPC->getValue() < 0) Out << '-';
- Out << "LLVM_INF" << (FPC->getType() == Type::FloatTy ? "F" : "")
+ if (V < 0) Out << '-';
+ Out << "LLVM_INF" <<
+ (FPC->getType() == Type::getFloatTy(FPC->getContext()) ? "F" : "")
<< " /*inf*/ ";
} else {
std::string Num;
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
// Print out the constant as a floating point number.
char Buffer[100];
- sprintf(Buffer, "%a", FPC->getValue());
+ sprintf(Buffer, "%a", V);
Num = Buffer;
#else
- Num = ftostr(FPC->getValue());
+ Num = ftostr(FPC->getValueAPF());
#endif
- Out << Num;
+ Out << Num;
}
}
break;
}
case Type::ArrayTyID:
- if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) {
+ // Use C99 compound expression literal initializer syntax.
+ if (!Static) {
+ Out << "(";
+ printType(Out, CPV->getType());
+ Out << ")";
+ }
+ Out << "{ "; // Arrays are wrapped in struct types.
+ if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
+ printConstantArray(CA, Static);
+ } else {
+ assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
const ArrayType *AT = cast<ArrayType>(CPV->getType());
Out << '{';
if (AT->getNumElements()) {
Out << ' ';
Constant *CZ = Constant::getNullValue(AT->getElementType());
- printConstant(CZ);
+ printConstant(CZ, Static);
for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) {
Out << ", ";
- printConstant(CZ);
+ printConstant(CZ, Static);
}
}
Out << " }";
- } else {
- printConstantArray(cast<ConstantArray>(CPV));
}
+ Out << " }"; // Arrays are wrapped in struct types.
break;
case Type::VectorTyID:
- if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) {
- const VectorType *AT = cast<VectorType>(CPV->getType());
- Out << '{';
- if (AT->getNumElements()) {
- Out << ' ';
- Constant *CZ = Constant::getNullValue(AT->getElementType());
- printConstant(CZ);
- for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) {
- Out << ", ";
- printConstant(CZ);
- }
+ // Use C99 compound expression literal initializer syntax.
+ if (!Static) {
+ Out << "(";
+ printType(Out, CPV->getType());
+ Out << ")";
+ }
+ if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
+ printConstantVector(CV, Static);
+ } else {
+ assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
+ const VectorType *VT = cast<VectorType>(CPV->getType());
+ Out << "{ ";
+ Constant *CZ = Constant::getNullValue(VT->getElementType());
+ printConstant(CZ, Static);
+ for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) {
+ Out << ", ";
+ printConstant(CZ, Static);
}
Out << " }";
- } else {
- printConstantVector(cast<ConstantVector>(CPV));
}
break;
case Type::StructTyID:
+ // Use C99 compound expression literal initializer syntax.
+ if (!Static) {
+ Out << "(";
+ printType(Out, CPV->getType());
+ Out << ")";
+ }
if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) {
const StructType *ST = cast<StructType>(CPV->getType());
Out << '{';
if (ST->getNumElements()) {
Out << ' ';
- printConstant(Constant::getNullValue(ST->getElementType(0)));
+ printConstant(Constant::getNullValue(ST->getElementType(0)), Static);
for (unsigned i = 1, e = ST->getNumElements(); i != e; ++i) {
Out << ", ";
- printConstant(Constant::getNullValue(ST->getElementType(i)));
+ printConstant(Constant::getNullValue(ST->getElementType(i)), Static);
}
}
Out << " }";
Out << '{';
if (CPV->getNumOperands()) {
Out << ' ';
- printConstant(cast<Constant>(CPV->getOperand(0)));
+ printConstant(cast<Constant>(CPV->getOperand(0)), Static);
for (unsigned i = 1, e = CPV->getNumOperands(); i != e; ++i) {
Out << ", ";
- printConstant(cast<Constant>(CPV->getOperand(i)));
+ printConstant(cast<Constant>(CPV->getOperand(i)), Static);
}
}
Out << " }";
Out << ")/*NULL*/0)";
break;
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) {
- writeOperand(GV);
+ writeOperand(GV, Static);
break;
}
// FALL THROUGH
default:
- cerr << "Unknown constant type: " << *CPV << "\n";
- abort();
+#ifndef NDEBUG
+ errs() << "Unknown constant type: " << *CPV << "\n";
+#endif
+ llvm_unreachable(0);
}
}
// 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) {
+bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) {
bool NeedsExplicitCast = false;
const Type *Ty = CE->getOperand(0)->getType();
bool TypeIsSigned = false;
switch (CE->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ // We need to cast integer arithmetic so that it is always performed
+ // as unsigned, to avoid undefined behavior on overflow.
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = true; break;
}
if (NeedsExplicitCast) {
Out << "((";
- if (Ty->isInteger() && Ty != Type::Int1Ty)
+ if (Ty->isIntegerTy() && Ty != Type::getInt1Ty(Ty->getContext()))
printSimpleType(Out, Ty, TypeIsSigned);
else
printType(Out, Ty); // not integer, sign doesn't matter
default:
// for most instructions, it doesn't matter
break;
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ // We need to cast integer arithmetic so that it is always performed
+ // as unsigned, to avoid undefined behavior on overflow.
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem:
Out << "((";
printSimpleType(Out, OpTy, typeIsSigned);
Out << ")";
- printConstant(CPV);
+ printConstant(CPV, false);
Out << ")";
} else
- printConstant(CPV);
+ printConstant(CPV, false);
}
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;
+ // Mangle globals with the standard mangler interface for LLC compatibility.
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(Operand)) {
+ SmallString<128> Str;
+ Mang->getNameWithPrefix(Str, GV, false);
+ return CBEMangle(Str.str().str());
+ }
+
+ std::string Name = Operand->getName();
+
+ if (Name.empty()) { // Assign unique names to local temporaries.
+ unsigned &No = AnonValueNumbers[Operand];
+ if (No == 0)
+ No = ++NextAnonValueNumber;
+ Name = "tmp__" + utostr(No);
+ }
+
+ std::string VarName;
+ VarName.reserve(Name.capacity());
- if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') || ch == '_'))
- VarName += '_';
- else
- VarName += ch;
- }
+ for (std::string::iterator I = Name.begin(), E = Name.end();
+ I != E; ++I) {
+ char ch = *I;
- Name = "llvm_cbe_" + VarName;
- } else {
- Name = Mang->getValueName(Operand);
+ if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') || ch == '_')) {
+ char buffer[5];
+ sprintf(buffer, "_%x_", ch);
+ VarName += buffer;
+ } else
+ VarName += ch;
}
- return Name;
+ return "llvm_cbe_" + VarName;
+}
+
+/// writeInstComputationInline - Emit the computation for the specified
+/// instruction inline, with no destination provided.
+void CWriter::writeInstComputationInline(Instruction &I) {
+ // We can't currently support integer types other than 1, 8, 16, 32, 64.
+ // Validate this.
+ const Type *Ty = I.getType();
+ if (Ty->isIntegerTy() && (Ty!=Type::getInt1Ty(I.getContext()) &&
+ Ty!=Type::getInt8Ty(I.getContext()) &&
+ Ty!=Type::getInt16Ty(I.getContext()) &&
+ Ty!=Type::getInt32Ty(I.getContext()) &&
+ Ty!=Type::getInt64Ty(I.getContext()))) {
+ llvm_report_error("The C backend does not currently support integer "
+ "types of widths other than 1, 8, 16, 32, 64.\n"
+ "This is being tracked as PR 4158.");
+ }
+
+ // If this is a non-trivial bool computation, make sure to truncate down to
+ // a 1 bit value. This is important because we want "add i1 x, y" to return
+ // "0" when x and y are true, not "2" for example.
+ bool NeedBoolTrunc = false;
+ if (I.getType() == Type::getInt1Ty(I.getContext()) &&
+ !isa<ICmpInst>(I) && !isa<FCmpInst>(I))
+ NeedBoolTrunc = true;
+
+ if (NeedBoolTrunc)
+ Out << "((";
+
+ visit(I);
+
+ if (NeedBoolTrunc)
+ Out << ")&1)";
}
-void CWriter::writeOperandInternal(Value *Operand) {
+
+void CWriter::writeOperandInternal(Value *Operand, bool Static) {
if (Instruction *I = dyn_cast<Instruction>(Operand))
+ // Should we inline this instruction to build a tree?
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
- // Should we inline this instruction to build a tree?
Out << '(';
- visit(*I);
+ writeInstComputationInline(*I);
Out << ')';
return;
}
Constant* CPV = dyn_cast<Constant>(Operand);
if (CPV && !isa<GlobalValue>(CPV))
- printConstant(CPV);
+ printConstant(CPV, Static);
else
Out << GetValueName(Operand);
}
-void CWriter::writeOperandRaw(Value *Operand) {
- Constant* CPV = dyn_cast<Constant>(Operand);
- if (CPV && !isa<GlobalValue>(CPV)) {
- printConstant(CPV);
- } else {
- Out << GetValueName(Operand);
- }
-}
-
-void CWriter::writeOperand(Value *Operand) {
- if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+void CWriter::writeOperand(Value *Operand, bool Static) {
+ bool isAddressImplicit = isAddressExposed(Operand);
+ if (isAddressImplicit)
Out << "(&"; // Global variables are referenced as their addresses by llvm
- writeOperandInternal(Operand);
+ writeOperandInternal(Operand, Static);
- if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+ if (isAddressImplicit)
Out << ')';
}
bool CWriter::writeInstructionCast(const Instruction &I) {
const Type *Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ // We need to cast integer arithmetic so that it is always performed
+ // as unsigned, to avoid undefined behavior on overflow.
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv:
default:
// for most instructions, it doesn't matter
break;
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ // We need to cast integer arithmetic so that it is always performed
+ // as unsigned, to avoid undefined behavior on overflow.
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem: // Cast to unsigned first
shouldCast = true;
castIsSigned = false;
break;
+ case Instruction::GetElementPtr:
case Instruction::AShr:
case Instruction::SDiv:
case Instruction::SRem: // Cast to signed first
Out << "((";
printSimpleType(Out, OpTy, castIsSigned);
Out << ")";
- if (castIsSigned && OpTy->getTypeID() == Type::IntegerTyID) {
- IMPL_SIGN_EXTENSION(OpTy, writeOperand(Operand));
- }
- else
- writeOperand(Operand);
+ writeOperand(Operand);
Out << ")";
} else
writeOperand(Operand);
// Write the operand with a cast to another type based on the icmp predicate
// being used.
-void CWriter::writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate) {
+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();
- // Extract the operand's type, we'll need it.
- const Type* OpTy = Operand->getType();
+ // Write out the casted operand if we should, otherwise just write the
+ // operand.
+ if (!shouldCast) {
+ writeOperand(Operand);
+ return;
+ }
+
+ // Should this be a signed comparison? If so, convert to signed.
+ bool castIsSigned = Cmp.isSigned();
- // Indicate whether to do the cast or not.
- bool shouldCast = false;
-
- // Indicate whether the cast should be to a signed type or not.
- bool castIsSigned = false;
-
- // 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 (predicate) {
- default:
- // for eq and ne, it doesn't matter
- break;
- case ICmpInst::ICMP_EQ:
- case ICmpInst::ICMP_NE:
- case ICmpInst::ICMP_UGT:
- case ICmpInst::ICMP_UGE:
- case ICmpInst::ICMP_ULT:
- case ICmpInst::ICMP_ULE:
- shouldCast = true;
- break;
- case ICmpInst::ICMP_SGT:
- case ICmpInst::ICMP_SGE:
- case ICmpInst::ICMP_SLT:
- case ICmpInst::ICMP_SLE:
- shouldCast = true;
- castIsSigned = true;
- break;
- }
-
- // Write out the casted operand if we should, otherwise just write the
- // operand.
- if (shouldCast) {
- Out << "((";
- if (OpTy->isInteger() && OpTy != Type::Int1Ty)
- printSimpleType(Out, OpTy, castIsSigned);
- else
- printType(Out, OpTy); // not integer, sign doesn't matter
- Out << ")";
- if(castIsSigned && OpTy->getTypeID() == Type::IntegerTyID) {
- IMPL_SIGN_EXTENSION(OpTy, writeOperand(Operand));
- } else {
- writeOperand(Operand);
- if(OpTy->getTypeID() == Type::IntegerTyID){
- const IntegerType * IntTy = cast<IntegerType>(OpTy);
- uint64_t BitMask = IntTy->getBitMask();
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- }
- Out << ")";
- } else {
- writeOperand(Operand);
- if(OpTy->getTypeID() == Type::IntegerTyID){
- const IntegerType * IntTy = cast<IntegerType>(OpTy);
- uint64_t BitMask = IntTy->getBitMask();
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- }
-}
+ // If the operand was a pointer, convert to a large integer type.
+ const Type* OpTy = Operand->getType();
+ if (isa<PointerType>(OpTy))
+ OpTy = TD->getIntPtrType(Operand->getContext());
+
+ Out << "((";
+ printSimpleType(Out, OpTy, castIsSigned);
+ Out << ")";
+ writeOperand(Operand);
+ Out << ")";
+}
// generateCompilerSpecificCode - This is where we add conditional compilation
// directives to cater to specific compilers as need be.
//
-static void generateCompilerSpecificCode(std::ostream& Out) {
+static void generateCompilerSpecificCode(formatted_raw_ostream& Out,
+ const TargetData *TD) {
// Alloca is hard to get, and we don't want to include stdlib.h here.
Out << "/* get a declaration for alloca */\n"
<< "#if defined(__CYGWIN__) || defined(__MINGW32__)\n"
<< "#define alloca(x) __builtin_alloca((x))\n"
- << "#define _alloca(x) __builtin_alloca((x))\n"
+ << "#define _alloca(x) __builtin_alloca((x))\n"
<< "#elif defined(__APPLE__)\n"
<< "extern void *__builtin_alloca(unsigned long);\n"
<< "#define alloca(x) __builtin_alloca(x)\n"
<< "extern void *__builtin_alloca(unsigned int);\n"
<< "#endif\n"
<< "#define alloca(x) __builtin_alloca(x)\n"
- << "#elif defined(__FreeBSD__) || defined(__OpenBSD__)\n"
+ << "#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__arm__)\n"
<< "#define alloca(x) __builtin_alloca(x)\n"
<< "#elif defined(_MSC_VER)\n"
<< "#define inline _inline\n"
<< "#define __ATTRIBUTE_DTOR__\n"
<< "#define LLVM_ASM(X)\n"
<< "#endif\n\n";
+
+ 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";
+
+ // Output typedefs for 128-bit integers. If these are needed with a
+ // 32-bit target or with a C compiler that doesn't support mode(TI),
+ // more drastic measures will be needed.
+ Out << "#if __GNUC__ && __LP64__ /* 128-bit integer types */\n"
+ << "typedef int __attribute__((mode(TI))) llvmInt128;\n"
+ << "typedef unsigned __attribute__((mode(TI))) llvmUInt128;\n"
+ << "#endif\n\n";
// Output target-specific code that should be inserted into main.
Out << "#define CODE_FOR_MAIN() /* Any target-specific code for main()*/\n";
- // On X86, set the FP control word to 64-bits of precision instead of 80 bits.
- Out << "#if defined(__GNUC__) && !defined(__llvm__)\n"
- << "#if defined(i386) || defined(__i386__) || defined(__i386) || "
- << "defined(__x86_64__)\n"
- << "#undef CODE_FOR_MAIN\n"
- << "#define CODE_FOR_MAIN() \\\n"
- << " {short F;__asm__ (\"fnstcw %0\" : \"=m\" (*&F)); \\\n"
- << " F=(F&~0x300)|0x200;__asm__(\"fldcw %0\"::\"m\"(*&F));}\n"
- << "#endif\n#endif\n";
-
}
/// FindStaticTors - Given a static ctor/dtor list, unpack its contents into
return GlobalDtors;
}
- // Otherwise, it it is other metadata, don't print it. This catches things
+ // Otherwise, if it is other metadata, don't print it. This catches things
// like debug information.
if (GV->getSection() == "llvm.metadata")
return NotPrinted;
return NotSpecial;
}
+// PrintEscapedString - Print each character of the specified string, escaping
+// it if it is not printable or if it is an escape char.
+static void PrintEscapedString(const char *Str, unsigned Length,
+ raw_ostream &Out) {
+ for (unsigned i = 0; i != Length; ++i) {
+ unsigned char C = Str[i];
+ if (isprint(C) && C != '\\' && C != '"')
+ Out << C;
+ else if (C == '\\')
+ Out << "\\\\";
+ else if (C == '\"')
+ Out << "\\\"";
+ else if (C == '\t')
+ Out << "\\t";
+ else
+ Out << "\\x" << hexdigit(C >> 4) << hexdigit(C & 0x0F);
+ }
+}
+
+// PrintEscapedString - Print each character of the specified string, escaping
+// it if it is not printable or if it is an escape char.
+static void PrintEscapedString(const std::string &Str, raw_ostream &Out) {
+ PrintEscapedString(Str.c_str(), Str.size(), Out);
+}
bool CWriter::doInitialization(Module &M) {
+ FunctionPass::doInitialization(M);
+
// Initialize
TheModule = &M;
IL = new IntrinsicLowering(*TD);
IL->AddPrototypes(M);
- // Ensure that all structure types have names...
- Mang = new Mangler(M);
- Mang->markCharUnacceptable('.');
+#if 0
+ std::string Triple = TheModule->getTargetTriple();
+ if (Triple.empty())
+ Triple = llvm::sys::getHostTriple();
+
+ std::string E;
+ if (const Target *Match = TargetRegistry::lookupTarget(Triple, E))
+ TAsm = Match->createAsmInfo(Triple);
+#endif
+ TAsm = new CBEMCAsmInfo();
+ Mang = new Mangler(*TAsm);
// Keep track of which functions are static ctors/dtors so they can have
// an attribute added to their prototypes.
Out << "/* Provide Declarations */\n";
Out << "#include <stdarg.h>\n"; // Varargs support
Out << "#include <setjmp.h>\n"; // Unwind support
- generateCompilerSpecificCode(Out);
+ generateCompilerSpecificCode(Out, TD);
// Provide a definition for `bool' if not compiling with a C++ compiler.
Out << "\n"
<< "\n\n/* Support for floating point constants */\n"
<< "typedef unsigned long long ConstantDoubleTy;\n"
<< "typedef unsigned int ConstantFloatTy;\n"
-
+ << "typedef struct { unsigned long long f1; unsigned short f2; "
+ "unsigned short pad[3]; } ConstantFP80Ty;\n"
+ // This is used for both kinds of 128-bit long double; meaning differs.
+ << "typedef struct { unsigned long long f1; unsigned long long f2; }"
+ " ConstantFP128Ty;\n"
<< "\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.
//
+ if (!M.getModuleInlineAsm().empty()) {
+ Out << "/* Module asm statements */\n"
+ << "asm(";
+
+ // Split the string into lines, to make it easier to read the .ll file.
+ std::string Asm = M.getModuleInlineAsm();
+ size_t CurPos = 0;
+ size_t NewLine = Asm.find_first_of('\n', CurPos);
+ while (NewLine != std::string::npos) {
+ // We found a newline, print the portion of the asm string from the
+ // last newline up to this newline.
+ Out << "\"";
+ PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine),
+ Out);
+ Out << "\\n\"\n";
+ CurPos = NewLine+1;
+ NewLine = Asm.find_first_of('\n', CurPos);
+ }
+ Out << "\"";
+ PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out);
+ Out << "\");\n"
+ << "/* End Module asm statements */\n";
+ }
// Loop over the symbol table, emitting all named constants...
printModuleTypes(M.getTypeSymbolTable());
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
- if (I->hasExternalLinkage() || I->hasExternalWeakLinkage())
+ if (I->hasExternalLinkage() || I->hasExternalWeakLinkage() ||
+ I->hasCommonLinkage())
Out << "extern ";
else if (I->hasDLLImportLinkage())
Out << "__declspec(dllimport) ";
Out << "\n/* Function Declarations */\n";
Out << "double fmod(double, double);\n"; // Support for FP rem
Out << "float fmodf(float, float);\n";
+ Out << "long double fmodl(long double, long double);\n";
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
// Don't print declarations for intrinsic functions.
- if (!I->getIntrinsicID() && I->getName() != "setjmp" &&
+ if (!I->isIntrinsic() && I->getName() != "setjmp" &&
I->getName() != "longjmp" && I->getName() != "_setjmp") {
if (I->hasExternalWeakLinkage())
Out << "extern ";
Out << " __HIDDEN__";
if (I->hasName() && I->getName()[0] == 1)
- Out << " LLVM_ASM(\"" << I->getName().c_str()+1 << "\")";
+ Out << " LLVM_ASM(\"" << I->getName().substr(1) << "\")";
Out << ";\n";
}
if (getGlobalVariableClass(I))
continue;
- if (I->hasInternalLinkage())
+ if (I->hasLocalLinkage())
Out << "static ";
else
Out << "extern ";
if (I->hasLinkOnceLinkage())
Out << " __attribute__((common))";
+ else if (I->hasCommonLinkage()) // FIXME is this right?
+ Out << " __ATTRIBUTE_WEAK__";
else if (I->hasWeakLinkage())
Out << " __ATTRIBUTE_WEAK__";
else if (I->hasExternalWeakLinkage())
if (getGlobalVariableClass(I))
continue;
- if (I->hasInternalLinkage())
+ if (I->hasLocalLinkage())
Out << "static ";
else if (I->hasDLLImportLinkage())
Out << "__declspec(dllimport) ";
Out << " __attribute__((common))";
else if (I->hasWeakLinkage())
Out << " __ATTRIBUTE_WEAK__";
+ else if (I->hasCommonLinkage())
+ Out << " __ATTRIBUTE_WEAK__";
if (I->hasHiddenVisibility())
Out << " __HIDDEN__";
// 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.
+ // FIXME common linkage should avoid this problem.
if (!I->getInitializer()->isNullValue()) {
Out << " = " ;
- writeOperand(I->getInitializer());
+ writeOperand(I->getInitializer(), true);
} 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()) ||
- isa<ArrayType>(I->getInitializer()->getType()) ||
isa<VectorType>(I->getInitializer()->getType())) {
Out << "{ 0 }";
+ } else if (isa<ArrayType>(I->getInitializer()->getType())) {
+ // As with structs and vectors, but with an extra set of braces
+ // because arrays are wrapped in structs.
+ Out << "{ { 0 } }";
} else {
// Just print it out normally.
- writeOperand(I->getInitializer());
+ writeOperand(I->getInitializer(), true);
}
}
Out << ";\n";
// the precision of the printed form, unless the printed form preserves
// precision.
//
- 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)) {
- double Val = FPC->getValue();
-
- FPConstantMap[FPC] = FPCounter; // Number the FP constants
-
- if (FPC->getType() == Type::DoubleTy) {
- Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
- << " = 0x" << std::hex << DoubleToBits(Val) << std::dec
- << "ULL; /* " << Val << " */\n";
- } else if (FPC->getType() == Type::FloatTy) {
- Out << "static const ConstantFloatTy FPConstant" << FPCounter++
- << " = 0x" << std::hex << FloatToBits(Val) << std::dec
- << "U; /* " << Val << " */\n";
- } else
- assert(0 && "Unknown float type!");
- }
+ printFloatingPointConstants(*I);
Out << '\n';
}
+void CWriter::printFloatingPointConstants(const Constant *C) {
+ // If this is a constant expression, recursively check for constant fp values.
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+ for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
+ printFloatingPointConstants(CE->getOperand(i));
+ return;
+ }
+
+ // Otherwise, check for a FP constant that we need to print.
+ const ConstantFP *FPC = dyn_cast<ConstantFP>(C);
+ if (FPC == 0 ||
+ // Do not put in FPConstantMap if safe.
+ isFPCSafeToPrint(FPC) ||
+ // Already printed this constant?
+ FPConstantMap.count(FPC))
+ return;
+
+ FPConstantMap[FPC] = FPCounter; // Number the FP constants
+
+ if (FPC->getType() == Type::getDoubleTy(FPC->getContext())) {
+ double Val = FPC->getValueAPF().convertToDouble();
+ uint64_t i = FPC->getValueAPF().bitcastToAPInt().getZExtValue();
+ Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
+ << " = 0x" << utohexstr(i)
+ << "ULL; /* " << Val << " */\n";
+ } else if (FPC->getType() == Type::getFloatTy(FPC->getContext())) {
+ float Val = FPC->getValueAPF().convertToFloat();
+ uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt().
+ getZExtValue();
+ Out << "static const ConstantFloatTy FPConstant" << FPCounter++
+ << " = 0x" << utohexstr(i)
+ << "U; /* " << Val << " */\n";
+ } else if (FPC->getType() == Type::getX86_FP80Ty(FPC->getContext())) {
+ // api needed to prevent premature destruction
+ APInt api = FPC->getValueAPF().bitcastToAPInt();
+ const uint64_t *p = api.getRawData();
+ Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
+ << " = { 0x" << utohexstr(p[0])
+ << "ULL, 0x" << utohexstr((uint16_t)p[1]) << ",{0,0,0}"
+ << "}; /* Long double constant */\n";
+ } else if (FPC->getType() == Type::getPPC_FP128Ty(FPC->getContext()) ||
+ FPC->getType() == Type::getFP128Ty(FPC->getContext())) {
+ APInt api = FPC->getValueAPF().bitcastToAPInt();
+ const uint64_t *p = api.getRawData();
+ Out << "static const ConstantFP128Ty FPConstant" << FPCounter++
+ << " = { 0x"
+ << utohexstr(p[0]) << ", 0x" << utohexstr(p[1])
+ << "}; /* Long double constant */\n";
+
+ } else {
+ llvm_unreachable("Unknown float type!");
+ }
+}
+
+
/// printSymbolTable - Run through symbol table looking for type names. If a
/// type name is found, emit its declaration...
// Print out forward declarations for structure types before anything else!
Out << "/* Structure forward decls */\n";
for (; I != End; ++I) {
- std::string Name = "struct l_" + Mang->makeNameProper(I->first);
+ std::string Name = "struct " + CBEMangle("l_"+I->first);
Out << Name << ";\n";
TypeNames.insert(std::make_pair(I->second, Name));
}
// for struct or opaque types.
Out << "/* Typedefs */\n";
for (I = TST.begin(); I != End; ++I) {
- std::string Name = "l_" + Mang->makeNameProper(I->first);
+ std::string Name = CBEMangle("l_"+I->first);
Out << "typedef ";
printType(Out, I->second, false, Name);
Out << ";\n";
Out << '\n';
// Keep track of which structures have been printed so far...
- std::set<const StructType *> StructPrinted;
+ std::set<const Type *> StructPrinted;
// Loop over all structures then push them into the stack so they are
// printed in the correct order.
//
Out << "/* Structure contents */\n";
for (I = TST.begin(); I != End; ++I)
- if (const StructType *STy = dyn_cast<StructType>(I->second))
+ if (isa<StructType>(I->second) || isa<ArrayType>(I->second))
// Only print out used types!
- printContainedStructs(STy, StructPrinted);
+ printContainedStructs(I->second, StructPrinted);
}
// Push the struct onto the stack and recursively push all structs
// TODO: Make this work properly with vector types
//
void CWriter::printContainedStructs(const Type *Ty,
- std::set<const StructType*> &StructPrinted){
+ std::set<const Type*> &StructPrinted) {
// Don't walk through pointers.
- if (isa<PointerType>(Ty) || Ty->isPrimitiveType() || Ty->isInteger()) return;
+ if (isa<PointerType>(Ty) || Ty->isPrimitiveType() || Ty->isIntegerTy())
+ return;
// Print all contained types first.
for (Type::subtype_iterator I = Ty->subtype_begin(),
E = Ty->subtype_end(); I != E; ++I)
printContainedStructs(*I, StructPrinted);
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (isa<StructType>(Ty) || isa<ArrayType>(Ty)) {
// Check to see if we have already printed this struct.
- if (StructPrinted.insert(STy).second) {
+ if (StructPrinted.insert(Ty).second) {
// Print structure type out.
- std::string Name = TypeNames[STy];
- printType(Out, STy, false, Name, true);
+ std::string Name = TypeNames[Ty];
+ printType(Out, Ty, false, Name, true);
Out << ";\n\n";
}
}
void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
/// isStructReturn - Should this function actually return a struct by-value?
- bool isStructReturn = F->getFunctionType()->isStructReturn();
+ bool isStructReturn = F->hasStructRetAttr();
- if (F->hasInternalLinkage()) Out << "static ";
+ if (F->hasLocalLinkage()) Out << "static ";
if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) ";
if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) ";
switch (F->getCallingConv()) {
case CallingConv::X86_StdCall:
- Out << "__stdcall ";
+ Out << "__attribute__((stdcall)) ";
break;
case CallingConv::X86_FastCall:
- Out << "__fastcall ";
+ Out << "__attribute__((fastcall)) ";
+ break;
+ default:
break;
}
// Loop over the arguments, printing them...
const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
- const ParamAttrsList *Attrs = FT->getParamAttrs();
+ const AttrListPtr &PAL = F->getAttributes();
std::stringstream FunctionInnards;
if (!F->isDeclaration()) {
if (!F->arg_empty()) {
Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
+ unsigned Idx = 1;
// If this is a struct-return function, don't print the hidden
// struct-return argument.
if (isStructReturn) {
assert(I != E && "Invalid struct return function!");
++I;
+ ++Idx;
}
std::string ArgName;
- unsigned Idx = 1;
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
if (I->hasName() || !Prototype)
ArgName = GetValueName(I);
else
ArgName = "";
- printType(FunctionInnards, I->getType(),
- /*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt),
+ const Type *ArgTy = I->getType();
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ ByValParams.insert(I);
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt),
ArgName);
PrintedArg = true;
++Idx;
} else {
// Loop over the arguments, printing them.
FunctionType::param_iterator I = FT->param_begin(), E = FT->param_end();
+ unsigned Idx = 1;
// If this is a struct-return function, don't print the hidden
// struct-return argument.
if (isStructReturn) {
assert(I != E && "Invalid struct return function!");
++I;
+ ++Idx;
}
- unsigned Idx = 1;
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
- printType(FunctionInnards, *I,
- /*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt));
+ const Type *ArgTy = *I;
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt));
PrintedArg = true;
++Idx;
}
// Print out the return type and the signature built above.
printType(Out, RetTy,
- /*isSigned=*/ Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt),
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt),
FunctionInnards.str());
}
return false;
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DstTy = I.getType();
- return (SrcTy->isFloatingPoint() && DstTy->isInteger()) ||
- (DstTy->isFloatingPoint() && SrcTy->isInteger());
+ return (SrcTy->isFloatingPointTy() && DstTy->isIntegerTy()) ||
+ (DstTy->isFloatingPointTy() && SrcTy->isIntegerTy());
}
void CWriter::printFunction(Function &F) {
/// isStructReturn - Should this function actually return a struct by-value?
- bool isStructReturn = F.getFunctionType()->isStructReturn();
+ bool isStructReturn = F.hasStructRetAttr();
printFunctionSignature(&F, false);
Out << " {\n";
printType(Out, AI->getAllocatedType(), false, GetValueName(AI));
Out << "; /* Address-exposed local */\n";
PrintedVar = true;
- } else if (I->getType() != Type::VoidTy && !isInlinableInst(*I)) {
+ } else if (I->getType() != Type::getVoidTy(F.getContext()) &&
+ !isInlinableInst(*I)) {
Out << " ";
printType(Out, I->getType(), false, GetValueName(&*I));
Out << ";\n";
for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E;
++II) {
if (!isInlinableInst(*II) && !isDirectAlloca(II)) {
- if (II->getType() != Type::VoidTy && !isInlineAsm(*II))
+ if (II->getType() != Type::getVoidTy(BB->getContext()) &&
+ !isInlineAsm(*II))
outputLValue(II);
else
Out << " ";
- visit(*II);
+ writeInstComputationInline(*II);
Out << ";\n";
}
}
- // Don't emit prefix or suffix for the terminator...
+ // Don't emit prefix or suffix for the terminator.
visit(*BB->getTerminator());
}
//
void CWriter::visitReturnInst(ReturnInst &I) {
// If this is a struct return function, return the temporary struct.
- bool isStructReturn = I.getParent()->getParent()->
- getFunctionType()->isStructReturn();
+ bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr();
if (isStructReturn) {
Out << " return StructReturn;\n";
return;
}
+ if (I.getNumOperands() > 1) {
+ Out << " {\n";
+ Out << " ";
+ printType(Out, I.getParent()->getParent()->getReturnType());
+ Out << " llvm_cbe_mrv_temp = {\n";
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
+ Out << " ";
+ writeOperand(I.getOperand(i));
+ if (i != e - 1)
+ Out << ",";
+ Out << "\n";
+ }
+ Out << " };\n";
+ Out << " return llvm_cbe_mrv_temp;\n";
+ Out << " }\n";
+ return;
+ }
+
Out << " return";
if (I.getNumOperands()) {
Out << ' ';
BasicBlock *Succ = cast<BasicBlock>(SI.getOperand(i+1));
printPHICopiesForSuccessor (SI.getParent(), Succ, 2);
printBranchToBlock(SI.getParent(), Succ, 2);
- if (Function::iterator(Succ) == next(Function::iterator(SI.getParent())))
+ if (Function::iterator(Succ) == llvm::next(Function::iterator(SI.getParent())))
Out << " break;\n";
}
Out << " }\n";
}
+void CWriter::visitIndirectBrInst(IndirectBrInst &IBI) {
+ Out << " goto *(void*)(";
+ writeOperand(IBI.getOperand(0));
+ Out << ");\n";
+}
+
void CWriter::visitUnreachableInst(UnreachableInst &I) {
Out << " /*UNREACHABLE*/;\n";
}
/// FIXME: This should be reenabled, but loop reordering safe!!
return true;
- if (next(Function::iterator(From)) != Function::iterator(To))
+ if (llvm::next(Function::iterator(From)) != Function::iterator(To))
return true; // Not the direct successor, we need a goto.
//isa<SwitchInst>(From->getTerminator())
// We must cast the results of binary operations which might be promoted.
bool needsCast = false;
- if ((I.getType() == Type::Int8Ty) || (I.getType() == Type::Int16Ty)
- || (I.getType() == Type::FloatTy)) {
+ if ((I.getType() == Type::getInt8Ty(I.getContext())) ||
+ (I.getType() == Type::getInt16Ty(I.getContext()))
+ || (I.getType() == Type::getFloatTy(I.getContext()))) {
needsCast = true;
Out << "((";
printType(Out, I.getType(), false);
Out << "-(";
writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
Out << ")";
+ } else if (BinaryOperator::isFNeg(&I)) {
+ Out << "-(";
+ writeOperand(BinaryOperator::getFNegArgument(cast<BinaryOperator>(&I)));
+ Out << ")";
} else if (I.getOpcode() == Instruction::FRem) {
// Output a call to fmod/fmodf instead of emitting a%b
- if (I.getType() == Type::FloatTy)
+ if (I.getType() == Type::getFloatTy(I.getContext()))
Out << "fmodf(";
- else
+ else if (I.getType() == Type::getDoubleTy(I.getContext()))
Out << "fmod(";
+ else // all 3 flavors of long double
+ Out << "fmodl(";
writeOperand(I.getOperand(0));
Out << ", ";
writeOperand(I.getOperand(1));
writeOperandWithCast(I.getOperand(0), I.getOpcode());
switch (I.getOpcode()) {
- case Instruction::Add: Out << " + "; break;
- case Instruction::Sub: Out << " - "; break;
- case Instruction::Mul: Out << " * "; break;
+ case Instruction::Add:
+ case Instruction::FAdd: Out << " + "; break;
+ case Instruction::Sub:
+ case Instruction::FSub: Out << " - "; break;
+ case Instruction::Mul:
+ case Instruction::FMul: Out << " * "; break;
case Instruction::URem:
case Instruction::SRem:
case Instruction::FRem: Out << " % "; break;
case Instruction::Shl : Out << " << "; break;
case Instruction::LShr:
case Instruction::AShr: Out << " >> "; break;
- default: cerr << "Invalid operator type!" << I; abort();
+ default:
+#ifndef NDEBUG
+ errs() << "Invalid operator type!" << I;
+#endif
+ llvm_unreachable(0);
}
writeOperandWithCast(I.getOperand(1), I.getOpcode());
// 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
- writeOperandWithCast(I.getOperand(0), I.getPredicate());
+ writeOperandWithCast(I.getOperand(0), I);
switch (I.getPredicate()) {
case ICmpInst::ICMP_EQ: Out << " == "; break;
case ICmpInst::ICMP_SLT: Out << " < "; break;
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_SGT: Out << " > "; break;
- default: cerr << "Invalid icmp predicate!" << I; abort();
+ default:
+#ifndef NDEBUG
+ errs() << "Invalid icmp predicate!" << I;
+#endif
+ llvm_unreachable(0);
}
- writeOperandWithCast(I.getOperand(1), I.getPredicate());
+ writeOperandWithCast(I.getOperand(1), I);
if (NeedsClosingParens)
Out << "))";
const char* op = 0;
switch (I.getPredicate()) {
- default: assert(0 && "Illegal FCmp predicate");
+ default: llvm_unreachable("Illegal FCmp predicate");
case FCmpInst::FCMP_ORD: op = "ord"; break;
case FCmpInst::FCMP_UNO: op = "uno"; break;
case FCmpInst::FCMP_UEQ: op = "ueq"; break;
static const char * getFloatBitCastField(const Type *Ty) {
switch (Ty->getTypeID()) {
- default: assert(0 && "Invalid Type");
+ default: llvm_unreachable("Invalid Type");
case Type::FloatTyID: return "Float";
case Type::DoubleTyID: return "Double";
case Type::IntegerTyID: {
void CWriter::visitCastInst(CastInst &I) {
const Type *DstTy = I.getType();
const Type *SrcTy = I.getOperand(0)->getType();
- Out << '(';
if (isFPIntBitCast(I)) {
+ Out << '(';
// These int<->float and long<->double casts need to be handled specially
Out << GetValueName(&I) << "__BITCAST_TEMPORARY."
<< getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
writeOperand(I.getOperand(0));
Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY."
<< getFloatBitCastField(I.getType());
- } else {
- printCast(I.getOpcode(), SrcTy, DstTy);
- if (I.getOpcode() == Instruction::Trunc ||
- I.getOpcode() == Instruction::FPToUI ||
- I.getOpcode() == Instruction::FPToSI ||
- I.getOpcode() == Instruction::PtrToInt) {
- if (const IntegerType* IntTy = dyn_cast<IntegerType>(DstTy)){
- uint64_t BitMask = IntTy->getBitMask();
- writeOperand(I.getOperand(0));
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- } else if (I.getOpcode() == Instruction::SExt && SrcTy == Type::Int1Ty) {
- // Make sure we really get a sext from bool by subtracing the bool from 0
- Out << "0-";
- writeOperand(I.getOperand(0));
- } else if (I.getOpcode() == Instruction::SExt &&
- SrcTy->getTypeID() == Type::IntegerTyID) {
- IMPL_SIGN_EXTENSION(SrcTy, writeOperand(I.getOperand(0)) );
- } else if (I.getOpcode() == Instruction::ZExt &&
- SrcTy->getTypeID() == Type::IntegerTyID) {
- const IntegerType* IntTy = cast<IntegerType>(SrcTy);
- uint64_t BitMask = IntTy->getBitMask();
- writeOperand(I.getOperand(0));
- Out << "&" << BitMask << (IntTy->getBitWidth() <=32 ? "U": "ULL");
- }
- else
- writeOperand(I.getOperand(0));
+ Out << ')';
+ return;
}
- Out << ")";
+
+ Out << '(';
+ printCast(I.getOpcode(), SrcTy, DstTy);
+
+ // Make a sext from i1 work by subtracting the i1 from 0 (an int).
+ if (SrcTy == Type::getInt1Ty(I.getContext()) &&
+ I.getOpcode() == Instruction::SExt)
+ Out << "0-";
+
+ writeOperand(I.getOperand(0));
+
+ if (DstTy == Type::getInt1Ty(I.getContext()) &&
+ (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";
+ }
+ Out << ')';
}
void CWriter::visitSelectInst(SelectInst &I) {
if (Function *F = CI->getCalledFunction())
switch (F->getIntrinsicID()) {
case Intrinsic::not_intrinsic:
+ case Intrinsic::memory_barrier:
case Intrinsic::vastart:
case Intrinsic::vacopy:
case Intrinsic::vaend:
case Intrinsic::setjmp:
case Intrinsic::longjmp:
case Intrinsic::prefetch:
- case Intrinsic::dbg_stoppoint:
- case Intrinsic::powi_f32:
- case Intrinsic::powi_f64:
- // We directly implement these intrinsics
+ case Intrinsic::powi:
+ case Intrinsic::x86_sse_cmp_ss:
+ case Intrinsic::x86_sse_cmp_ps:
+ case Intrinsic::x86_sse2_cmp_sd:
+ case Intrinsic::x86_sse2_cmp_pd:
+ case Intrinsic::ppc_altivec_lvsl:
+ // We directly implement these intrinsics
break;
default:
// If this is an intrinsic that directly corresponds to a GCC
}
}
-
void CWriter::visitCallInst(CallInst &I) {
- //check if we have inline asm
- if (isInlineAsm(I)) {
- visitInlineAsm(I);
- return;
- }
+ if (isa<InlineAsm>(I.getOperand(0)))
+ return visitInlineAsm(I);
bool WroteCallee = false;
// Handle intrinsic function calls first...
if (Function *F = I.getCalledFunction())
- if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
- switch (ID) {
- default: {
- // If this is an intrinsic that directly corresponds to a GCC
- // builtin, we emit it here.
- const char *BuiltinName = "";
-#define GET_GCC_BUILTIN_NAME
-#include "llvm/Intrinsics.gen"
-#undef GET_GCC_BUILTIN_NAME
- assert(BuiltinName[0] && "Unknown LLVM intrinsic!");
-
- Out << BuiltinName;
- WroteCallee = true;
- break;
- }
- 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;
- 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;
- case Intrinsic::vacopy:
- Out << "0; ";
- Out << "va_copy(*(va_list*)";
- writeOperand(I.getOperand(1));
- Out << ", *(va_list*)";
- writeOperand(I.getOperand(2));
- Out << ')';
- return;
- case Intrinsic::returnaddress:
- Out << "__builtin_return_address(";
- writeOperand(I.getOperand(1));
- Out << ')';
+ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
+ if (visitBuiltinCall(I, ID, WroteCallee))
return;
- case Intrinsic::frameaddress:
- Out << "__builtin_frame_address(";
- writeOperand(I.getOperand(1));
- Out << ')';
- return;
- case Intrinsic::powi_f32:
- case Intrinsic::powi_f64:
- Out << "__builtin_powi(";
- writeOperand(I.getOperand(1));
- Out << ", ";
- writeOperand(I.getOperand(2));
- Out << ')';
- return;
- case Intrinsic::setjmp:
- Out << "setjmp(*(jmp_buf*)";
- writeOperand(I.getOperand(1));
- Out << ')';
- return;
- case Intrinsic::longjmp:
- Out << "longjmp(*(jmp_buf*)";
- writeOperand(I.getOperand(1));
- Out << ", ";
- writeOperand(I.getOperand(2));
- Out << ')';
- return;
- case Intrinsic::prefetch:
- Out << "LLVM_PREFETCH((const void *)";
- writeOperand(I.getOperand(1));
- Out << ", ";
- writeOperand(I.getOperand(2));
- Out << ", ";
- writeOperand(I.getOperand(3));
- Out << ")";
- return;
- 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;
- }
- }
- }
Value *Callee = I.getCalledValue();
// If this is a call to a struct-return function, assign to the first
// parameter instead of passing it to the call.
- bool isStructRet = FTy->isStructReturn();
+ const AttrListPtr &PAL = I.getAttributes();
+ bool hasByVal = I.hasByValArgument();
+ bool isStructRet = I.hasStructRetAttr();
if (isStructRet) {
- Out << "*(";
- writeOperand(I.getOperand(1));
- Out << ") = ";
+ writeOperandDeref(I.getOperand(1));
+ Out << " = ";
}
if (I.isTailCall()) Out << " /*tail*/ ";
if (!WroteCallee) {
// If this is an indirect call to a struct return function, we need to cast
- // the pointer.
- bool NeedsCast = isStructRet && !isa<Function>(Callee);
+ // the pointer. Ditto for indirect calls with byval arguments.
+ bool NeedsCast = (hasByVal || isStructRet) && !isa<Function>(Callee);
// 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
if (NeedsCast) {
// Ok, just cast the pointer type.
Out << "((";
- if (!isStructRet)
- printType(Out, I.getCalledValue()->getType());
- else
- printStructReturnPointerFunctionType(Out,
+ if (isStructRet)
+ printStructReturnPointerFunctionType(Out, PAL,
cast<PointerType>(I.getCalledValue()->getType()));
+ else if (hasByVal)
+ printType(Out, I.getCalledValue()->getType(), false, "", true, PAL);
+ else
+ printType(Out, I.getCalledValue()->getType());
Out << ")(void*)";
}
writeOperand(Callee);
++ArgNo;
}
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
bool PrintedArg = false;
- unsigned Idx = 1;
- for (; AI != AE; ++AI, ++ArgNo, ++Idx) {
+ for (; AI != AE; ++AI, ++ArgNo) {
if (PrintedArg) Out << ", ";
if (ArgNo < NumDeclaredParams &&
(*AI)->getType() != FTy->getParamType(ArgNo)) {
Out << '(';
printType(Out, FTy->getParamType(ArgNo),
- /*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt));
+ /*isSigned=*/PAL.paramHasAttr(ArgNo+1, Attribute::SExt));
Out << ')';
}
- writeOperand(*AI);
+ // Check if the argument is expected to be passed by value.
+ if (I.paramHasAttr(ArgNo+1, Attribute::ByVal))
+ writeOperandDeref(*AI);
+ else
+ writeOperand(*AI);
PrintedArg = true;
}
Out << ')';
}
+/// visitBuiltinCall - Handle the call to the specified builtin. Returns true
+/// if the entire call is handled, return false if 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_synchronize()";
+ 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()) {
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "The C backend does not currently support zero "
+ << "argument varargs functions, such as '"
+ << I.getParent()->getParent()->getName() << "'!";
+ llvm_report_error(Msg.str());
+ }
+ 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::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: llvm_unreachable("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;
+ case Intrinsic::ppc_altivec_lvsl:
+ Out << '(';
+ printType(Out, I.getType());
+ Out << ')';
+ Out << "__builtin_altivec_lvsl(0, (void*)";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+ return true;
+ }
+}
//This converts the llvm constraint string to something gcc is expecting.
//TODO: work out platform independent constraints and factor those out
// of the per target tables
// handle multiple constraint codes
std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) {
-
assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
- const char** table = 0;
+ // Grab the translation table from MCAsmInfo if it exists.
+ const MCAsmInfo *TargetAsm;
+ std::string Triple = TheModule->getTargetTriple();
+ if (Triple.empty())
+ Triple = llvm::sys::getHostTriple();
- //Grab the translation table from TargetAsmInfo if it exists
- if (!TAsm) {
- std::string E;
- const TargetMachineRegistry::Entry* Match =
- 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();
- }
- }
- if (TAsm)
- table = TAsm->getAsmCBE();
-
- //Search the translation table if it exists
+ std::string E;
+ if (const Target *Match = TargetRegistry::lookupTarget(Triple, E))
+ TargetAsm = Match->createAsmInfo(Triple);
+ else
+ return c.Codes[0];
+
+ const char *const *table = TargetAsm->getAsmCBE();
+
+ // Search the translation table if it exists.
for (int i = 0; table && table[i]; i += 2)
- if (c.Codes[0] == table[i])
+ if (c.Codes[0] == table[i]) {
+ delete TargetAsm;
return table[i+1];
+ }
- //default is identity
+ // Default is identity.
+ delete TargetAsm;
return c.Codes[0];
}
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;
+
+ std::vector<std::pair<Value*, int> > ResultVals;
+ if (CI.getType() == Type::getVoidTy(CI.getContext()))
+ ;
+ else if (const StructType *ST = dyn_cast<StructType>(CI.getType())) {
+ for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
+ ResultVals.push_back(std::make_pair(&CI, (int)i));
+ } else {
+ ResultVals.push_back(std::make_pair(&CI, -1));
+ }
+
+ // Fix up the asm string for gcc and emit it.
+ Out << "__asm__ volatile (\"" << gccifyAsm(as->getAsmString()) << "\"\n";
+ Out << " :";
+
+ unsigned ValueCount = 0;
+ bool IsFirst = true;
+
+ // Convert over all the output constraints.
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 =
- InterpretASMConstraint(*I);
- 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;
+ E = Constraints.end(); I != E; ++I) {
+
+ if (I->Type != InlineAsm::isOutput) {
+ ++ValueCount;
+ continue; // Ignore non-output constraints.
}
+
+ assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
+ std::string C = InterpretASMConstraint(*I);
+ if (C.empty()) continue;
+
+ if (!IsFirst) {
+ Out << ", ";
+ IsFirst = false;
}
+
+ // Unpack the dest.
+ Value *DestVal;
+ int DestValNo = -1;
+
+ if (ValueCount < ResultVals.size()) {
+ DestVal = ResultVals[ValueCount].first;
+ DestValNo = ResultVals[ValueCount].second;
+ } else
+ DestVal = CI.getOperand(ValueCount-ResultVals.size()+1);
+
+ if (I->isEarlyClobber)
+ C = "&"+C;
+
+ Out << "\"=" << C << "\"(" << GetValueName(DestVal);
+ if (DestValNo != -1)
+ Out << ".field" << DestValNo; // Multiple retvals.
+ Out << ")";
+ ++ValueCount;
}
- //fix up the asm string for gcc
- std::string asmstr = gccifyAsm(as->getAsmString());
- Out << "__asm__ volatile (\"" << asmstr << "\"\n";
- Out << " :";
- for (std::vector<std::pair<std::string, Value*> >::iterator I = Output.begin(),
- E = Output.end(); I != E; ++I) {
- Out << "\"" << I->first << "\"(";
- writeOperandRaw(I->second);
- Out << ")";
- if (I + 1 != E)
- Out << ",";
- }
+ // Convert over all the input constraints.
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);
+ IsFirst = true;
+ ValueCount = 0;
+ for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+ E = Constraints.end(); I != E; ++I) {
+ if (I->Type != InlineAsm::isInput) {
+ ++ValueCount;
+ continue; // Ignore non-input constraints.
+ }
+
+ assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
+ std::string C = InterpretASMConstraint(*I);
+ if (C.empty()) continue;
+
+ if (!IsFirst) {
+ Out << ", ";
+ IsFirst = false;
+ }
+
+ assert(ValueCount >= ResultVals.size() && "Input can't refer to result");
+ Value *SrcVal = CI.getOperand(ValueCount-ResultVals.size()+1);
+
+ Out << "\"" << C << "\"(";
+ if (!I->isIndirect)
+ writeOperand(SrcVal);
+ else
+ writeOperandDeref(SrcVal);
Out << ")";
- if (I + 1 != E)
- Out << ",";
}
- if (Clobber.size())
- Out << "\n :" << Clobber.substr(1);
- Out << ")";
-}
+
+ // Convert over the clobber constraints.
+ IsFirst = true;
+ for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+ E = Constraints.end(); I != E; ++I) {
+ if (I->Type != InlineAsm::isClobber)
+ continue; // Ignore non-input constraints.
-void CWriter::visitMallocInst(MallocInst &I) {
- assert(0 && "lowerallocations pass didn't work!");
+ assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
+ std::string C = InterpretASMConstraint(*I);
+ if (C.empty()) continue;
+
+ if (!IsFirst) {
+ Out << ", ";
+ IsFirst = false;
+ }
+
+ Out << '\"' << C << '"';
+ }
+
+ Out << ")";
}
void CWriter::visitAllocaInst(AllocaInst &I) {
Out << ')';
}
-void CWriter::visitFreeInst(FreeInst &I) {
- assert(0 && "lowerallocations pass didn't work!");
-}
-
-void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I,
- gep_type_iterator E) {
- bool HasImplicitAddress = false;
- // If accessing a global value with no indexing, avoid *(&GV) syndrome
- if (isa<GlobalValue>(Ptr)) {
- HasImplicitAddress = true;
- } else if (isDirectAlloca(Ptr)) {
- HasImplicitAddress = true;
- }
-
+void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I,
+ gep_type_iterator E, bool Static) {
+
+ // If there are no indices, just print out the pointer.
if (I == E) {
- if (!HasImplicitAddress)
- Out << '*'; // Implicit zero first argument: '*x' is equivalent to 'x[0]'
-
- writeOperandInternal(Ptr);
+ writeOperand(Ptr);
return;
}
-
- const Constant *CI = dyn_cast<Constant>(I.getOperand());
- if (HasImplicitAddress && (!CI || !CI->isNullValue()))
- Out << "(&";
-
- writeOperandInternal(Ptr);
-
- if (HasImplicitAddress && (!CI || !CI->isNullValue())) {
- Out << ')';
- HasImplicitAddress = false; // HIA is only true if we haven't addressed yet
+
+ // 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);
}
+
+ 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 << '&';
- assert(!HasImplicitAddress || (CI && CI->isNullValue()) &&
- "Can only have implicit address with direct accessing");
-
- if (HasImplicitAddress) {
- ++I;
- } else if (CI && CI->isNullValue()) {
- gep_type_iterator TmpI = I; ++TmpI;
-
- // Print out the -> operator if possible...
- if (TmpI != E && isa<StructType>(*TmpI)) {
- Out << (HasImplicitAddress ? "." : "->");
- Out << "field" << cast<ConstantInt>(TmpI.getOperand())->getZExtValue();
- I = ++TmpI;
+ // 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, Static);
+ } 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 << ")";
}
}
- for (; I != E; ++I)
+ for (; I != E; ++I) {
if (isa<StructType>(*I)) {
Out << ".field" << cast<ConstantInt>(I.getOperand())->getZExtValue();
- } else {
+ } else if (isa<ArrayType>(*I)) {
+ Out << ".array[";
+ writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
+ Out << ']';
+ } else if (!isa<VectorType>(*I)) {
Out << '[';
- writeOperand(I.getOperand());
+ writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
Out << ']';
+ } 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 << "))";
+ }
}
+ }
+ Out << ")";
}
-void CWriter::visitLoadInst(LoadInst &I) {
- Out << '*';
- if (I.isVolatile()) {
+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) {
Out << "((";
- printType(Out, I.getType(), false, "volatile*");
+ if (IsUnaligned)
+ Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {";
+ printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*");
+ if (IsUnaligned) {
+ Out << "; } ";
+ if (IsVolatile) Out << "volatile ";
+ Out << "*";
+ }
Out << ")";
}
- writeOperand(I.getOperand(0));
+ writeOperand(Operand);
- if (I.isVolatile())
+ if (IsVolatile || IsUnaligned) {
Out << ')';
+ if (IsUnaligned)
+ Out << "->data";
+ }
+}
+
+void CWriter::visitLoadInst(LoadInst &I) {
+ writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(),
+ I.getAlignment());
+
}
void CWriter::visitStoreInst(StoreInst &I) {
- Out << '*';
- if (I.isVolatile()) {
- Out << "((";
- printType(Out, I.getOperand(0)->getType(), false, " volatile*");
- Out << ")";
- }
- writeOperand(I.getPointerOperand());
- if (I.isVolatile()) Out << ')';
+ writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(),
+ I.isVolatile(), I.getAlignment());
Out << " = ";
Value *Operand = I.getOperand(0);
Constant *BitMask = 0;
writeOperand(Operand);
if (BitMask) {
Out << ") & ";
- printConstant(BitMask);
+ printConstant(BitMask, false);
Out << ")";
}
}
void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) {
- Out << '&';
- printIndexingExpression(I.getPointerOperand(), gep_type_begin(I),
- gep_type_end(I));
+ printGEPExpression(I.getPointerOperand(), gep_type_begin(I),
+ gep_type_end(I), false);
}
void CWriter::visitVAArgInst(VAArgInst &I) {
Out << ");\n ";
}
+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));
+ Out << "] = (";
+ writeOperand(I.getOperand(1));
+ Out << ")";
+}
+
+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 << "]";
+}
+
+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)),
+ false);
+ }
+ }
+ }
+ Out << "}";
+}
+
+void CWriter::visitInsertValueInst(InsertValueInst &IVI) {
+ // Start by copying the entire aggregate value into the result variable.
+ writeOperand(IVI.getOperand(0));
+ Out << ";\n ";
+
+ // Then do the insert to update the field.
+ Out << GetValueName(&IVI);
+ for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end();
+ i != e; ++i) {
+ const Type *IndexedTy =
+ ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), b, i+1);
+ if (isa<ArrayType>(IndexedTy))
+ Out << ".array[" << *i << "]";
+ else
+ Out << ".field" << *i;
+ }
+ Out << " = ";
+ writeOperand(IVI.getOperand(1));
+}
+
+void CWriter::visitExtractValueInst(ExtractValueInst &EVI) {
+ Out << "(";
+ if (isa<UndefValue>(EVI.getOperand(0))) {
+ Out << "(";
+ printType(Out, EVI.getType());
+ Out << ") 0/*UNDEF*/";
+ } else {
+ Out << GetValueName(EVI.getOperand(0));
+ for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end();
+ i != e; ++i) {
+ const Type *IndexedTy =
+ ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), b, i+1);
+ if (isa<ArrayType>(IndexedTy))
+ Out << ".array[" << *i << "]";
+ else
+ Out << ".field" << *i;
+ }
+ }
+ Out << ")";
+}
+
//===----------------------------------------------------------------------===//
// External Interface declaration
//===----------------------------------------------------------------------===//
bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM,
- std::ostream &o,
+ formatted_raw_ostream &o,
CodeGenFileType FileType,
- bool Fast) {
- if (FileType != TargetMachine::AssemblyFile) return true;
+ CodeGenOpt::Level OptLevel) {
+ if (FileType != TargetMachine::CGFT_AssemblyFile) return true;
- PM.add(createLowerGCPass());
- PM.add(createLowerAllocationsPass(true));
+ PM.add(createGCLoweringPass());
PM.add(createLowerInvokePass());
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
PM.add(new CWriter(o));
+ PM.add(createGCInfoDeleter());
return false;
}