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 // This file implements the LLVM to ICE converter. | 10 // This file implements the LLVM to ICE converter. |
11 // | 11 // |
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #include <iostream> | 14 #include <iostream> |
15 | 15 |
16 #include "llvm/IR/Constant.h" | 16 #include "llvm/IR/Constant.h" |
17 #include "llvm/IR/Constants.h" | 17 #include "llvm/IR/Constants.h" |
18 #include "llvm/IR/DataLayout.h" | 18 #include "llvm/IR/DataLayout.h" |
19 #include "llvm/IR/Instruction.h" | 19 #include "llvm/IR/Instruction.h" |
20 #include "llvm/IR/Instructions.h" | 20 #include "llvm/IR/Instructions.h" |
21 #include "llvm/IR/LLVMContext.h" | 21 #include "llvm/IR/LLVMContext.h" |
22 #include "llvm/IR/Module.h" | 22 #include "llvm/IR/Module.h" |
23 | 23 |
24 #include "IceCfg.h" | 24 #include "IceCfg.h" |
25 #include "IceCfgNode.h" | 25 #include "IceCfgNode.h" |
26 #include "IceClFlags.h" | 26 #include "IceClFlags.h" |
27 #include "IceConverter.h" | 27 #include "IceConverter.h" |
28 #include "IceDefs.h" | 28 #include "IceDefs.h" |
29 #include "IceGlobalContext.h" | 29 #include "IceGlobalContext.h" |
30 #include "IceGlobalInits.h" | |
30 #include "IceInst.h" | 31 #include "IceInst.h" |
31 #include "IceOperand.h" | 32 #include "IceOperand.h" |
32 #include "IceTargetLowering.h" | 33 #include "IceTargetLowering.h" |
33 #include "IceTypes.h" | 34 #include "IceTypes.h" |
34 #include "IceTypeConverter.h" | 35 #include "IceTypeConverter.h" |
35 | 36 |
36 using namespace llvm; | 37 using namespace llvm; |
Jim Stichnoth
2014/10/03 01:28:08
Is this needed? There are a lot of explicit uses
Karl
2014/10/04 16:28:33
We are very inconsistent. Removing llvm:: to make
| |
37 | 38 |
38 namespace { | 39 namespace { |
39 | 40 |
40 // Debugging helper | 41 // Debugging helper |
41 template <typename T> static std::string LLVMObjectAsString(const T *O) { | 42 template <typename T> static std::string LLVMObjectAsString(const T *O) { |
42 std::string Dump; | 43 std::string Dump; |
43 raw_string_ostream Stream(Dump); | 44 raw_string_ostream Stream(Dump); |
44 O->print(Stream); | 45 O->print(Stream); |
45 return Stream.str(); | 46 return Stream.str(); |
46 } | 47 } |
47 | 48 |
48 // Converter from LLVM to ICE. The entry point is the convertFunction method. | 49 // Base class for converting LLVM to ICE. |
49 // | |
50 // Note: this currently assumes that the given IR was verified to be valid PNaCl | |
51 // bitcode: | |
52 // https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi | |
53 // If not, all kinds of assertions may fire. | |
54 // | |
55 class LLVM2ICEConverter { | 50 class LLVM2ICEConverter { |
56 public: | 51 public: |
57 LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) | 52 LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) |
58 : Ctx(Ctx), Func(NULL), TypeConverter(LLVMContext) {} | 53 : Ctx(Ctx), TypeConverter(LLVMContext) {} |
54 | |
55 protected: | |
56 // Data | |
57 Ice::GlobalContext *Ctx; | |
58 Ice::TypeConverter TypeConverter; | |
jvoung (off chromium)
2014/10/03 16:15:29
Could disallow copy / assign.
Karl
2014/10/04 16:28:33
Done.
| |
59 }; | |
60 | |
61 // Converter from LLVM functions to ICE. The entry point is the | |
62 // convertFunction method. | |
63 // | |
64 // Note: this currently assumes that the given IR was verified to be | |
65 // valid PNaCl bitcode: | |
66 // https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi | |
67 // If not, all kinds of assertions may fire. | |
68 class LLVM2ICEFunctionConverter : LLVM2ICEConverter { | |
69 public: | |
70 LLVM2ICEFunctionConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) | |
71 : LLVM2ICEConverter(Ctx, LLVMContext), Func(NULL) {} | |
59 | 72 |
60 // Caller is expected to delete the returned Ice::Cfg object. | 73 // Caller is expected to delete the returned Ice::Cfg object. |
61 Ice::Cfg *convertFunction(const Function *F) { | 74 Ice::Cfg *convertFunction(const Function *F) { |
62 static Ice::TimerIdT IDllvmConvert = | 75 static Ice::TimerIdT IDllvmConvert = |
63 Ice::GlobalContext::getTimerID("llvmConvert"); | 76 Ice::GlobalContext::getTimerID("llvmConvert"); |
64 Ice::TimerMarker T(IDllvmConvert, Ctx); | 77 Ice::TimerMarker T(IDllvmConvert, Ctx); |
65 VarMap.clear(); | 78 VarMap.clear(); |
66 NodeMap.clear(); | 79 NodeMap.clear(); |
67 Func = new Ice::Cfg(Ctx); | 80 Func = new Ice::Cfg(Ctx); |
68 Func->setFunctionName(F->getName()); | 81 Func->setFunctionName(F->getName()); |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 << I->getArgType(ArgIndex) | 617 << I->getArgType(ArgIndex) |
605 << ". Found: " << Call->getArg(ArgIndex)->getType(); | 618 << ". Found: " << Call->getArg(ArgIndex)->getType(); |
606 report_fatal_error(StrBuf.str()); | 619 report_fatal_error(StrBuf.str()); |
607 break; | 620 break; |
608 } | 621 } |
609 } | 622 } |
610 } | 623 } |
611 | 624 |
612 private: | 625 private: |
613 // Data | 626 // Data |
614 Ice::GlobalContext *Ctx; | |
615 Ice::Cfg *Func; | 627 Ice::Cfg *Func; |
616 std::map<const Value *, Ice::Variable *> VarMap; | 628 std::map<const Value *, Ice::Variable *> VarMap; |
617 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; | 629 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; |
618 Ice::TypeConverter TypeConverter; | |
619 }; | 630 }; |
620 | 631 |
632 // Converter from LLVM global variables to ICE. The entry point is the | |
633 // convertGlobalsToIce method. | |
634 // | |
635 // Note: this currently assumes that the given IR was verified to be | |
636 // valid PNaCl bitcode: | |
637 // https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi | |
638 // If not, all kinds of assertions may fire. | |
639 class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter { | |
640 public: | |
641 LLVM2ICEGlobalsConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) | |
642 : LLVM2ICEConverter(Ctx, LLVMContext) {} | |
643 | |
644 ~LLVM2ICEGlobalsConverter() { | |
645 llvm::DeleteContainerSeconds(GlobalVarAddressMap); | |
646 } | |
647 | |
648 /// Converts global variables, and their initializers into ICE global | |
649 /// addresses, for module Mod. Puts corresponding converted global | |
650 /// addresses into GlobalAddresses. | |
651 void convertGlobalsToIce(llvm::Module *Mod, | |
652 std::vector<Ice::GlobalAddress *> &GlobalAddresses); | |
Jim Stichnoth
2014/10/03 01:28:08
Can you make a typedef for std::vector<Ice::Global
Karl
2014/10/04 16:28:33
Added typedef Translator::GlobalAddressList.
Adde
| |
653 | |
654 private: | |
655 // Map from global variables to thier corresponding global address. | |
Jim Stichnoth
2014/10/03 01:28:08
their
Karl
2014/10/04 16:28:33
Done.
| |
656 std::map<const llvm::GlobalVariable *, Ice::GlobalAddress *> | |
657 GlobalVarAddressMap; | |
658 | |
659 // Adds the Initializer to the list of initializers for Global address. | |
660 void AddGlobalInitializer(Ice::GlobalAddress &Global, | |
jvoung (off chromium)
2014/10/03 16:15:29
method name consistency: "addGlobalInitializer" in
Karl
2014/10/04 16:28:33
Done.
| |
661 const llvm::Constant *Initializer) { | |
662 AddGlobalInitializer(Global, Initializer, false, 0); | |
jvoung (off chromium)
2014/10/03 16:15:29
nit: For some of the other code in Subzero, there
Karl
2014/10/04 16:28:33
Done.
| |
663 } | |
664 | |
665 // Adds Initializer to the list of initializers for Global | |
666 // address. HasOffset is true only if Initializer is a relocation | |
667 // initializer and Offset should be added to the relocation. | |
668 void AddGlobalInitializer(Ice::GlobalAddress &Global, | |
669 const llvm::Constant *Initializer, bool HasOffset, | |
670 Ice::GlobalAddress::RelocOffsetType Offset); | |
671 | |
672 // Returns the global address associated with global variable GV. | |
673 Ice::GlobalAddress *getGlobalVarAddress(const llvm::GlobalVariable *GV) { | |
674 Ice::GlobalAddress *Addr = GlobalVarAddressMap[GV]; | |
Jim Stichnoth
2014/10/03 01:28:08
Maybe better form to do something like this?
if
Karl
2014/10/04 16:28:33
Done.
| |
675 if (Addr) | |
676 return Addr; | |
677 Addr = new Ice::GlobalAddress(); | |
678 GlobalVarAddressMap[GV] = Addr; | |
679 return Addr; | |
680 } | |
681 | |
682 // Converts the given constant C to the corresponding integer | |
683 // literal it contains. | |
684 Ice::GlobalAddress::RelocOffsetType | |
685 getIntegerLiteralConstant(const llvm::Value *C) { | |
686 const llvm::ConstantInt *CI = llvm::dyn_cast<llvm::ConstantInt>(C); | |
Jim Stichnoth
2014/10/03 01:28:08
if (auto CI = llvm::dyn_cast<const llvm::ConstantI
Karl
2014/10/04 16:28:33
Fixed all occurrences in file.
| |
687 if (CI && CI->getType()->isIntegerTy(32)) | |
688 return CI->getSExtValue(); | |
689 | |
690 std::string Buffer; | |
691 raw_string_ostream StrBuf(Buffer); | |
692 StrBuf << "Constant not i32 literal: " << *C; | |
693 report_fatal_error(StrBuf.str()); | |
694 return 0; | |
695 } | |
696 }; | |
697 | |
698 void LLVM2ICEGlobalsConverter::convertGlobalsToIce( | |
699 llvm::Module *Mod, std::vector<Ice::GlobalAddress *> &GlobalAddresses) { | |
700 for (llvm::Module::const_global_iterator I = Mod->global_begin(), | |
701 E = Mod->global_end(); | |
702 I != E; ++I) { | |
703 if (!I->hasInitializer()) | |
704 continue; | |
jvoung (off chromium)
2014/10/03 16:15:29
For the PNaCl ABI, should we be stricter? I though
Karl
2014/10/04 16:28:33
I agree. I was being lazy because there is a test
| |
705 | |
706 const llvm::GlobalVariable *GV = llvm::dyn_cast<GlobalVariable>(I); | |
707 assert(GV); | |
Jim Stichnoth
2014/10/03 01:28:08
If you're going to assert(GV), might as well use l
Karl
2014/10/04 16:28:33
Not sure what you are asking. Are you asking to pu
| |
708 Ice::IceString Name = GV->getName(); | |
709 if (!GV->hasInternalLinkage()) { | |
710 std::string Buffer; | |
711 raw_string_ostream StrBuf(Buffer); | |
712 StrBuf << "Can't define external global address: " << Name; | |
713 report_fatal_error(StrBuf.str()); | |
714 } | |
715 | |
716 Ice::GlobalAddress *Addr = getGlobalVarAddress(GV); | |
717 GlobalAddresses.push_back(Addr); | |
718 Addr->setAlignment(GV->getAlignment()); | |
719 Addr->setIsConstant(GV->isConstant()); | |
720 Addr->setName(Name); | |
721 | |
722 const llvm::Constant *Initializer = GV->getInitializer(); | |
723 if (const llvm::ConstantStruct *CompoundInit = | |
724 dyn_cast<llvm::ConstantStruct>(Initializer)) { | |
725 for (llvm::ConstantStruct::const_op_iterator i = CompoundInit->op_begin(), | |
Jim Stichnoth
2014/10/03 01:28:08
Use I and E instead of i and e for consistency?
Karl
2014/10/04 16:28:33
Done.
| |
726 e = CompoundInit->op_end(); | |
727 i != e; ++i) { | |
728 if (const llvm::Constant *Init = dyn_cast<llvm::Constant>(i)) { | |
729 AddGlobalInitializer(*Addr, Init); | |
730 } | |
jvoung (off chromium)
2014/10/03 16:15:29
What are the possible "else" here, and should it b
Karl
2014/10/04 16:28:33
The format in PNaCl ABI is that the struct is part
| |
731 } | |
732 } else { | |
733 AddGlobalInitializer(*Addr, Initializer); | |
734 } | |
735 } | |
736 } | |
737 | |
738 void LLVM2ICEGlobalsConverter::AddGlobalInitializer( | |
739 Ice::GlobalAddress &Global, const llvm::Constant *Initializer, | |
740 bool HasOffset, Ice::GlobalAddress::RelocOffsetType Offset) { | |
741 assert(HasOffset || Offset == 0); | |
742 | |
743 if (const llvm::ConstantDataArray *CDA = | |
744 llvm::dyn_cast<llvm::ConstantDataArray>(Initializer)) { | |
745 assert(!HasOffset && llvm::isa<llvm::IntegerType>(CDA->getElementType()) && | |
746 (llvm::cast<llvm::IntegerType>(CDA->getElementType()) | |
747 ->getBitWidth() == 8)); | |
748 Global.AddInitializer(new Ice::GlobalAddress::DataInitializer( | |
749 CDA->getRawDataValues().data(), CDA->getNumElements())); | |
750 return; | |
751 } | |
752 | |
753 if (llvm::isa<llvm::ConstantAggregateZero>(Initializer)) { | |
754 if (const llvm::ArrayType *AT = | |
755 llvm::dyn_cast<llvm::ArrayType>(Initializer->getType())) { | |
756 assert(!HasOffset && llvm::isa<llvm::IntegerType>(AT->getElementType()) && | |
757 (llvm::cast<llvm::IntegerType>(AT->getElementType()) | |
758 ->getBitWidth() == 8)); | |
759 Global.AddInitializer( | |
760 new Ice::GlobalAddress::ZeroInitializer(AT->getNumElements())); | |
761 } else { | |
762 llvm_unreachable("Unhandled constant aggregate zero type"); | |
763 } | |
764 return; | |
765 } | |
766 | |
767 if (const ConstantExpr *Exp = | |
768 llvm::dyn_cast<llvm::ConstantExpr>(Initializer)) { | |
769 switch (Exp->getOpcode()) { | |
770 case Instruction::Add: | |
771 assert(!HasOffset); | |
772 AddGlobalInitializer(Global, Exp->getOperand(0), true, | |
773 getIntegerLiteralConstant(Exp->getOperand(1))); | |
774 return; | |
775 case Instruction::PtrToInt: { | |
776 assert(TypeConverter.convertToIceType(Exp->getType()) == | |
777 TypeConverter.getIcePointerType()); | |
778 llvm::GlobalValue *GV = | |
779 llvm::dyn_cast<llvm::GlobalValue>(Exp->getOperand(0)); | |
780 assert(GV); | |
781 if (llvm::Function *Fcn = llvm::dyn_cast<Function>(GV)) { | |
782 Ice::GlobalAddress::RelocationAddress Addr(Fcn); | |
783 Global.AddInitializer( | |
784 new Ice::GlobalAddress::RelocInitializer(Addr, Offset)); | |
785 return; | |
786 } else if (llvm::GlobalVariable *Var = | |
787 llvm::dyn_cast<llvm::GlobalVariable>(GV)) { | |
788 Ice::GlobalAddress::RelocationAddress Addr(getGlobalVarAddress(Var)); | |
789 Global.AddInitializer( | |
790 new Ice::GlobalAddress::RelocInitializer(Addr, Offset)); | |
791 return; | |
792 } | |
793 break; | |
794 } | |
795 default: | |
796 break; | |
797 } | |
798 } | |
799 | |
800 std::string Buffer; | |
801 raw_string_ostream StrBuf(Buffer); | |
802 StrBuf << "Unhandled global initializer: " << Initializer; | |
803 report_fatal_error(StrBuf.str()); | |
804 } | |
805 | |
621 } // end of anonymous namespace | 806 } // end of anonymous namespace |
622 | 807 |
623 namespace Ice { | 808 namespace Ice { |
624 | 809 |
625 void Converter::convertToIce() { | 810 void Converter::convertToIce() { |
626 static TimerIdT IDconvertToIce = GlobalContext::getTimerID("convertToIce"); | 811 static TimerIdT IDconvertToIce = GlobalContext::getTimerID("convertToIce"); |
627 TimerMarker T(IDconvertToIce, Ctx); | 812 TimerMarker T(IDconvertToIce, Ctx); |
628 nameUnnamedGlobalAddresses(Mod); | 813 nameUnnamedGlobalAddresses(Mod); |
814 nameUnnamedFunctions(Mod); | |
629 if (!Ctx->getFlags().DisableGlobals) | 815 if (!Ctx->getFlags().DisableGlobals) |
630 convertGlobals(Mod); | 816 convertGlobals(Mod); |
631 convertFunctions(); | 817 convertFunctions(); |
632 } | 818 } |
633 | 819 |
820 void Converter::convertGlobals(llvm::Module *Mod) { | |
821 LLVM2ICEGlobalsConverter GlobalsConverter(Ctx, Mod->getContext()); | |
822 std::vector<Ice::GlobalAddress *> GlobalAddresses; | |
823 GlobalsConverter.convertGlobalsToIce(Mod, GlobalAddresses); | |
824 lowerIceGlobals(GlobalAddresses); | |
825 } | |
826 | |
634 void Converter::convertFunctions() { | 827 void Converter::convertFunctions() { |
635 for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { | 828 for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { |
636 if (I->empty()) | 829 if (I->empty()) |
637 continue; | 830 continue; |
638 LLVM2ICEConverter FunctionConverter(Ctx, Mod->getContext()); | 831 LLVM2ICEFunctionConverter FunctionConverter(Ctx, Mod->getContext()); |
639 | 832 |
640 Timer TConvert; | 833 Timer TConvert; |
641 Cfg *Fcn = FunctionConverter.convertFunction(I); | 834 Cfg *Fcn = FunctionConverter.convertFunction(I); |
642 translateFcn(Fcn); | 835 translateFcn(Fcn); |
643 } | 836 } |
644 | 837 |
645 emitConstants(); | 838 emitConstants(); |
646 } | 839 } |
647 | 840 |
648 } // end of namespace Ice | 841 } // end of namespace Ice |
OLD | NEW |