| OLD | NEW |
| 1 //===- subzero/src/IceConverter.cpp - Converts LLVM to Ice ---------------===// | 1 //===- subzero/src/IceConverter.cpp - Converts LLVM to Ice ---------------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 // Debugging helper | 45 // Debugging helper |
| 46 template <typename T> static std::string LLVMObjectAsString(const T *O) { | 46 template <typename T> static std::string LLVMObjectAsString(const T *O) { |
| 47 std::string Dump; | 47 std::string Dump; |
| 48 raw_string_ostream Stream(Dump); | 48 raw_string_ostream Stream(Dump); |
| 49 O->print(Stream); | 49 O->print(Stream); |
| 50 return Stream.str(); | 50 return Stream.str(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 // Base class for converting LLVM to ICE. | 53 // Base class for converting LLVM to ICE. |
| 54 // TODO(stichnot): Redesign Converter, LLVM2ICEConverter, | 54 // TODO(stichnot): Redesign Converter, LLVM2ICEConverter, |
| 55 // LLVM2ICEFunctionConverter, and LLVM2ICEGlobalsConverter with | 55 // LLVM2ICEFunctionConverter, and LLVM2ICEGlobalsConverter with respect to |
| 56 // respect to Translator. In particular, the unique_ptr ownership | 56 // Translator. In particular, the unique_ptr ownership rules in |
| 57 // rules in LLVM2ICEFunctionConverter. | 57 // LLVM2ICEFunctionConverter. |
| 58 class LLVM2ICEConverter { | 58 class LLVM2ICEConverter { |
| 59 LLVM2ICEConverter() = delete; | 59 LLVM2ICEConverter() = delete; |
| 60 LLVM2ICEConverter(const LLVM2ICEConverter &) = delete; | 60 LLVM2ICEConverter(const LLVM2ICEConverter &) = delete; |
| 61 LLVM2ICEConverter &operator=(const LLVM2ICEConverter &) = delete; | 61 LLVM2ICEConverter &operator=(const LLVM2ICEConverter &) = delete; |
| 62 | 62 |
| 63 public: | 63 public: |
| 64 explicit LLVM2ICEConverter(Ice::Converter &Converter) | 64 explicit LLVM2ICEConverter(Ice::Converter &Converter) |
| 65 : Converter(Converter), Ctx(Converter.getContext()), | 65 : Converter(Converter), Ctx(Converter.getContext()), |
| 66 TypeConverter(Converter.getModule()->getContext()) {} | 66 TypeConverter(Converter.getModule()->getContext()) {} |
| 67 | 67 |
| 68 Ice::Converter &getConverter() const { return Converter; } | 68 Ice::Converter &getConverter() const { return Converter; } |
| 69 | 69 |
| 70 protected: | 70 protected: |
| 71 Ice::Converter &Converter; | 71 Ice::Converter &Converter; |
| 72 Ice::GlobalContext *Ctx; | 72 Ice::GlobalContext *Ctx; |
| 73 const Ice::TypeConverter TypeConverter; | 73 const Ice::TypeConverter TypeConverter; |
| 74 }; | 74 }; |
| 75 | 75 |
| 76 // Converter from LLVM functions to ICE. The entry point is the | 76 // Converter from LLVM functions to ICE. The entry point is the convertFunction |
| 77 // convertFunction method. | 77 // method. |
| 78 // | 78 // |
| 79 // Note: this currently assumes that the given IR was verified to be | 79 // Note: this currently assumes that the given IR was verified to be valid |
| 80 // valid PNaCl bitcode. Otherwise, the behavior is undefined. | 80 // PNaCl bitcode. Otherwise, the behavior is undefined. |
| 81 class LLVM2ICEFunctionConverter : LLVM2ICEConverter { | 81 class LLVM2ICEFunctionConverter : LLVM2ICEConverter { |
| 82 LLVM2ICEFunctionConverter() = delete; | 82 LLVM2ICEFunctionConverter() = delete; |
| 83 LLVM2ICEFunctionConverter(const LLVM2ICEFunctionConverter &) = delete; | 83 LLVM2ICEFunctionConverter(const LLVM2ICEFunctionConverter &) = delete; |
| 84 LLVM2ICEFunctionConverter & | 84 LLVM2ICEFunctionConverter & |
| 85 operator=(const LLVM2ICEFunctionConverter &) = delete; | 85 operator=(const LLVM2ICEFunctionConverter &) = delete; |
| 86 | 86 |
| 87 public: | 87 public: |
| 88 explicit LLVM2ICEFunctionConverter(Ice::Converter &Converter) | 88 explicit LLVM2ICEFunctionConverter(Ice::Converter &Converter) |
| 89 : LLVM2ICEConverter(Converter), Func(nullptr) {} | 89 : LLVM2ICEConverter(Converter), Func(nullptr) {} |
| 90 | 90 |
| 91 void convertFunction(const Function *F) { | 91 void convertFunction(const Function *F) { |
| 92 if (Ctx->isIRGenerationDisabled()) | 92 if (Ctx->isIRGenerationDisabled()) |
| 93 return; | 93 return; |
| 94 Func = Ice::Cfg::create(Ctx, Converter.getNextSequenceNumber()); | 94 Func = Ice::Cfg::create(Ctx, Converter.getNextSequenceNumber()); |
| 95 Ice::Cfg::setCurrentCfg(Func.get()); | 95 Ice::Cfg::setCurrentCfg(Func.get()); |
| 96 | 96 |
| 97 VarMap.clear(); | 97 VarMap.clear(); |
| 98 NodeMap.clear(); | 98 NodeMap.clear(); |
| 99 Func->setFunctionName(F->getName()); | 99 Func->setFunctionName(F->getName()); |
| 100 Func->setReturnType(convertToIceType(F->getReturnType())); | 100 Func->setReturnType(convertToIceType(F->getReturnType())); |
| 101 Func->setInternal(F->hasInternalLinkage()); | 101 Func->setInternal(F->hasInternalLinkage()); |
| 102 Ice::TimerMarker T(Ice::TimerStack::TT_llvmConvert, Func.get()); | 102 Ice::TimerMarker T(Ice::TimerStack::TT_llvmConvert, Func.get()); |
| 103 | 103 |
| 104 // The initial definition/use of each arg is the entry node. | 104 // The initial definition/use of each arg is the entry node. |
| 105 for (auto ArgI = F->arg_begin(), ArgE = F->arg_end(); ArgI != ArgE; | 105 for (auto ArgI = F->arg_begin(), ArgE = F->arg_end(); ArgI != ArgE; |
| 106 ++ArgI) { | 106 ++ArgI) { |
| 107 Func->addArg(mapValueToIceVar(ArgI)); | 107 Func->addArg(mapValueToIceVar(ArgI)); |
| 108 } | 108 } |
| 109 | 109 |
| 110 // Make an initial pass through the block list just to resolve the | 110 // Make an initial pass through the block list just to resolve the blocks |
| 111 // blocks in the original linearized order. Otherwise the ICE | 111 // in the original linearized order. Otherwise the ICE linearized order |
| 112 // linearized order will be affected by branch targets in | 112 // will be affected by branch targets in terminator instructions. |
| 113 // terminator instructions. | |
| 114 for (const BasicBlock &BBI : *F) | 113 for (const BasicBlock &BBI : *F) |
| 115 mapBasicBlockToNode(&BBI); | 114 mapBasicBlockToNode(&BBI); |
| 116 for (const BasicBlock &BBI : *F) | 115 for (const BasicBlock &BBI : *F) |
| 117 convertBasicBlock(&BBI); | 116 convertBasicBlock(&BBI); |
| 118 Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock())); | 117 Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock())); |
| 119 Func->computeInOutEdges(); | 118 Func->computeInOutEdges(); |
| 120 | 119 |
| 121 Ice::Cfg::setCurrentCfg(nullptr); | 120 Ice::Cfg::setCurrentCfg(nullptr); |
| 122 Converter.translateFcn(std::move(Func)); | 121 Converter.translateFcn(std::move(Func)); |
| 123 } | 122 } |
| 124 | 123 |
| 125 // convertConstant() does not use Func or require it to be a valid | 124 // convertConstant() does not use Func or require it to be a valid Ice::Cfg |
| 126 // Ice::Cfg pointer. As such, it's suitable for e.g. constructing | 125 // pointer. As such, it's suitable for e.g. constructing global initializers. |
| 127 // global initializers. | |
| 128 Ice::Constant *convertConstant(const Constant *Const) { | 126 Ice::Constant *convertConstant(const Constant *Const) { |
| 129 if (const auto GV = dyn_cast<GlobalValue>(Const)) { | 127 if (const auto GV = dyn_cast<GlobalValue>(Const)) { |
| 130 Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV); | 128 Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV); |
| 131 bool IsUndefined = false; | 129 bool IsUndefined = false; |
| 132 if (const auto *Func = llvm::dyn_cast<Ice::FunctionDeclaration>(Decl)) | 130 if (const auto *Func = llvm::dyn_cast<Ice::FunctionDeclaration>(Decl)) |
| 133 IsUndefined = Func->isProto(); | 131 IsUndefined = Func->isProto(); |
| 134 else if (const auto *Var = llvm::dyn_cast<Ice::VariableDeclaration>(Decl)) | 132 else if (const auto *Var = llvm::dyn_cast<Ice::VariableDeclaration>(Decl)) |
| 135 IsUndefined = !Var->hasInitializer(); | 133 IsUndefined = !Var->hasInitializer(); |
| 136 else | 134 else |
| 137 report_fatal_error("Unhandled GlobalDeclaration type"); | 135 report_fatal_error("Unhandled GlobalDeclaration type"); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 188 } |
| 191 | 189 |
| 192 Ice::Type convertToIceType(Type *LLVMTy) const { | 190 Ice::Type convertToIceType(Type *LLVMTy) const { |
| 193 Ice::Type IceTy = TypeConverter.convertToIceType(LLVMTy); | 191 Ice::Type IceTy = TypeConverter.convertToIceType(LLVMTy); |
| 194 if (IceTy == Ice::IceType_NUM) | 192 if (IceTy == Ice::IceType_NUM) |
| 195 report_fatal_error(std::string("Invalid PNaCl type ") + | 193 report_fatal_error(std::string("Invalid PNaCl type ") + |
| 196 LLVMObjectAsString(LLVMTy)); | 194 LLVMObjectAsString(LLVMTy)); |
| 197 return IceTy; | 195 return IceTy; |
| 198 } | 196 } |
| 199 | 197 |
| 200 // Given an LLVM instruction and an operand number, produce the | 198 // Given an LLVM instruction and an operand number, produce the Ice::Operand |
| 201 // Ice::Operand this refers to. If there's no such operand, return | 199 // this refers to. If there's no such operand, return nullptr. |
| 202 // nullptr. | |
| 203 Ice::Operand *convertOperand(const Instruction *Inst, unsigned OpNum) { | 200 Ice::Operand *convertOperand(const Instruction *Inst, unsigned OpNum) { |
| 204 if (OpNum >= Inst->getNumOperands()) { | 201 if (OpNum >= Inst->getNumOperands()) { |
| 205 return nullptr; | 202 return nullptr; |
| 206 } | 203 } |
| 207 const Value *Op = Inst->getOperand(OpNum); | 204 const Value *Op = Inst->getOperand(OpNum); |
| 208 return convertValue(Op); | 205 return convertValue(Op); |
| 209 } | 206 } |
| 210 | 207 |
| 211 Ice::Operand *convertValue(const Value *Op) { | 208 Ice::Operand *convertValue(const Value *Op) { |
| 212 if (const auto Const = dyn_cast<Constant>(Op)) { | 209 if (const auto Const = dyn_cast<Constant>(Op)) { |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 Ice::CfgNode *CaseSuccessor = mapBasicBlockToNode(I.getCaseSuccessor()); | 541 Ice::CfgNode *CaseSuccessor = mapBasicBlockToNode(I.getCaseSuccessor()); |
| 545 Switch->addBranch(CurrentCase, CaseValue, CaseSuccessor); | 542 Switch->addBranch(CurrentCase, CaseValue, CaseSuccessor); |
| 546 } | 543 } |
| 547 return Switch; | 544 return Switch; |
| 548 } | 545 } |
| 549 | 546 |
| 550 Ice::Inst *convertCallInstruction(const CallInst *Inst) { | 547 Ice::Inst *convertCallInstruction(const CallInst *Inst) { |
| 551 Ice::Variable *Dest = mapValueToIceVar(Inst); | 548 Ice::Variable *Dest = mapValueToIceVar(Inst); |
| 552 Ice::Operand *CallTarget = convertValue(Inst->getCalledValue()); | 549 Ice::Operand *CallTarget = convertValue(Inst->getCalledValue()); |
| 553 unsigned NumArgs = Inst->getNumArgOperands(); | 550 unsigned NumArgs = Inst->getNumArgOperands(); |
| 554 // Note: Subzero doesn't (yet) do anything special with the Tail | 551 // Note: Subzero doesn't (yet) do anything special with the Tail flag in |
| 555 // flag in the bitcode, i.e. CallInst::isTailCall(). | 552 // the bitcode, i.e. CallInst::isTailCall(). |
| 556 Ice::InstCall *NewInst = nullptr; | 553 Ice::InstCall *NewInst = nullptr; |
| 557 const Ice::Intrinsics::FullIntrinsicInfo *Info = nullptr; | 554 const Ice::Intrinsics::FullIntrinsicInfo *Info = nullptr; |
| 558 | 555 |
| 559 if (const auto Target = dyn_cast<Ice::ConstantRelocatable>(CallTarget)) { | 556 if (const auto Target = dyn_cast<Ice::ConstantRelocatable>(CallTarget)) { |
| 560 // Check if this direct call is to an Intrinsic (starts with "llvm.") | 557 // Check if this direct call is to an Intrinsic (starts with "llvm.") |
| 561 bool BadIntrinsic; | 558 bool BadIntrinsic; |
| 562 Info = Ctx->getIntrinsicsInfo().find(Target->getName(), BadIntrinsic); | 559 Info = Ctx->getIntrinsicsInfo().find(Target->getName(), BadIntrinsic); |
| 563 if (BadIntrinsic) { | 560 if (BadIntrinsic) { |
| 564 report_fatal_error(std::string("Invalid PNaCl intrinsic call: ") + | 561 report_fatal_error(std::string("Invalid PNaCl intrinsic call: ") + |
| 565 LLVMObjectAsString(Inst)); | 562 LLVMObjectAsString(Inst)); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 private: | 639 private: |
| 643 // Data | 640 // Data |
| 644 std::unique_ptr<Ice::Cfg> Func; | 641 std::unique_ptr<Ice::Cfg> Func; |
| 645 std::map<const Value *, Ice::Variable *> VarMap; | 642 std::map<const Value *, Ice::Variable *> VarMap; |
| 646 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; | 643 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; |
| 647 }; | 644 }; |
| 648 | 645 |
| 649 // Converter from LLVM global variables to ICE. The entry point is the | 646 // Converter from LLVM global variables to ICE. The entry point is the |
| 650 // convertGlobalsToIce method. | 647 // convertGlobalsToIce method. |
| 651 // | 648 // |
| 652 // Note: this currently assumes that the given IR was verified to be | 649 // Note: this currently assumes that the given IR was verified to be valid |
| 653 // valid PNaCl bitcode. Othewise, the behavior is undefined. | 650 // PNaCl bitcode. Otherwise, the behavior is undefined. |
| 654 class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter { | 651 class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter { |
| 655 LLVM2ICEGlobalsConverter() = delete; | 652 LLVM2ICEGlobalsConverter() = delete; |
| 656 LLVM2ICEGlobalsConverter(const LLVM2ICEGlobalsConverter &) = delete; | 653 LLVM2ICEGlobalsConverter(const LLVM2ICEGlobalsConverter &) = delete; |
| 657 LLVM2ICEGlobalsConverter & | 654 LLVM2ICEGlobalsConverter & |
| 658 operator=(const LLVM2ICEGlobalsConverter &) = delete; | 655 operator=(const LLVM2ICEGlobalsConverter &) = delete; |
| 659 | 656 |
| 660 public: | 657 public: |
| 661 explicit LLVM2ICEGlobalsConverter(Ice::Converter &Converter) | 658 explicit LLVM2ICEGlobalsConverter(Ice::Converter &Converter) |
| 662 : LLVM2ICEConverter(Converter) {} | 659 : LLVM2ICEConverter(Converter) {} |
| 663 | 660 |
| 664 /// Converts global variables, and their initializers into ICE | 661 /// Converts global variables, and their initializers into ICE global variable |
| 665 /// global variable declarations, for module Mod. Returns the set of | 662 /// declarations, for module Mod. Returns the set of converted declarations. |
| 666 /// converted declarations. | |
| 667 std::unique_ptr<Ice::VariableDeclarationList> | 663 std::unique_ptr<Ice::VariableDeclarationList> |
| 668 convertGlobalsToIce(Module *Mod); | 664 convertGlobalsToIce(Module *Mod); |
| 669 | 665 |
| 670 private: | 666 private: |
| 671 // Adds the Initializer to the list of initializers for the Global | 667 // Adds the Initializer to the list of initializers for the Global variable |
| 672 // variable declaraation. | 668 // declaration. |
| 673 void addGlobalInitializer(Ice::VariableDeclaration &Global, | 669 void addGlobalInitializer(Ice::VariableDeclaration &Global, |
| 674 const Constant *Initializer) { | 670 const Constant *Initializer) { |
| 675 const bool HasOffset = false; | 671 const bool HasOffset = false; |
| 676 const Ice::RelocOffsetT Offset = 0; | 672 const Ice::RelocOffsetT Offset = 0; |
| 677 addGlobalInitializer(Global, Initializer, HasOffset, Offset); | 673 addGlobalInitializer(Global, Initializer, HasOffset, Offset); |
| 678 } | 674 } |
| 679 | 675 |
| 680 // Adds Initializer to the list of initializers for Global variable | 676 // Adds Initializer to the list of initializers for Global variable |
| 681 // declaration. HasOffset is true only if Initializer is a | 677 // declaration. HasOffset is true only if Initializer is a relocation |
| 682 // relocation initializer and Offset should be added to the | 678 // initializer and Offset should be added to the relocation. |
| 683 // relocation. | |
| 684 void addGlobalInitializer(Ice::VariableDeclaration &Global, | 679 void addGlobalInitializer(Ice::VariableDeclaration &Global, |
| 685 const Constant *Initializer, bool HasOffset, | 680 const Constant *Initializer, bool HasOffset, |
| 686 Ice::RelocOffsetT Offset); | 681 Ice::RelocOffsetT Offset); |
| 687 | 682 |
| 688 // Converts the given constant C to the corresponding integer | 683 // Converts the given constant C to the corresponding integer literal it |
| 689 // literal it contains. | 684 // contains. |
| 690 Ice::RelocOffsetT getIntegerLiteralConstant(const Value *C) { | 685 Ice::RelocOffsetT getIntegerLiteralConstant(const Value *C) { |
| 691 const auto CI = dyn_cast<ConstantInt>(C); | 686 const auto CI = dyn_cast<ConstantInt>(C); |
| 692 if (CI && CI->getType()->isIntegerTy(32)) | 687 if (CI && CI->getType()->isIntegerTy(32)) |
| 693 return CI->getSExtValue(); | 688 return CI->getSExtValue(); |
| 694 | 689 |
| 695 std::string Buffer; | 690 std::string Buffer; |
| 696 raw_string_ostream StrBuf(Buffer); | 691 raw_string_ostream StrBuf(Buffer); |
| 697 StrBuf << "Constant not i32 literal: " << *C; | 692 StrBuf << "Constant not i32 literal: " << *C; |
| 698 report_fatal_error(StrBuf.str()); | 693 report_fatal_error(StrBuf.str()); |
| 699 return 0; | 694 return 0; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 Ctx->pushTimer(TimerID, StackID); | 900 Ctx->pushTimer(TimerID, StackID); |
| 906 } | 901 } |
| 907 LLVM2ICEFunctionConverter FunctionConverter(*this); | 902 LLVM2ICEFunctionConverter FunctionConverter(*this); |
| 908 FunctionConverter.convertFunction(&I); | 903 FunctionConverter.convertFunction(&I); |
| 909 if (TimeThisFunction) | 904 if (TimeThisFunction) |
| 910 Ctx->popTimer(TimerID, StackID); | 905 Ctx->popTimer(TimerID, StackID); |
| 911 } | 906 } |
| 912 } | 907 } |
| 913 | 908 |
| 914 } // end of namespace Ice | 909 } // end of namespace Ice |
| OLD | NEW |