#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h"
#include <sstream>
using namespace llvm;
+/// CBackendTargetMachineModule - Note that this is used on hosts that
+/// cannot link in a library unless there are references into the
+/// library. In particular, it seems that it is not possible to get
+/// things to work on Win32 without this. Though it is unused, do not
+/// remove it.
+extern "C" int CBackendTargetMachineModule;
+int CBackendTargetMachineModule = 0;
+
// Register the target.
-static RegisterTarget<CTargetMachine> X("c", " C backend");
+static RegisterTarget<CTargetMachine> X("c", "C backend");
namespace {
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
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;
+ raw_ostream &Out;
IntrinsicLowering *IL;
Mangler *Mang;
LoopInfo *LI;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
std::set<const Argument*> ByValParams;
+ unsigned FPCounter;
public:
static char ID;
- explicit CWriter(std::ostream &o)
- : FunctionPass((intptr_t)&ID), Out(o), IL(0), Mang(0), LI(0),
- TheModule(0), TAsm(0), TD(0) {}
+ explicit CWriter(raw_ostream &o)
+ : FunctionPass(&ID), Out(o), IL(0), Mang(0), LI(0),
+ TheModule(0), TAsm(0), TD(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.
virtual bool doFinalization(Module &M) {
// Free memory...
+ delete IL;
+ delete TD;
delete Mang;
FPConstantMap.clear();
TypeNames.clear();
return false;
}
- std::ostream &printType(std::ostream &Out, const Type *Ty,
+ raw_ostream &printType(raw_ostream &Out, const Type *Ty,
bool isSigned = false,
const std::string &VariableName = "",
bool IgnoreName = false,
- const PAListPtr &PAL = PAListPtr());
- std::ostream &printSimpleType(std::ostream &Out, const Type *Ty,
+ const AttrListPtr &PAL = AttrListPtr());
+ std::ostream &printType(std::ostream &Out, const Type *Ty,
+ bool isSigned = false,
+ const std::string &VariableName = "",
+ bool IgnoreName = false,
+ const AttrListPtr &PAL = AttrListPtr());
+ raw_ostream &printSimpleType(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 = "");
- void printStructReturnPointerFunctionType(std::ostream &Out,
- const PAListPtr &PAL,
+ void printStructReturnPointerFunctionType(raw_ostream &Out,
+ const AttrListPtr &PAL,
const PointerType *Ty);
/// writeOperandDeref - Print the result of dereferencing the specified
void printModuleTypes(const TypeSymbolTable &ST);
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 &);
/// 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,
- const PAListPtr &PAL,
+void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out,
+ const AttrListPtr &PAL,
const PointerType *TheTy) {
const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
std::stringstream FunctionInnards;
if (PrintedType)
FunctionInnards << ", ";
const Type *ArgTy = *I;
- if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
assert(isa<PointerType>(ArgTy));
ArgTy = cast<PointerType>(ArgTy)->getElementType();
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt), "");
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), "");
PrintedType = true;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, RetTy,
- /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt), tstr);
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr);
+}
+
+raw_ostream &
+CWriter::printSimpleType(raw_ostream &Out, const Type *Ty, bool isSigned,
+ 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;
+ 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:
+ cerr << "Unknown primitive type: " << *Ty << "\n";
+ abort();
+ }
}
std::ostream &
const VectorType *VTy = cast<VectorType>(Ty);
return printSimpleType(Out, VTy->getElementType(), isSigned,
" __attribute__((vector_size(" +
- utostr(TD->getABITypeSize(VTy)) + " ))) " + NameSoFar);
+ utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar);
}
default:
}
}
+// Pass the Type* and the variable name and this prints out the variable
+// declaration.
+//
+raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
+ bool isSigned, const std::string &NameSoFar,
+ bool IgnoreName, const AttrListPtr &PAL) {
+ if (Ty->isPrimitiveType() || Ty->isInteger() || 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;
+ // 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++);
+ assert(TypeNames.find(Ty) == TypeNames.end());
+ TypeNames[Ty] = TyName;
+ return Out << TyName << ' ' << NameSoFar;
+ }
+ default:
+ assert(0 && "Unhandled case in getTypeProps!");
+ abort();
+ }
+
+ 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 PAListPtr &PAL) {
+ bool IgnoreName, const AttrListPtr &PAL) {
if (Ty->isPrimitiveType() || Ty->isInteger() || isa<VectorType>(Ty)) {
printSimpleType(Out, Ty, isSigned, NameSoFar);
return Out;
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)) {
+ 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, ParamAttr::SExt), "");
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), "");
++Idx;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, FTy->getReturnType(),
- /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt), tstr);
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr);
return Out;
}
case Type::StructTyID: {
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) {
// only deal in IEEE FP).
//
static bool isFPCSafeToPrint(const ConstantFP *CFP) {
+ bool ignored;
// Do long doubles in hex for now.
- if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
+ 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 (CFP->getType() == Type::FloatTy)
+ APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
char Buffer[100];
sprintf(Buffer, "%a", APF.convertToDouble());
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:
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;
Out << CI->getZExtValue() << 'u';
else
Out << CI->getSExtValue();
- Out << ')';
+ Out << ')';
}
return;
}
"long double")
<< "*)&FPConstant" << I->second << ')';
} else {
- assert(FPC->getType() == Type::FloatTy ||
- FPC->getType() == Type::DoubleTy);
- double V = FPC->getType() == Type::FloatTy ?
- FPC->getValueAPF().convertToFloat() :
- FPC->getValueAPF().convertToDouble();
+ double V;
+ if (FPC->getType() == Type::FloatTy)
+ V = FPC->getValueAPF().convertToFloat();
+ else if (FPC->getType() == Type::DoubleTy)
+ 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
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!Ty->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = true; break;
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!OpTy->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem:
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!Ty->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv:
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!OpTy->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem: // Cast to unsigned first
// 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(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 (getGlobalVariableClass(I))
continue;
- if (I->hasInternalLinkage())
+ if (I->hasLocalLinkage())
Out << "static ";
else
Out << "extern ";
if (getGlobalVariableClass(I))
continue;
- if (I->hasInternalLinkage())
+ if (I->hasLocalLinkage())
Out << "static ";
else if (I->hasDLLImportLinkage())
Out << "__declspec(dllimport) ";
// 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)) {
- 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 << 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 << 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!");
- }
+ 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::DoubleTy) {
+ 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::FloatTy) {
+ 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::X86_FP80Ty) {
+ // 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::PPC_FP128Ty) {
+ 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 {
+ assert(0 && "Unknown float type!");
+ }
+}
+
+
/// printSymbolTable - Run through symbol table looking for type names. If a
/// type name is found, emit its declaration...
/// isStructReturn - Should this function actually return a struct by-value?
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;
}
// Loop over the arguments, printing them...
const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
- const PAListPtr &PAL = F->getParamAttrs();
+ const AttrListPtr &PAL = F->getAttributes();
std::stringstream FunctionInnards;
else
ArgName = "";
const Type *ArgTy = I->getType();
- if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
ArgTy = cast<PointerType>(ArgTy)->getElementType();
ByValParams.insert(I);
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt),
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt),
ArgName);
PrintedArg = true;
++Idx;
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
const Type *ArgTy = *I;
- if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
assert(isa<PointerType>(ArgTy));
ArgTy = cast<PointerType>(ArgTy)->getElementType();
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt));
+ /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt));
PrintedArg = true;
++Idx;
}
// Print out the return type and the signature built above.
printType(Out, RetTy,
- /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt),
+ /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt),
FunctionInnards.str());
}
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)
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;
// If this is a call to a struct-return function, assign to the first
// parameter instead of passing it to the call.
- const PAListPtr &PAL = I.getParamAttrs();
+ const AttrListPtr &PAL = I.getAttributes();
bool hasByVal = I.hasByValArgument();
bool isStructRet = I.hasStructRetAttr();
if (isStructRet) {
(*AI)->getType() != FTy->getParamType(ArgNo)) {
Out << '(';
printType(Out, FTy->getParamType(ArgNo),
- /*isSigned=*/PAL.paramHasAttr(ArgNo+1, ParamAttr::SExt));
+ /*isSigned=*/PAL.paramHasAttr(ArgNo+1, Attribute::SExt));
Out << ')';
}
// Check if the argument is expected to be passed by value.
- if (I.paramHasAttr(ArgNo+1, ParamAttr::ByVal))
+ if (I.paramHasAttr(ArgNo+1, Attribute::ByVal))
writeOperandDeref(*AI);
else
writeOperand(*AI);
case Intrinsic::dbg_stoppoint: {
// If we use writeOperand directly we get a "u" suffix which is rejected
// by gcc.
+ std::stringstream SPIStr;
DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
+ SPI.getDirectory()->print(SPIStr);
Out << "\n#line "
<< SPI.getLine()
- << " \"" << SPI.getDirectory()
- << SPI.getFileName() << "\"\n";
+ << " \"";
+ Out << SPIStr.str();
+ SPIStr.clear();
+ SPI.getFileName()->print(SPIStr);
+ Out << SPIStr.str() << "\"\n";
return true;
}
case Intrinsic::x86_sse_cmp_ss:
//===----------------------------------------------------------------------===//
bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM,
- std::ostream &o,
+ raw_ostream &o,
CodeGenFileType FileType,
- bool Fast) {
+ CodeGenOpt::Level OptLevel) {
if (FileType != TargetMachine::AssemblyFile) return true;
PM.add(createGCLoweringPass());
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
PM.add(new CWriter(o));
- PM.add(createCollectorMetadataDeleter());
+ PM.add(createGCInfoDeleter());
return false;
}