//
// 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/Analysis/ConstantsScanner.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include <sstream>
using namespace llvm;
-namespace {
- // Register the target.
- RegisterTarget<CTargetMachine> X("c", " C backend");
+// Register the target.
+static RegisterTarget<CTargetMachine> X("c", " C backend");
+namespace {
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
/// any unnamed structure types that are used by the program, and merges
/// external functions with the same name.
std::map<const Type *, std::string> TypeNames;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
+ std::set<const Argument*> ByValParams;
public:
static char ID;
- CWriter(std::ostream &o)
+ explicit CWriter(std::ostream &o)
: FunctionPass((intptr_t)&ID), Out(o), IL(0), Mang(0), LI(0),
TheModule(0), TAsm(0), TD(0) {}
printFloatingPointConstants(F);
printFunction(F);
- FPConstantMap.clear();
return false;
}
virtual bool doFinalization(Module &M) {
// Free memory...
delete Mang;
+ FPConstantMap.clear();
TypeNames.clear();
+ ByValParams.clear();
+ intrinsicPrototypesAlreadyGenerated.clear();
return false;
}
std::ostream &printType(std::ostream &Out, const Type *Ty,
bool isSigned = false,
const std::string &VariableName = "",
- bool IgnoreName = false);
+ bool IgnoreName = false,
+ const PAListPtr &PAL = PAListPtr());
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,
+ const PAListPtr &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 writeInstComputationInline(Instruction &I);
void writeOperandInternal(Value *Operand);
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 printFunctionSignature(const Function *F, bool Prototype);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE);
void printConstantArray(ConstantArray *CPA);
- void printConstantVector(ConstantVector *CP);
+ void printConstantVector(ConstantVector *CV);
+ /// 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
// emit it inline where it would go.
if (I.getType() == Type::VoidTy || !I.hasOneUse() ||
isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I) ||
- isa<LoadInst>(I) || isa<VAArgInst>(I))
+ 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 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 visitStoreInst (StoreInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
void visitVAArgInst (VAArgInst &I);
+
+ void visitInsertElementInst(InsertElementInst &I);
+ void visitExtractElementInst(ExtractElementInst &I);
+ void visitShuffleVectorInst(ShuffleVectorInst &SVI);
+ void visitGetResultInst(GetResultInst &GRI);
+
+ void visitInsertValueInst(InsertValueInst &I);
+ void visitExtractValueInst(ExtractValueInst &I);
void visitInstruction(Instruction &I) {
cerr << "C Writer does not know about " << 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);
std::string GetValueName(const Value *Operand);
};
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;
}
/// 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,
+ const PAListPtr &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, ParamAttr::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::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, ParamAttr::SExt), tstr);
}
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->isInteger() || 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 :
+ // 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->getABITypeSize(VTy)) + " ))) " + NameSoFar);
+ }
+
+ default:
cerr << "Unknown primitive type: " << *Ty << "\n";
abort();
}
//
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
bool isSigned, const std::string &NameSoFar,
- bool IgnoreName) {
- if (Ty->isPrimitiveType() || Ty->isInteger()) {
+ bool IgnoreName, const PAListPtr &PAL) {
+ if (Ty->isPrimitiveType() || Ty->isInteger() || 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, ParamAttr::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, ParamAttr::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, ParamAttr::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) + "]");
- }
-
- case Type::VectorTyID: {
- const VectorType *PTy = cast<VectorType>(Ty);
- unsigned NumElements = PTy->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: {
// only deal in IEEE FP).
//
static bool isFPCSafeToPrint(const ConstantFP *CFP) {
+ // Do long doubles in hex for now.
+ if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
+ return false;
+ APFloat APF = APFloat(CFP->getValueAPF()); // copy
+ if (CFP->getType()==Type::FloatTy)
+ APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
#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
}
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));
+ Out << ")";
return;
case Instruction::Select:
Out << '(';
if (NeedsClosingParens)
Out << "))";
Out << ')';
+ return;
}
default:
cerr << "CWriter Error: Unhandled constant expression: "
<< *CE << "\n";
abort();
}
- } 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') ;
+ Out << (CI->getZExtValue() ? '1' : '0');
+ else if (Ty == Type::Int32Ty)
+ 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 << ')';
+ 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::FloatTy ? "float" :
+ FPC->getType() == Type::DoubleTy ? "double" :
+ "long double")
<< "*)&FPConstant" << I->second << ')';
} else {
- if (IsNAN(FPC->getValue())) {
+ assert(FPC->getType() == Type::FloatTy ||
+ FPC->getType() == Type::DoubleTy);
+ double V = FPC->getType() == Type::FloatTy ?
+ FPC->getValueAPF().convertToFloat() :
+ FPC->getValueAPF().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]);
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 << '-';
+ if (V < 0) Out << '-';
Out << "LLVM_INF" << (FPC->getType() == Type::FloatTy ? "F" : "")
<< " /*inf*/ ";
} else {
#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)) {
+ Out << "{ "; // Arrays are wrapped in struct types.
+ if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
+ printConstantArray(CA);
+ } else {
+ assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
const ArrayType *AT = cast<ArrayType>(CPV->getType());
Out << '{';
if (AT->getNumElements()) {
}
}
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());
+ // Use C99 compound expression literal initializer syntax.
+ Out << "(";
+ printType(Out, CPV->getType());
+ Out << ")";
+ if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
+ printConstantVector(CV);
+ } else {
+ assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
+ const VectorType *VT = cast<VectorType>(CPV->getType());
+ Out << "{ ";
+ Constant *CZ = Constant::getNullValue(VT->getElementType());
+ printConstant(CZ);
+ for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) {
+ Out << ", ";
printConstant(CZ);
- for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) {
- Out << ", ";
- printConstant(CZ);
- }
}
Out << " }";
- } else {
- printConstantVector(cast<ConstantVector>(CPV));
}
break;
char ch = *I;
if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') || ch == '_'))
- VarName += '_';
- else
+ (ch >= '0' && ch <= '9') || ch == '_')) {
+ char buffer[5];
+ sprintf(buffer, "_%x_", ch);
+ VarName += buffer;
+ } else
VarName += ch;
}
return Name;
}
+/// writeInstComputationInline - Emit the computation for the specified
+/// instruction inline, with no destination provided.
+void CWriter::writeInstComputationInline(Instruction &I) {
+ // 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::Int1Ty && !isa<ICmpInst>(I) && !isa<FCmpInst>(I))
+ NeedBoolTrunc = true;
+
+ if (NeedBoolTrunc)
+ Out << "((";
+
+ visit(I);
+
+ if (NeedBoolTrunc)
+ Out << ")&1)";
+}
+
+
void CWriter::writeOperandInternal(Value *Operand) {
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;
}
}
void CWriter::writeOperand(Value *Operand) {
- if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+ bool isAddressImplicit = isAddressExposed(Operand);
+ if (isAddressImplicit)
Out << "(&"; // Global variables are referenced as their addresses by llvm
writeOperandInternal(Operand);
- if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+ if (isAddressImplicit)
Out << ')';
}
shouldCast = true;
castIsSigned = false;
break;
+ case Instruction::GetElementPtr:
case Instruction::AShr:
case Instruction::SDiv:
case Instruction::SRem: // Cast to signed first
// Write the operand with a cast to another type based on the icmp predicate
// being used.
-void CWriter::writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate) {
-
- // Extract the operand's type, we'll need it.
- const Type* OpTy = Operand->getType();
-
- // Indicate whether to do the cast or not.
- bool shouldCast = false;
-
- // 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_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;
- }
+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();
// 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 << ")";
- writeOperand(Operand);
- Out << ")";
- } else
+ if (!shouldCast) {
writeOperand(Operand);
+ return;
+ }
+
+ // Should this be a signed comparison? If so, convert to signed.
+ bool castIsSigned = Cmp.isSignedPredicate();
+
+ // If the operand was a pointer, convert to a large integer type.
+ const Type* OpTy = Operand->getType();
+ if (isa<PointerType>(OpTy))
+ OpTy = TD->getIntPtrType();
+
+ Out << "((";
+ printSimpleType(Out, OpTy, castIsSigned);
+ Out << ")";
+ writeOperand(Operand);
+ Out << ")";
}
// 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(std::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"
<< "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__)\n"
<< "#define alloca(x) __builtin_alloca(x)\n"
<< "#elif defined(_MSC_VER)\n"
<< "#define inline _inline\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.
+ if (TD->getPointerSize() >= 8) {
+ Out << "#ifdef __GNUC__ /* 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
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
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 ";
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())
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());
// 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());
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) {
+ double Val = FPC->getValueAPF().convertToDouble();
+ uint64_t i = FPC->getValueAPF().convertToAPInt().getZExtValue();
Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
- << " = 0x" << std::hex << DoubleToBits(Val) << std::dec
+ << " = 0x" << std::hex << i << std::dec
<< "ULL; /* " << Val << " */\n";
} else if (FPC->getType() == Type::FloatTy) {
+ float Val = FPC->getValueAPF().convertToFloat();
+ uint32_t i = (uint32_t)FPC->getValueAPF().convertToAPInt().
+ getZExtValue();
Out << "static const ConstantFloatTy FPConstant" << FPCounter++
- << " = 0x" << std::hex << FloatToBits(Val) << std::dec
+ << " = 0x" << std::hex << i << std::dec
<< "U; /* " << Val << " */\n";
+ } else if (FPC->getType() == Type::X86_FP80Ty) {
+ // api needed to prevent premature destruction
+ APInt api = FPC->getValueAPF().convertToAPInt();
+ const uint64_t *p = api.getRawData();
+ Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
+ << " = { 0x" << std::hex
+ << ((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16)
+ << "ULL, 0x" << (uint16_t)(p[0] >> 48) << ",{0,0,0}"
+ << "}; /* Long double constant */\n" << std::dec;
+ } else if (FPC->getType() == Type::PPC_FP128Ty) {
+ APInt api = FPC->getValueAPF().convertToAPInt();
+ const uint64_t *p = api.getRawData();
+ Out << "static const ConstantFP128Ty FPConstant" << FPCounter++
+ << " = { 0x" << std::hex
+ << p[0] << ", 0x" << p[1]
+ << "}; /* Long double constant */\n" << std::dec;
+
} else
assert(0 && "Unknown float type!");
}
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;
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->hasDLLImportLinkage()) Out << "__declspec(dllimport) ";
// Loop over the arguments, printing them...
const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
- const ParamAttrsList *Attrs = FT->getParamAttrs();
+ const PAListPtr &PAL = F->getParamAttrs();
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, ParamAttr::ByVal)) {
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ ByValParams.insert(I);
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::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, ParamAttr::ByVal)) {
+ assert(isa<PointerType>(ArgTy));
+ ArgTy = cast<PointerType>(ArgTy)->getElementType();
+ }
+ printType(FunctionInnards, ArgTy,
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::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, ParamAttr::SExt),
FunctionInnards.str());
}
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";
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 << ' ';
// Output a call to fmod/fmodf instead of emitting a%b
if (I.getType() == Type::FloatTy)
Out << "fmodf(";
- else
+ else if (I.getType() == Type::DoubleTy)
Out << "fmod(";
+ else // all 3 flavors of long double
+ Out << "fmodl(";
writeOperand(I.getOperand(0));
Out << ", ";
writeOperand(I.getOperand(1));
// 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;
default: cerr << "Invalid icmp predicate!" << I; abort();
}
- writeOperandWithCast(I.getOperand(1), I.getPredicate());
+ writeOperandWithCast(I.getOperand(1), I);
if (NeedsClosingParens)
Out << "))";
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::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));
- if (DstTy == Type::Int1Ty &&
- (I.getOpcode() == Instruction::Trunc ||
- I.getOpcode() == Instruction::FPToUI ||
- I.getOpcode() == Instruction::FPToSI ||
- I.getOpcode() == Instruction::PtrToInt)) {
- // Make sure we really get a trunc to bool by anding the operand with 1
- Out << "&1u";
- }
+ Out << ')';
+ return;
+ }
+
+ Out << '(';
+ printCast(I.getOpcode(), SrcTy, DstTy);
+
+ // Make a sext from i1 work by subtracting the i1 from 0 (an int).
+ if (SrcTy == Type::Int1Ty && I.getOpcode() == Instruction::SExt)
+ Out << "0-";
+
+ writeOperand(I.getOperand(0));
+
+ if (DstTy == Type::Int1Ty &&
+ (I.getOpcode() == Instruction::Trunc ||
+ I.getOpcode() == Instruction::FPToUI ||
+ I.getOpcode() == Instruction::FPToSI ||
+ I.getOpcode() == Instruction::PtrToInt)) {
+ // Make sure we really get a trunc to bool by anding the operand with 1
+ Out << "&1u";
}
Out << ')';
}
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::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 << ')';
- 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";
+ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
+ if (visitBuiltinCall(I, ID, WroteCallee))
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 PAListPtr &PAL = I.getParamAttrs();
+ 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, ParamAttr::SExt));
Out << ')';
}
- writeOperand(*AI);
+ // Check if the argument is expected to be passed by value.
+ if (I.paramHasAttr(ArgNo+1, ParamAttr::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 it it wasn't handled, and
+/// optionally set 'WroteCallee' if the callee has already been printed out.
+bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID,
+ bool &WroteCallee) {
+ switch (ID) {
+ default: {
+ // If this is an intrinsic that directly corresponds to a GCC
+ // builtin, we emit it here.
+ const char *BuiltinName = "";
+ Function *F = I.getCalledFunction();
+#define GET_GCC_BUILTIN_NAME
+#include "llvm/Intrinsics.gen"
+#undef GET_GCC_BUILTIN_NAME
+ assert(BuiltinName[0] && "Unknown LLVM intrinsic!");
+
+ Out << BuiltinName;
+ WroteCallee = true;
+ return false;
+ }
+ case Intrinsic::memory_barrier:
+ Out << "__sync_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()) {
+ cerr << "The C backend does not currently support zero "
+ << "argument varargs functions, such as '"
+ << I.getParent()->getParent()->getName() << "'!\n";
+ abort();
+ }
+ writeOperand(--I.getParent()->getParent()->arg_end());
+ Out << ')';
+ return true;
+ case Intrinsic::vaend:
+ if (!isa<ConstantPointerNull>(I.getOperand(1))) {
+ Out << "0; va_end(*(va_list*)";
+ writeOperand(I.getOperand(1));
+ Out << ')';
+ } else {
+ Out << "va_end(*(va_list*)0)";
+ }
+ return true;
+ case Intrinsic::vacopy:
+ Out << "0; ";
+ Out << "va_copy(*(va_list*)";
+ writeOperand(I.getOperand(1));
+ Out << ", *(va_list*)";
+ writeOperand(I.getOperand(2));
+ Out << ')';
+ return true;
+ case Intrinsic::returnaddress:
+ Out << "__builtin_return_address(";
+ writeOperand(I.getOperand(1));
+ Out << ')';
+ return true;
+ case Intrinsic::frameaddress:
+ Out << "__builtin_frame_address(";
+ writeOperand(I.getOperand(1));
+ Out << ')';
+ return true;
+ case Intrinsic::powi:
+ Out << "__builtin_powi(";
+ writeOperand(I.getOperand(1));
+ Out << ", ";
+ writeOperand(I.getOperand(2));
+ Out << ')';
+ return true;
+ case Intrinsic::setjmp:
+ Out << "setjmp(*(jmp_buf*)";
+ writeOperand(I.getOperand(1));
+ Out << ')';
+ return true;
+ case Intrinsic::longjmp:
+ Out << "longjmp(*(jmp_buf*)";
+ writeOperand(I.getOperand(1));
+ Out << ", ";
+ writeOperand(I.getOperand(2));
+ Out << ')';
+ return true;
+ case Intrinsic::prefetch:
+ Out << "LLVM_PREFETCH((const void *)";
+ writeOperand(I.getOperand(1));
+ Out << ", ";
+ writeOperand(I.getOperand(2));
+ Out << ", ";
+ writeOperand(I.getOperand(3));
+ Out << ")";
+ return true;
+ case Intrinsic::stacksave:
+ // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save()
+ // to work around GCC bugs (see PR1809).
+ Out << "0; *((void**)&" << GetValueName(&I)
+ << ") = __builtin_stack_save()";
+ return true;
+ case Intrinsic::dbg_stoppoint: {
+ // If we use writeOperand directly we get a "u" suffix which is rejected
+ // by gcc.
+ DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
+ Out << "\n#line "
+ << SPI.getLine()
+ << " \"" << SPI.getDirectory()
+ << SPI.getFileName() << "\"\n";
+ return true;
+ }
+ case Intrinsic::x86_sse_cmp_ss:
+ case Intrinsic::x86_sse_cmp_ps:
+ case Intrinsic::x86_sse2_cmp_sd:
+ case Intrinsic::x86_sse2_cmp_pd:
+ Out << '(';
+ printType(Out, I.getType());
+ Out << ')';
+ // Multiple GCC builtins multiplex onto this intrinsic.
+ switch (cast<ConstantInt>(I.getOperand(3))->getZExtValue()) {
+ default: assert(0 && "Invalid llvm.x86.sse.cmp!");
+ case 0: Out << "__builtin_ia32_cmpeq"; break;
+ case 1: Out << "__builtin_ia32_cmplt"; break;
+ case 2: Out << "__builtin_ia32_cmple"; break;
+ case 3: Out << "__builtin_ia32_cmpunord"; break;
+ case 4: Out << "__builtin_ia32_cmpneq"; break;
+ case 5: Out << "__builtin_ia32_cmpnlt"; break;
+ case 6: Out << "__builtin_ia32_cmpnle"; break;
+ case 7: Out << "__builtin_ia32_cmpord"; break;
+ }
+ if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd)
+ Out << 'p';
+ else
+ Out << 's';
+ if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps)
+ Out << 's';
+ else
+ Out << 'd';
+
+ Out << "(";
+ writeOperand(I.getOperand(1));
+ Out << ", ";
+ writeOperand(I.getOperand(2));
+ Out << ")";
+ return true;
+ 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
assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
- const char** table = 0;
+ const char *const *table = 0;
//Grab the translation table from TargetAsmInfo if it exists
if (!TAsm) {
std::string E;
- const TargetMachineRegistry::Entry* Match =
+ const TargetMachineRegistry::entry* Match =
TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, E);
if (Match) {
//Per platform Target Machines don't exist, so create it
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::VoidTy)
+ ;
+ 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);
+
+ // Convert over the clobber constraints.
+ IsFirst = true;
+ ValueCount = 0;
+ 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.
+
+ 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 << ")";
}
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) {
+
+ // 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);
+ } 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;
}
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));
}
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)));
+ }
+ }
+ }
+ Out << "}";
+}
+
+void CWriter::visitGetResultInst(GetResultInst &GRI) {
+ Out << "(";
+ if (isa<UndefValue>(GRI.getOperand(0))) {
+ Out << "(";
+ printType(Out, GRI.getType());
+ Out << ") 0/*UNDEF*/";
+ } else {
+ Out << GetValueName(GRI.getOperand(0)) << ".field" << GRI.getIndex();
+ }
+ 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 Fast) {
if (FileType != TargetMachine::AssemblyFile) return true;
- PM.add(createLowerGCPass());
+ PM.add(createGCLoweringPass());
PM.add(createLowerAllocationsPass(true));
PM.add(createLowerInvokePass());
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
PM.add(new CWriter(o));
+ PM.add(createCollectorMetadataDeleter());
return false;
}