#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
-#include "llvm/ParamAttrsList.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/TypeSymbolTable.h"
std::map<const Type *, std::string> TypeNames;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
- std::set<const Value*> ByValParams;
+ 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) {}
delete Mang;
FPConstantMap.clear();
TypeNames.clear();
- intrinsicPrototypesAlreadyGenerated.clear();
ByValParams.clear();
+ intrinsicPrototypesAlreadyGenerated.clear();
return false;
}
bool isSigned = false,
const std::string &VariableName = "",
bool IgnoreName = false,
- const ParamAttrsList *PAL = 0);
+ const PAListPtr &PAL = PAListPtr());
std::ostream &printSimpleType(std::ostream &Out, const Type *Ty,
bool isSigned,
const std::string &NameSoFar = "");
void printStructReturnPointerFunctionType(std::ostream &Out,
- const ParamAttrsList *PAL,
+ 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 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))
// 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 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);
};
/// 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 ParamAttrsList *PAL,
+ const PAListPtr &PAL,
const PointerType *TheTy) {
const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
std::stringstream FunctionInnards;
if (PrintedType)
FunctionInnards << ", ";
const Type *ArgTy = *I;
- if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
assert(isa<PointerType>(ArgTy));
ArgTy = cast<PointerType>(ArgTy)->getElementType();
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt), "");
PrintedType = true;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, RetTy,
- /*isSigned=*/PAL && PAL->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) {
+ const std::string &NameSoFar) {
assert((Ty->isPrimitiveType() || Ty->isInteger() || isa<VectorType>(Ty)) &&
"Invalid type for printSimpleType");
switch (Ty->getTypeID()) {
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::VectorTyID: {
const VectorType *VTy = cast<VectorType>(Ty);
- return printType(Out, VTy->getElementType(), false,
+ return printSimpleType(Out, VTy->getElementType(), isSigned,
" __attribute__((vector_size(" +
utostr(TD->getABITypeSize(VTy)) + " ))) " + NameSoFar);
}
//
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
bool isSigned, const std::string &NameSoFar,
- bool IgnoreName, const ParamAttrsList* PAL) {
+ bool IgnoreName, const PAListPtr &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 && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
assert(isa<PointerType>(ArgTy));
ArgTy = cast<PointerType>(ArgTy)->getElementType();
}
if (I != FTy->param_begin())
FunctionInnards << ", ";
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt), "");
++Idx;
}
if (FTy->isVarArg()) {
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, FTy->getReturnType(),
- /*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
+ /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt), tstr);
return Out;
}
case Type::StructTyID: {
isa<VectorType>(PTy->getElementType()))
ptrName = "(" + ptrName + ")";
- if (PAL)
+ 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);
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 << '(';
} else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
Out << "((";
printType(Out, CPV->getType()); // sign doesn't matter
- Out << ")/*UNDEF*/0)";
+ Out << ")/*UNDEF*/";
+ if (!isa<VectorType>(CPV->getType())) {
+ Out << "0)";
+ } else {
+ Out << "{})";
+ }
return;
}
}
case Type::ArrayTyID:
- if (ConstantArray *CA = cast<ConstantArray>(CPV)) {
+ if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
printConstantArray(CA);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
Out << "(";
printType(Out, CPV->getType());
Out << ")";
- if (ConstantVector *CV = cast<ConstantVector>(CPV)) {
+ if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
printConstantVector(CV);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
}
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 << ')';
}
<< "#define __builtin_stack_restore(X) /* noop */\n"
<< "#endif\n\n";
+ 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";
}
void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
/// isStructReturn - Should this function actually return a struct by-value?
- bool isStructReturn = F->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 *PAL = F->getParamAttrs();
+ const PAListPtr &PAL = F->getParamAttrs();
std::stringstream FunctionInnards;
else
ArgName = "";
const Type *ArgTy = I->getType();
- if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
- assert(isa<PointerType>(ArgTy));
+ if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
ArgTy = cast<PointerType>(ArgTy)->getElementType();
- const Value *Arg = &(*I);
- ByValParams.insert(Arg);
+ ByValParams.insert(I);
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt),
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt),
ArgName);
PrintedArg = true;
++Idx;
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
const Type *ArgTy = *I;
- if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+ if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
assert(isa<PointerType>(ArgTy));
ArgTy = cast<PointerType>(ArgTy)->getElementType();
}
printType(FunctionInnards, ArgTy,
- /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt));
+ /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt));
PrintedArg = true;
++Idx;
}
// Print out the return type and the signature built above.
printType(Out, RetTy,
- /*isSigned=*/ PAL && PAL->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.isStructReturn();
+ bool isStructReturn = F.hasStructRetAttr();
printFunctionSignature(&F, false);
Out << " {\n";
//
void CWriter::visitReturnInst(ReturnInst &I) {
// If this is a struct return function, return the temporary struct.
- bool isStructReturn = I.getParent()->getParent()->isStructReturn();
+ bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr();
if (isStructReturn) {
Out << " return StructReturn;\n";
// Make sure we really get a sext from bool by subtracing the bool from 0
Out << "0-";
}
- // If it's a byval parameter being casted, then takes its address.
- bool isByVal = ByValParams.count(I.getOperand(0));
- if (isByVal) {
- assert(I.getOpcode() == Instruction::BitCast &&
- "ByVal aggregate parameter must ptr type");
- Out << '&';
- }
writeOperand(I.getOperand(0));
if (DstTy == Type::Int1Ty &&
(I.getOpcode() == Instruction::Trunc ||
case Intrinsic::prefetch:
case Intrinsic::dbg_stoppoint:
case Intrinsic::powi:
- // We directly implement these intrinsics
+ 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)) {
// 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::memory_barrier:
- Out << "0; __sync_syncronize()";
- return;
- 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:
- 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::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()";
+ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
+ if (visitBuiltinCall(I, ID, WroteCallee))
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.
- const ParamAttrsList *PAL = I.getParamAttrs();
+ const PAListPtr &PAL = I.getParamAttrs();
bool hasByVal = I.hasByValArgument();
- bool isStructRet = I.isStructReturn();
+ bool isStructRet = I.hasStructRetAttr();
if (isStructRet) {
- bool isByVal = ByValParams.count(I.getOperand(1));
- if (!isByVal) Out << "*(";
- writeOperand(I.getOperand(1));
- if (!isByVal) Out << ")";
+ writeOperandDeref(I.getOperand(1));
Out << " = ";
}
(*AI)->getType() != FTy->getParamType(ArgNo)) {
Out << '(';
printType(Out, FTy->getParamType(ArgNo),
- /*isSigned=*/PAL && PAL->paramHasAttr(ArgNo+1, ParamAttr::SExt));
+ /*isSigned=*/PAL.paramHasAttr(ArgNo+1, ParamAttr::SExt));
Out << ')';
}
// Check if the argument is expected to be passed by value.
- bool isOutByVal = PAL && PAL->paramHasAttr(ArgNo+1, ParamAttr::ByVal);
- // Check if this argument itself is passed in by reference.
- bool isInByVal = ByValParams.count(*AI);
- if (isOutByVal && !isInByVal)
- Out << "*(";
- else if (!isOutByVal && isInByVal)
- Out << "&(";
- writeOperand(*AI);
- if (isOutByVal ^ isInByVal)
- Out << ")";
+ 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) {
Out << "__asm__ volatile (\"" << asmstr << "\"\n";
Out << " :";
- for (std::vector<std::pair<std::string, Value*> >::iterator I = Output.begin(),
+ for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(),
E = Output.end(); I != E; ++I) {
Out << "\"" << I->first << "\"(";
writeOperandRaw(I->second);
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)) {
- // Check if it's actually an aggregate parameter passed by value.
- bool isByVal = ByValParams.count(Ptr);
- Out << ((HasImplicitAddress || isByVal) ? "." : "->");
- 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<VectorType>(*I)) {
Out << '[';
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::writeMemoryAccess(Value *Operand, const Type *OperandType,
}
void CWriter::visitLoadInst(LoadInst &I) {
-
writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(),
I.getAlignment());
}
void CWriter::visitStoreInst(StoreInst &I) {
-
writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(),
I.isVolatile(), I.getAlignment());
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));
}
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 << "}";
+}
+
+
//===----------------------------------------------------------------------===//
// External Interface declaration
//===----------------------------------------------------------------------===//