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 |