|  | //===- subzero/src/IceConverter.cpp - Converts LLVM to Ice  ---------------===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Implements the LLVM to ICE converter. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "IceConverter.h" | 
|  |  | 
|  | #include "IceCfg.h" | 
|  | #include "IceCfgNode.h" | 
|  | #include "IceClFlags.h" | 
|  | #include "IceDefs.h" | 
|  | #include "IceGlobalContext.h" | 
|  | #include "IceGlobalInits.h" | 
|  | #include "IceInst.h" | 
|  | #include "IceMangling.h" | 
|  | #include "IceOperand.h" | 
|  | #include "IceTargetLowering.h" | 
|  | #include "IceTypes.h" | 
|  | #include "IceTypeConverter.h" | 
|  |  | 
|  | #ifdef __clang__ | 
|  | #pragma clang diagnostic push | 
|  | #pragma clang diagnostic ignored "-Wunused-parameter" | 
|  | #endif // __clang__ | 
|  |  | 
|  | #include "llvm/IR/Constant.h" | 
|  | #include "llvm/IR/Constants.h" | 
|  | #include "llvm/IR/DataLayout.h" | 
|  | #include "llvm/IR/Instruction.h" | 
|  | #include "llvm/IR/Instructions.h" | 
|  | #include "llvm/IR/LLVMContext.h" | 
|  | #include "llvm/IR/Module.h" | 
|  |  | 
|  | #ifdef __clang__ | 
|  | #pragma clang diagnostic pop | 
|  | #endif // __clang__ | 
|  |  | 
|  | // TODO(kschimpf): Remove two namespaces being visible at once. | 
|  | using namespace llvm; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Debugging helper | 
|  | template <typename T> static std::string LLVMObjectAsString(const T *O) { | 
|  | std::string Dump; | 
|  | raw_string_ostream Stream(Dump); | 
|  | O->print(Stream); | 
|  | return Stream.str(); | 
|  | } | 
|  |  | 
|  | // Base class for converting LLVM to ICE. | 
|  | // TODO(stichnot): Redesign Converter, LLVM2ICEConverter, | 
|  | // LLVM2ICEFunctionConverter, and LLVM2ICEGlobalsConverter with respect to | 
|  | // Translator.  In particular, the unique_ptr ownership rules in | 
|  | // LLVM2ICEFunctionConverter. | 
|  | class LLVM2ICEConverter { | 
|  | LLVM2ICEConverter() = delete; | 
|  | LLVM2ICEConverter(const LLVM2ICEConverter &) = delete; | 
|  | LLVM2ICEConverter &operator=(const LLVM2ICEConverter &) = delete; | 
|  |  | 
|  | public: | 
|  | explicit LLVM2ICEConverter(Ice::Converter &Converter) | 
|  | : Converter(Converter), Ctx(Converter.getContext()), | 
|  | TypeConverter(Converter.getModule()->getContext()) {} | 
|  |  | 
|  | Ice::Converter &getConverter() const { return Converter; } | 
|  |  | 
|  | protected: | 
|  | Ice::Converter &Converter; | 
|  | Ice::GlobalContext *Ctx; | 
|  | const Ice::TypeConverter TypeConverter; | 
|  | }; | 
|  |  | 
|  | // Converter from LLVM functions to ICE. The entry point is the convertFunction | 
|  | // method. | 
|  | // | 
|  | // Note: this currently assumes that the given IR was verified to be valid | 
|  | // PNaCl bitcode. Otherwise, the behavior is undefined. | 
|  | class LLVM2ICEFunctionConverter : LLVM2ICEConverter { | 
|  | LLVM2ICEFunctionConverter() = delete; | 
|  | LLVM2ICEFunctionConverter(const LLVM2ICEFunctionConverter &) = delete; | 
|  | LLVM2ICEFunctionConverter & | 
|  | operator=(const LLVM2ICEFunctionConverter &) = delete; | 
|  |  | 
|  | public: | 
|  | explicit LLVM2ICEFunctionConverter(Ice::Converter &Converter) | 
|  | : LLVM2ICEConverter(Converter), Func(nullptr) {} | 
|  |  | 
|  | void convertFunction(const Function *F) { | 
|  | Func = Ice::Cfg::create(Ctx, Converter.getNextSequenceNumber()); | 
|  | { | 
|  | Ice::CfgLocalAllocatorScope _(Func.get()); | 
|  |  | 
|  | VarMap.clear(); | 
|  | NodeMap.clear(); | 
|  | Func->setFunctionName( | 
|  | Ctx->getGlobalString(Ice::mangleName(F->getName()))); | 
|  | Func->setReturnType(convertToIceType(F->getReturnType())); | 
|  | Func->setInternal(F->hasInternalLinkage()); | 
|  | Ice::TimerMarker T(Ice::TimerStack::TT_llvmConvert, Func.get()); | 
|  |  | 
|  | // The initial definition/use of each arg is the entry node. | 
|  | for (auto ArgI = F->arg_begin(), ArgE = F->arg_end(); ArgI != ArgE; | 
|  | ++ArgI) { | 
|  | Func->addArg(mapValueToIceVar(&*ArgI)); | 
|  | } | 
|  |  | 
|  | // Make an initial pass through the block list just to resolve the blocks | 
|  | // in the original linearized order. Otherwise the ICE linearized order | 
|  | // will be affected by branch targets in terminator instructions. | 
|  | for (const BasicBlock &BBI : *F) | 
|  | mapBasicBlockToNode(&BBI); | 
|  | for (const BasicBlock &BBI : *F) | 
|  | convertBasicBlock(&BBI); | 
|  | Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock())); | 
|  | Func->computeInOutEdges(); | 
|  | } | 
|  | Converter.translateFcn(std::move(Func)); | 
|  | } | 
|  |  | 
|  | // convertConstant() does not use Func or require it to be a valid Ice::Cfg | 
|  | // pointer. As such, it's suitable for e.g. constructing global initializers. | 
|  | Ice::Constant *convertConstant(const Constant *Const) { | 
|  | if (const auto GV = dyn_cast<GlobalValue>(Const)) { | 
|  | Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV); | 
|  | bool IsUndefined = false; | 
|  | if (const auto *Func = llvm::dyn_cast<Ice::FunctionDeclaration>(Decl)) | 
|  | IsUndefined = Func->isProto(); | 
|  | else if (const auto *Var = llvm::dyn_cast<Ice::VariableDeclaration>(Decl)) | 
|  | IsUndefined = !Var->hasInitializer(); | 
|  | else | 
|  | report_fatal_error("Unhandled GlobalDeclaration type"); | 
|  | if (IsUndefined) | 
|  | return Ctx->getConstantExternSym(Decl->getName()); | 
|  | else { | 
|  | const Ice::RelocOffsetT Offset = 0; | 
|  | return Ctx->getConstantSym( | 
|  | Offset, Ctx->getGlobalString(Decl->getName().toString())); | 
|  | } | 
|  | } else if (const auto CI = dyn_cast<ConstantInt>(Const)) { | 
|  | Ice::Type Ty = convertToIceType(CI->getType()); | 
|  | return Ctx->getConstantInt(Ty, CI->getSExtValue()); | 
|  | } else if (const auto CFP = dyn_cast<ConstantFP>(Const)) { | 
|  | Ice::Type Type = convertToIceType(CFP->getType()); | 
|  | if (Type == Ice::IceType_f32) | 
|  | return Ctx->getConstantFloat(CFP->getValueAPF().convertToFloat()); | 
|  | else if (Type == Ice::IceType_f64) | 
|  | return Ctx->getConstantDouble(CFP->getValueAPF().convertToDouble()); | 
|  | llvm_unreachable("Unexpected floating point type"); | 
|  | return nullptr; | 
|  | } else if (const auto CU = dyn_cast<UndefValue>(Const)) { | 
|  | return Ctx->getConstantUndef(convertToIceType(CU->getType())); | 
|  | } else { | 
|  | llvm_unreachable("Unhandled constant type"); | 
|  | return nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | // LLVM values (instructions, etc.) are mapped directly to ICE variables. | 
|  | // mapValueToIceVar has a version that forces an ICE type on the variable, | 
|  | // and a version that just uses convertToIceType on V. | 
|  | Ice::Variable *mapValueToIceVar(const Value *V, Ice::Type IceTy) { | 
|  | if (IceTy == Ice::IceType_void) | 
|  | return nullptr; | 
|  | if (VarMap.find(V) == VarMap.end()) { | 
|  | VarMap[V] = Func->makeVariable(IceTy); | 
|  | if (Ice::BuildDefs::dump()) | 
|  | VarMap[V]->setName(Func.get(), V->getName()); | 
|  | } | 
|  | return VarMap[V]; | 
|  | } | 
|  |  | 
|  | Ice::Variable *mapValueToIceVar(const Value *V) { | 
|  | return mapValueToIceVar(V, convertToIceType(V->getType())); | 
|  | } | 
|  |  | 
|  | Ice::CfgNode *mapBasicBlockToNode(const BasicBlock *BB) { | 
|  | if (NodeMap.find(BB) == NodeMap.end()) { | 
|  | NodeMap[BB] = Func->makeNode(); | 
|  | if (Ice::BuildDefs::dump()) | 
|  | NodeMap[BB]->setName(BB->getName()); | 
|  | } | 
|  | return NodeMap[BB]; | 
|  | } | 
|  |  | 
|  | Ice::Type convertToIceType(Type *LLVMTy) const { | 
|  | Ice::Type IceTy = TypeConverter.convertToIceType(LLVMTy); | 
|  | if (IceTy == Ice::IceType_NUM) | 
|  | report_fatal_error(std::string("Invalid PNaCl type ") + | 
|  | LLVMObjectAsString(LLVMTy)); | 
|  | return IceTy; | 
|  | } | 
|  |  | 
|  | // Given an LLVM instruction and an operand number, produce the Ice::Operand | 
|  | // this refers to. If there's no such operand, return nullptr. | 
|  | Ice::Operand *convertOperand(const Instruction *Instr, unsigned OpNum) { | 
|  | if (OpNum >= Instr->getNumOperands()) { | 
|  | return nullptr; | 
|  | } | 
|  | const Value *Op = Instr->getOperand(OpNum); | 
|  | return convertValue(Op); | 
|  | } | 
|  |  | 
|  | Ice::Operand *convertValue(const Value *Op) { | 
|  | if (const auto Const = dyn_cast<Constant>(Op)) { | 
|  | return convertConstant(Const); | 
|  | } else { | 
|  | return mapValueToIceVar(Op); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Note: this currently assumes a 1x1 mapping between LLVM IR and Ice | 
|  | // instructions. | 
|  | Ice::Inst *convertInstruction(const Instruction *Instr) { | 
|  | switch (Instr->getOpcode()) { | 
|  | case Instruction::PHI: | 
|  | return convertPHINodeInstruction(cast<PHINode>(Instr)); | 
|  | case Instruction::Br: | 
|  | return convertBrInstruction(cast<BranchInst>(Instr)); | 
|  | case Instruction::Ret: | 
|  | return convertRetInstruction(cast<ReturnInst>(Instr)); | 
|  | case Instruction::IntToPtr: | 
|  | return convertIntToPtrInstruction(cast<IntToPtrInst>(Instr)); | 
|  | case Instruction::PtrToInt: | 
|  | return convertPtrToIntInstruction(cast<PtrToIntInst>(Instr)); | 
|  | case Instruction::ICmp: | 
|  | return convertICmpInstruction(cast<ICmpInst>(Instr)); | 
|  | case Instruction::FCmp: | 
|  | return convertFCmpInstruction(cast<FCmpInst>(Instr)); | 
|  | case Instruction::Select: | 
|  | return convertSelectInstruction(cast<SelectInst>(Instr)); | 
|  | case Instruction::Switch: | 
|  | return convertSwitchInstruction(cast<SwitchInst>(Instr)); | 
|  | case Instruction::Load: | 
|  | return convertLoadInstruction(cast<LoadInst>(Instr)); | 
|  | case Instruction::Store: | 
|  | return convertStoreInstruction(cast<StoreInst>(Instr)); | 
|  | case Instruction::ZExt: | 
|  | return convertCastInstruction(cast<ZExtInst>(Instr), Ice::InstCast::Zext); | 
|  | case Instruction::SExt: | 
|  | return convertCastInstruction(cast<SExtInst>(Instr), Ice::InstCast::Sext); | 
|  | case Instruction::Trunc: | 
|  | return convertCastInstruction(cast<TruncInst>(Instr), | 
|  | Ice::InstCast::Trunc); | 
|  | case Instruction::FPTrunc: | 
|  | return convertCastInstruction(cast<FPTruncInst>(Instr), | 
|  | Ice::InstCast::Fptrunc); | 
|  | case Instruction::FPExt: | 
|  | return convertCastInstruction(cast<FPExtInst>(Instr), | 
|  | Ice::InstCast::Fpext); | 
|  | case Instruction::FPToSI: | 
|  | return convertCastInstruction(cast<FPToSIInst>(Instr), | 
|  | Ice::InstCast::Fptosi); | 
|  | case Instruction::FPToUI: | 
|  | return convertCastInstruction(cast<FPToUIInst>(Instr), | 
|  | Ice::InstCast::Fptoui); | 
|  | case Instruction::SIToFP: | 
|  | return convertCastInstruction(cast<SIToFPInst>(Instr), | 
|  | Ice::InstCast::Sitofp); | 
|  | case Instruction::UIToFP: | 
|  | return convertCastInstruction(cast<UIToFPInst>(Instr), | 
|  | Ice::InstCast::Uitofp); | 
|  | case Instruction::BitCast: | 
|  | return convertCastInstruction(cast<BitCastInst>(Instr), | 
|  | Ice::InstCast::Bitcast); | 
|  | case Instruction::Add: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Add); | 
|  | case Instruction::Sub: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Sub); | 
|  | case Instruction::Mul: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Mul); | 
|  | case Instruction::UDiv: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Udiv); | 
|  | case Instruction::SDiv: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Sdiv); | 
|  | case Instruction::URem: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Urem); | 
|  | case Instruction::SRem: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Srem); | 
|  | case Instruction::Shl: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Shl); | 
|  | case Instruction::LShr: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Lshr); | 
|  | case Instruction::AShr: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Ashr); | 
|  | case Instruction::FAdd: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Fadd); | 
|  | case Instruction::FSub: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Fsub); | 
|  | case Instruction::FMul: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Fmul); | 
|  | case Instruction::FDiv: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Fdiv); | 
|  | case Instruction::FRem: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Frem); | 
|  | case Instruction::And: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::And); | 
|  | case Instruction::Or: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Or); | 
|  | case Instruction::Xor: | 
|  | return convertArithInstruction(Instr, Ice::InstArithmetic::Xor); | 
|  | case Instruction::ExtractElement: | 
|  | return convertExtractElementInstruction(cast<ExtractElementInst>(Instr)); | 
|  | case Instruction::InsertElement: | 
|  | return convertInsertElementInstruction(cast<InsertElementInst>(Instr)); | 
|  | case Instruction::Call: | 
|  | return convertCallInstruction(cast<CallInst>(Instr)); | 
|  | case Instruction::Alloca: | 
|  | return convertAllocaInstruction(cast<AllocaInst>(Instr)); | 
|  | case Instruction::Unreachable: | 
|  | return convertUnreachableInstruction(cast<UnreachableInst>(Instr)); | 
|  | default: | 
|  | report_fatal_error(std::string("Invalid PNaCl instruction: ") + | 
|  | LLVMObjectAsString(Instr)); | 
|  | } | 
|  |  | 
|  | llvm_unreachable("convertInstruction"); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertLoadInstruction(const LoadInst *Instr) { | 
|  | Ice::Operand *Src = convertOperand(Instr, 0); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | return Ice::InstLoad::create(Func.get(), Dest, Src); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertStoreInstruction(const StoreInst *Instr) { | 
|  | Ice::Operand *Addr = convertOperand(Instr, 1); | 
|  | Ice::Operand *Val = convertOperand(Instr, 0); | 
|  | return Ice::InstStore::create(Func.get(), Val, Addr); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertArithInstruction(const Instruction *Instr, | 
|  | Ice::InstArithmetic::OpKind Opcode) { | 
|  | const auto BinOp = cast<BinaryOperator>(Instr); | 
|  | Ice::Operand *Src0 = convertOperand(Instr, 0); | 
|  | Ice::Operand *Src1 = convertOperand(Instr, 1); | 
|  | Ice::Variable *Dest = mapValueToIceVar(BinOp); | 
|  | return Ice::InstArithmetic::create(Func.get(), Opcode, Dest, Src0, Src1); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertPHINodeInstruction(const PHINode *Instr) { | 
|  | unsigned NumValues = Instr->getNumIncomingValues(); | 
|  | Ice::InstPhi *IcePhi = | 
|  | Ice::InstPhi::create(Func.get(), NumValues, mapValueToIceVar(Instr)); | 
|  | for (unsigned N = 0, E = NumValues; N != E; ++N) { | 
|  | IcePhi->addArgument(convertOperand(Instr, N), | 
|  | mapBasicBlockToNode(Instr->getIncomingBlock(N))); | 
|  | } | 
|  | return IcePhi; | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertBrInstruction(const BranchInst *Instr) { | 
|  | if (Instr->isConditional()) { | 
|  | Ice::Operand *Src = convertOperand(Instr, 0); | 
|  | BasicBlock *BBThen = Instr->getSuccessor(0); | 
|  | BasicBlock *BBElse = Instr->getSuccessor(1); | 
|  | Ice::CfgNode *NodeThen = mapBasicBlockToNode(BBThen); | 
|  | Ice::CfgNode *NodeElse = mapBasicBlockToNode(BBElse); | 
|  | return Ice::InstBr::create(Func.get(), Src, NodeThen, NodeElse); | 
|  | } else { | 
|  | BasicBlock *BBSucc = Instr->getSuccessor(0); | 
|  | return Ice::InstBr::create(Func.get(), mapBasicBlockToNode(BBSucc)); | 
|  | } | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertIntToPtrInstruction(const IntToPtrInst *Instr) { | 
|  | Ice::Operand *Src = convertOperand(Instr, 0); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr, Ice::getPointerType()); | 
|  | return Ice::InstAssign::create(Func.get(), Dest, Src); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertPtrToIntInstruction(const PtrToIntInst *Instr) { | 
|  | Ice::Operand *Src = convertOperand(Instr, 0); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | return Ice::InstAssign::create(Func.get(), Dest, Src); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertRetInstruction(const ReturnInst *Instr) { | 
|  | Ice::Operand *RetOperand = convertOperand(Instr, 0); | 
|  | if (RetOperand) { | 
|  | return Ice::InstRet::create(Func.get(), RetOperand); | 
|  | } else { | 
|  | return Ice::InstRet::create(Func.get()); | 
|  | } | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertCastInstruction(const Instruction *Instr, | 
|  | Ice::InstCast::OpKind CastKind) { | 
|  | Ice::Operand *Src = convertOperand(Instr, 0); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | return Ice::InstCast::create(Func.get(), CastKind, Dest, Src); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertICmpInstruction(const ICmpInst *Instr) { | 
|  | Ice::Operand *Src0 = convertOperand(Instr, 0); | 
|  | Ice::Operand *Src1 = convertOperand(Instr, 1); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  |  | 
|  | Ice::InstIcmp::ICond Cond; | 
|  | switch (Instr->getPredicate()) { | 
|  | default: | 
|  | llvm_unreachable("ICmpInst predicate"); | 
|  | case CmpInst::ICMP_EQ: | 
|  | Cond = Ice::InstIcmp::Eq; | 
|  | break; | 
|  | case CmpInst::ICMP_NE: | 
|  | Cond = Ice::InstIcmp::Ne; | 
|  | break; | 
|  | case CmpInst::ICMP_UGT: | 
|  | Cond = Ice::InstIcmp::Ugt; | 
|  | break; | 
|  | case CmpInst::ICMP_UGE: | 
|  | Cond = Ice::InstIcmp::Uge; | 
|  | break; | 
|  | case CmpInst::ICMP_ULT: | 
|  | Cond = Ice::InstIcmp::Ult; | 
|  | break; | 
|  | case CmpInst::ICMP_ULE: | 
|  | Cond = Ice::InstIcmp::Ule; | 
|  | break; | 
|  | case CmpInst::ICMP_SGT: | 
|  | Cond = Ice::InstIcmp::Sgt; | 
|  | break; | 
|  | case CmpInst::ICMP_SGE: | 
|  | Cond = Ice::InstIcmp::Sge; | 
|  | break; | 
|  | case CmpInst::ICMP_SLT: | 
|  | Cond = Ice::InstIcmp::Slt; | 
|  | break; | 
|  | case CmpInst::ICMP_SLE: | 
|  | Cond = Ice::InstIcmp::Sle; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return Ice::InstIcmp::create(Func.get(), Cond, Dest, Src0, Src1); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertFCmpInstruction(const FCmpInst *Instr) { | 
|  | Ice::Operand *Src0 = convertOperand(Instr, 0); | 
|  | Ice::Operand *Src1 = convertOperand(Instr, 1); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  |  | 
|  | Ice::InstFcmp::FCond Cond; | 
|  | switch (Instr->getPredicate()) { | 
|  |  | 
|  | default: | 
|  | llvm_unreachable("FCmpInst predicate"); | 
|  |  | 
|  | case CmpInst::FCMP_FALSE: | 
|  | Cond = Ice::InstFcmp::False; | 
|  | break; | 
|  | case CmpInst::FCMP_OEQ: | 
|  | Cond = Ice::InstFcmp::Oeq; | 
|  | break; | 
|  | case CmpInst::FCMP_OGT: | 
|  | Cond = Ice::InstFcmp::Ogt; | 
|  | break; | 
|  | case CmpInst::FCMP_OGE: | 
|  | Cond = Ice::InstFcmp::Oge; | 
|  | break; | 
|  | case CmpInst::FCMP_OLT: | 
|  | Cond = Ice::InstFcmp::Olt; | 
|  | break; | 
|  | case CmpInst::FCMP_OLE: | 
|  | Cond = Ice::InstFcmp::Ole; | 
|  | break; | 
|  | case CmpInst::FCMP_ONE: | 
|  | Cond = Ice::InstFcmp::One; | 
|  | break; | 
|  | case CmpInst::FCMP_ORD: | 
|  | Cond = Ice::InstFcmp::Ord; | 
|  | break; | 
|  | case CmpInst::FCMP_UEQ: | 
|  | Cond = Ice::InstFcmp::Ueq; | 
|  | break; | 
|  | case CmpInst::FCMP_UGT: | 
|  | Cond = Ice::InstFcmp::Ugt; | 
|  | break; | 
|  | case CmpInst::FCMP_UGE: | 
|  | Cond = Ice::InstFcmp::Uge; | 
|  | break; | 
|  | case CmpInst::FCMP_ULT: | 
|  | Cond = Ice::InstFcmp::Ult; | 
|  | break; | 
|  | case CmpInst::FCMP_ULE: | 
|  | Cond = Ice::InstFcmp::Ule; | 
|  | break; | 
|  | case CmpInst::FCMP_UNE: | 
|  | Cond = Ice::InstFcmp::Une; | 
|  | break; | 
|  | case CmpInst::FCMP_UNO: | 
|  | Cond = Ice::InstFcmp::Uno; | 
|  | break; | 
|  | case CmpInst::FCMP_TRUE: | 
|  | Cond = Ice::InstFcmp::True; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return Ice::InstFcmp::create(Func.get(), Cond, Dest, Src0, Src1); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertExtractElementInstruction(const ExtractElementInst *Instr) { | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | Ice::Operand *Source1 = convertValue(Instr->getOperand(0)); | 
|  | Ice::Operand *Source2 = convertValue(Instr->getOperand(1)); | 
|  | return Ice::InstExtractElement::create(Func.get(), Dest, Source1, Source2); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertInsertElementInstruction(const InsertElementInst *Instr) { | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | Ice::Operand *Source1 = convertValue(Instr->getOperand(0)); | 
|  | Ice::Operand *Source2 = convertValue(Instr->getOperand(1)); | 
|  | Ice::Operand *Source3 = convertValue(Instr->getOperand(2)); | 
|  | return Ice::InstInsertElement::create(Func.get(), Dest, Source1, Source2, | 
|  | Source3); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertSelectInstruction(const SelectInst *Instr) { | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | Ice::Operand *Cond = convertValue(Instr->getCondition()); | 
|  | Ice::Operand *Source1 = convertValue(Instr->getTrueValue()); | 
|  | Ice::Operand *Source2 = convertValue(Instr->getFalseValue()); | 
|  | return Ice::InstSelect::create(Func.get(), Dest, Cond, Source1, Source2); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertSwitchInstruction(const SwitchInst *Instr) { | 
|  | Ice::Operand *Source = convertValue(Instr->getCondition()); | 
|  | Ice::CfgNode *LabelDefault = mapBasicBlockToNode(Instr->getDefaultDest()); | 
|  | unsigned NumCases = Instr->getNumCases(); | 
|  | Ice::InstSwitch *Switch = | 
|  | Ice::InstSwitch::create(Func.get(), NumCases, Source, LabelDefault); | 
|  | unsigned CurrentCase = 0; | 
|  | for (SwitchInst::ConstCaseIt I = Instr->case_begin(), E = Instr->case_end(); | 
|  | I != E; ++I, ++CurrentCase) { | 
|  | uint64_t CaseValue = I.getCaseValue()->getSExtValue(); | 
|  | Ice::CfgNode *CaseSuccessor = mapBasicBlockToNode(I.getCaseSuccessor()); | 
|  | Switch->addBranch(CurrentCase, CaseValue, CaseSuccessor); | 
|  | } | 
|  | return Switch; | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertCallInstruction(const CallInst *Instr) { | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr); | 
|  | Ice::Operand *CallTarget = convertValue(Instr->getCalledValue()); | 
|  | unsigned NumArgs = Instr->getNumArgOperands(); | 
|  | // Note: Subzero doesn't (yet) do anything special with the Tail flag in | 
|  | // the bitcode, i.e. CallInst::isTailCall(). | 
|  | Ice::InstCall *NewInst = nullptr; | 
|  | const Ice::Intrinsics::FullIntrinsicInfo *Info = nullptr; | 
|  |  | 
|  | if (const auto Target = dyn_cast<Ice::ConstantRelocatable>(CallTarget)) { | 
|  | // Check if this direct call is to an Intrinsic (starts with "llvm.") | 
|  | bool BadIntrinsic; | 
|  | Info = Ctx->getIntrinsicsInfo().find(Target->getName(), BadIntrinsic); | 
|  | if (BadIntrinsic) { | 
|  | report_fatal_error(std::string("Invalid PNaCl intrinsic call: ") + | 
|  | LLVMObjectAsString(Instr)); | 
|  | } | 
|  | if (Info) | 
|  | NewInst = Ice::InstIntrinsicCall::create(Func.get(), NumArgs, Dest, | 
|  | CallTarget, Info->Info); | 
|  | } | 
|  |  | 
|  | // Not an intrinsic call. | 
|  | if (NewInst == nullptr) { | 
|  | NewInst = Ice::InstCall::create(Func.get(), NumArgs, Dest, CallTarget, | 
|  | Instr->isTailCall()); | 
|  | } | 
|  | for (unsigned i = 0; i < NumArgs; ++i) { | 
|  | NewInst->addArg(convertOperand(Instr, i)); | 
|  | } | 
|  | if (Info) { | 
|  | validateIntrinsicCall(NewInst, Info); | 
|  | } | 
|  | return NewInst; | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertAllocaInstruction(const AllocaInst *Instr) { | 
|  | // PNaCl bitcode only contains allocas of byte-granular objects. | 
|  | Ice::Operand *ByteCount = convertValue(Instr->getArraySize()); | 
|  | uint32_t Align = Instr->getAlignment(); | 
|  | Ice::Variable *Dest = mapValueToIceVar(Instr, Ice::getPointerType()); | 
|  |  | 
|  | return Ice::InstAlloca::create(Func.get(), Dest, ByteCount, Align); | 
|  | } | 
|  |  | 
|  | Ice::Inst *convertUnreachableInstruction(const UnreachableInst * /*Instr*/) { | 
|  | return Ice::InstUnreachable::create(Func.get()); | 
|  | } | 
|  |  | 
|  | Ice::CfgNode *convertBasicBlock(const BasicBlock *BB) { | 
|  | Ice::CfgNode *Node = mapBasicBlockToNode(BB); | 
|  | for (const Instruction &II : *BB) { | 
|  | Ice::Inst *Instr = convertInstruction(&II); | 
|  | Node->appendInst(Instr); | 
|  | } | 
|  | return Node; | 
|  | } | 
|  |  | 
|  | void validateIntrinsicCall(const Ice::InstCall *Call, | 
|  | const Ice::Intrinsics::FullIntrinsicInfo *I) { | 
|  | Ice::SizeT ArgIndex = 0; | 
|  | switch (I->validateCall(Call, ArgIndex)) { | 
|  | case Ice::Intrinsics::IsValidCall: | 
|  | break; | 
|  | case Ice::Intrinsics::BadReturnType: { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Intrinsic call expects return type " << I->getReturnType() | 
|  | << ". Found: " << Call->getReturnType(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | break; | 
|  | } | 
|  | case Ice::Intrinsics::WrongNumOfArgs: { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Intrinsic call expects " << I->getNumArgs() | 
|  | << ". Found: " << Call->getNumArgs(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | break; | 
|  | } | 
|  | case Ice::Intrinsics::WrongCallArgType: { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Intrinsic call argument " << ArgIndex << " expects type " | 
|  | << I->getArgType(ArgIndex) | 
|  | << ". Found: " << Call->getArg(ArgIndex)->getType(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Data | 
|  | std::unique_ptr<Ice::Cfg> Func; | 
|  | std::map<const Value *, Ice::Variable *> VarMap; | 
|  | std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; | 
|  | }; | 
|  |  | 
|  | // Converter from LLVM global variables to ICE. The entry point is the | 
|  | // convertGlobalsToIce method. | 
|  | // | 
|  | // Note: this currently assumes that the given IR was verified to be valid | 
|  | // PNaCl bitcode. Otherwise, the behavior is undefined. | 
|  | class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter { | 
|  | LLVM2ICEGlobalsConverter() = delete; | 
|  | LLVM2ICEGlobalsConverter(const LLVM2ICEGlobalsConverter &) = delete; | 
|  | LLVM2ICEGlobalsConverter & | 
|  | operator=(const LLVM2ICEGlobalsConverter &) = delete; | 
|  |  | 
|  | public: | 
|  | explicit LLVM2ICEGlobalsConverter(Ice::Converter &Converter, | 
|  | Ice::VariableDeclarationList *G) | 
|  | : LLVM2ICEConverter(Converter), GlobalPool(G) {} | 
|  |  | 
|  | /// Converts global variables, and their initializers into ICE global variable | 
|  | /// declarations, for module Mod. Returns the set of converted declarations. | 
|  | void convertGlobalsToIce(Module *Mod); | 
|  |  | 
|  | private: | 
|  | // Adds the Initializer to the list of initializers for the Global variable | 
|  | // declaration. | 
|  | void addGlobalInitializer(Ice::VariableDeclaration &Global, | 
|  | const Constant *Initializer) { | 
|  | constexpr bool HasOffset = false; | 
|  | constexpr Ice::RelocOffsetT Offset = 0; | 
|  | addGlobalInitializer(Global, Initializer, HasOffset, Offset); | 
|  | } | 
|  |  | 
|  | // Adds Initializer to the list of initializers for Global variable | 
|  | // declaration. HasOffset is true only if Initializer is a relocation | 
|  | // initializer and Offset should be added to the relocation. | 
|  | void addGlobalInitializer(Ice::VariableDeclaration &Global, | 
|  | const Constant *Initializer, bool HasOffset, | 
|  | Ice::RelocOffsetT Offset); | 
|  |  | 
|  | // Converts the given constant C to the corresponding integer literal it | 
|  | // contains. | 
|  | Ice::RelocOffsetT getIntegerLiteralConstant(const Value *C) { | 
|  | const auto CI = dyn_cast<ConstantInt>(C); | 
|  | if (CI && CI->getType()->isIntegerTy(32)) | 
|  | return CI->getSExtValue(); | 
|  |  | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Constant not i32 literal: " << *C; | 
|  | report_fatal_error(StrBuf.str()); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | Ice::VariableDeclarationList *GlobalPool; | 
|  | }; | 
|  |  | 
|  | void LLVM2ICEGlobalsConverter::convertGlobalsToIce(Module *Mod) { | 
|  | for (Module::const_global_iterator I = Mod->global_begin(), | 
|  | E = Mod->global_end(); | 
|  | I != E; ++I) { | 
|  |  | 
|  | const GlobalVariable *GV = &*I; | 
|  |  | 
|  | Ice::GlobalDeclaration *Var = getConverter().getGlobalDeclaration(GV); | 
|  | auto *VarDecl = cast<Ice::VariableDeclaration>(Var); | 
|  | GlobalPool->push_back(VarDecl); | 
|  |  | 
|  | if (!GV->hasInternalLinkage() && GV->hasInitializer()) { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Can't define external global declaration: " << GV->getName(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  |  | 
|  | if (!GV->hasInitializer()) { | 
|  | if (Ice::getFlags().getAllowUninitializedGlobals()) | 
|  | continue; | 
|  | else { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Global declaration missing initializer: " << GV->getName(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  | } | 
|  |  | 
|  | const Constant *Initializer = GV->getInitializer(); | 
|  | if (const auto CompoundInit = dyn_cast<ConstantStruct>(Initializer)) { | 
|  | for (ConstantStruct::const_op_iterator I = CompoundInit->op_begin(), | 
|  | E = CompoundInit->op_end(); | 
|  | I != E; ++I) { | 
|  | if (const auto Init = dyn_cast<Constant>(I)) { | 
|  | addGlobalInitializer(*VarDecl, Init); | 
|  | } | 
|  | } | 
|  | } else { | 
|  | addGlobalInitializer(*VarDecl, Initializer); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void LLVM2ICEGlobalsConverter::addGlobalInitializer( | 
|  | Ice::VariableDeclaration &Global, const Constant *Initializer, | 
|  | bool HasOffset, Ice::RelocOffsetT Offset) { | 
|  | (void)HasOffset; | 
|  | assert(HasOffset || Offset == 0); | 
|  |  | 
|  | if (const auto CDA = dyn_cast<ConstantDataArray>(Initializer)) { | 
|  | assert(!HasOffset && isa<IntegerType>(CDA->getElementType()) && | 
|  | (cast<IntegerType>(CDA->getElementType())->getBitWidth() == 8)); | 
|  | Global.addInitializer(Ice::VariableDeclaration::DataInitializer::create( | 
|  | GlobalPool, CDA->getRawDataValues().data(), CDA->getNumElements())); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (isa<ConstantAggregateZero>(Initializer)) { | 
|  | if (const auto AT = dyn_cast<ArrayType>(Initializer->getType())) { | 
|  | assert(!HasOffset && isa<IntegerType>(AT->getElementType()) && | 
|  | (cast<IntegerType>(AT->getElementType())->getBitWidth() == 8)); | 
|  | Global.addInitializer(Ice::VariableDeclaration::ZeroInitializer::create( | 
|  | GlobalPool, AT->getNumElements())); | 
|  | } else { | 
|  | llvm_unreachable("Unhandled constant aggregate zero type"); | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (const auto Exp = dyn_cast<ConstantExpr>(Initializer)) { | 
|  | switch (Exp->getOpcode()) { | 
|  | case Instruction::Add: | 
|  | assert(!HasOffset); | 
|  | addGlobalInitializer(Global, Exp->getOperand(0), true, | 
|  | getIntegerLiteralConstant(Exp->getOperand(1))); | 
|  | return; | 
|  | case Instruction::PtrToInt: { | 
|  | assert(TypeConverter.convertToIceType(Exp->getType()) == | 
|  | Ice::getPointerType()); | 
|  | const auto GV = dyn_cast<GlobalValue>(Exp->getOperand(0)); | 
|  | assert(GV); | 
|  | const Ice::GlobalDeclaration *Addr = | 
|  | getConverter().getGlobalDeclaration(GV); | 
|  | Global.addInitializer(Ice::VariableDeclaration::RelocInitializer::create( | 
|  | GlobalPool, Addr, {Ice::RelocOffset::create(Ctx, Offset)})); | 
|  | return; | 
|  | } | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Unhandled global initializer: " << Initializer; | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  |  | 
|  | } // end of anonymous namespace | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | void Converter::nameUnnamedGlobalVariables(Module *Mod) { | 
|  | const std::string GlobalPrefix = getFlags().getDefaultGlobalPrefix(); | 
|  | if (GlobalPrefix.empty()) | 
|  | return; | 
|  | uint32_t NameIndex = 0; | 
|  | for (auto V = Mod->global_begin(), E = Mod->global_end(); V != E; ++V) { | 
|  | if (!V->hasName()) { | 
|  | V->setName(createUnnamedName(GlobalPrefix, NameIndex)); | 
|  | ++NameIndex; | 
|  | } else { | 
|  | checkIfUnnamedNameSafe(V->getName(), "global", GlobalPrefix); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Converter::nameUnnamedFunctions(Module *Mod) { | 
|  | const std::string FunctionPrefix = getFlags().getDefaultFunctionPrefix(); | 
|  | if (FunctionPrefix.empty()) | 
|  | return; | 
|  | uint32_t NameIndex = 0; | 
|  | for (Function &F : *Mod) { | 
|  | if (!F.hasName()) { | 
|  | F.setName(createUnnamedName(FunctionPrefix, NameIndex)); | 
|  | ++NameIndex; | 
|  | } else { | 
|  | checkIfUnnamedNameSafe(F.getName(), "function", FunctionPrefix); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Converter::convertToIce() { | 
|  | TimerMarker T(TimerStack::TT_convertToIce, Ctx); | 
|  | nameUnnamedGlobalVariables(Mod); | 
|  | nameUnnamedFunctions(Mod); | 
|  | installGlobalDeclarations(Mod); | 
|  | convertGlobals(Mod); | 
|  | convertFunctions(); | 
|  | } | 
|  |  | 
|  | GlobalDeclaration *Converter::getGlobalDeclaration(const GlobalValue *V) { | 
|  | GlobalDeclarationMapType::const_iterator Pos = GlobalDeclarationMap.find(V); | 
|  | if (Pos == GlobalDeclarationMap.end()) { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Can't find global declaration for: " << V->getName(); | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  | return Pos->second; | 
|  | } | 
|  |  | 
|  | void Converter::installGlobalDeclarations(Module *Mod) { | 
|  | const TypeConverter Converter(Mod->getContext()); | 
|  | // Install function declarations. | 
|  | for (const Function &Func : *Mod) { | 
|  | FuncSigType Signature; | 
|  | FunctionType *FuncType = Func.getFunctionType(); | 
|  | Signature.setReturnType( | 
|  | Converter.convertToIceType(FuncType->getReturnType())); | 
|  | for (size_t I = 0; I < FuncType->getNumParams(); ++I) { | 
|  | Signature.appendArgType( | 
|  | Converter.convertToIceType(FuncType->getParamType(I))); | 
|  | } | 
|  | auto *IceFunc = FunctionDeclaration::create( | 
|  | Ctx, Signature, Func.getCallingConv(), Func.getLinkage(), Func.empty()); | 
|  | IceFunc->setName(Ctx, Func.getName()); | 
|  | if (!IceFunc->verifyLinkageCorrect(Ctx)) { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Function " << IceFunc->getName() | 
|  | << " has incorrect linkage: " << IceFunc->getLinkageName(); | 
|  | if (IceFunc->isExternal()) | 
|  | StrBuf << "\n  Use flag -allow-externally-defined-symbols to override"; | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  | if (!IceFunc->validateTypeSignature(Ctx)) | 
|  | report_fatal_error(IceFunc->getTypeSignatureError(Ctx)); | 
|  | GlobalDeclarationMap[&Func] = IceFunc; | 
|  | } | 
|  | // Install global variable declarations. | 
|  | for (Module::const_global_iterator I = Mod->global_begin(), | 
|  | E = Mod->global_end(); | 
|  | I != E; ++I) { | 
|  | const GlobalVariable *GV = &*I; | 
|  | constexpr bool NoSuppressMangling = false; | 
|  | auto *Var = VariableDeclaration::create( | 
|  | GlobalDeclarationsPool.get(), NoSuppressMangling, GV->getLinkage()); | 
|  | Var->setAlignment(GV->getAlignment()); | 
|  | Var->setIsConstant(GV->isConstant()); | 
|  | Var->setName(Ctx, GV->getName()); | 
|  | if (!Var->verifyLinkageCorrect()) { | 
|  | std::string Buffer; | 
|  | raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Global " << Var->getName() | 
|  | << " has incorrect linkage: " << Var->getLinkageName(); | 
|  | if (Var->isExternal()) | 
|  | StrBuf << "\n  Use flag -allow-externally-defined-symbols to override"; | 
|  | report_fatal_error(StrBuf.str()); | 
|  | } | 
|  | GlobalDeclarationMap[GV] = Var; | 
|  | } | 
|  | } | 
|  |  | 
|  | void Converter::convertGlobals(Module *Mod) { | 
|  | LLVM2ICEGlobalsConverter(*this, GlobalDeclarationsPool.get()) | 
|  | .convertGlobalsToIce(Mod); | 
|  | lowerGlobals(std::move(GlobalDeclarationsPool)); | 
|  | } | 
|  |  | 
|  | void Converter::convertFunctions() { | 
|  | for (const Function &I : *Mod) { | 
|  | if (I.empty()) | 
|  | continue; | 
|  | TimerMarker _(Ctx, I.getName()); | 
|  | LLVM2ICEFunctionConverter FunctionConverter(*this); | 
|  | FunctionConverter.convertFunction(&I); | 
|  | } | 
|  | } | 
|  |  | 
|  | } // end of namespace Ice |