| OLD | NEW |
| 1 //===- subzero/src/llvm2ice.cpp - Driver for testing ----------------------===// | 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 defines a driver that uses LLVM capabilities to parse a | 10 // This file implements the LLVM to ICE converter. |
| 11 // bitcode file and build the LLVM IR, and then convert the LLVM basic | |
| 12 // blocks, instructions, and operands into their Subzero equivalents. | |
| 13 // | 11 // |
| 14 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
| 15 | 13 |
| 14 #include "IceConverter.h" |
| 15 |
| 16 #include "IceCfg.h" | 16 #include "IceCfg.h" |
| 17 #include "IceCfgNode.h" | 17 #include "IceCfgNode.h" |
| 18 #include "IceDefs.h" | 18 #include "IceDefs.h" |
| 19 #include "IceGlobalContext.h" | 19 #include "IceGlobalContext.h" |
| 20 #include "IceInst.h" | 20 #include "IceInst.h" |
| 21 #include "IceOperand.h" | 21 #include "IceOperand.h" |
| 22 #include "IceTargetLowering.h" | 22 #include "IceTargetLowering.h" |
| 23 #include "IceTypes.h" | 23 #include "IceTypes.h" |
| 24 | 24 |
| 25 #include "llvm/IR/Constant.h" | 25 #include "llvm/IR/Constant.h" |
| 26 #include "llvm/IR/Constants.h" | 26 #include "llvm/IR/Constants.h" |
| 27 #include "llvm/IR/DataLayout.h" | 27 #include "llvm/IR/DataLayout.h" |
| 28 #include "llvm/IR/Instruction.h" | 28 #include "llvm/IR/Instruction.h" |
| 29 #include "llvm/IR/Instructions.h" | 29 #include "llvm/IR/Instructions.h" |
| 30 #include "llvm/IR/LLVMContext.h" | 30 #include "llvm/IR/LLVMContext.h" |
| 31 #include "llvm/IR/Module.h" | 31 #include "llvm/IR/Module.h" |
| 32 #include "llvm/IRReader/IRReader.h" | |
| 33 #include "llvm/Support/CommandLine.h" | |
| 34 #include "llvm/Support/ErrorHandling.h" | |
| 35 #include "llvm/Support/raw_os_ostream.h" | |
| 36 #include "llvm/Support/SourceMgr.h" | |
| 37 | 32 |
| 38 #include <fstream> | |
| 39 #include <iostream> | 33 #include <iostream> |
| 40 | 34 |
| 41 using namespace llvm; | 35 using namespace llvm; |
| 42 | 36 |
| 37 namespace { |
| 38 |
| 43 // Debugging helper | 39 // Debugging helper |
| 44 template <typename T> static std::string LLVMObjectAsString(const T *O) { | 40 template <typename T> static std::string LLVMObjectAsString(const T *O) { |
| 45 std::string Dump; | 41 std::string Dump; |
| 46 raw_string_ostream Stream(Dump); | 42 raw_string_ostream Stream(Dump); |
| 47 O->print(Stream); | 43 O->print(Stream); |
| 48 return Stream.str(); | 44 return Stream.str(); |
| 49 } | 45 } |
| 50 | 46 |
| 51 // Converter from LLVM to ICE. The entry point is the convertFunction method. | 47 // Converter from LLVM to ICE. The entry point is the convertFunction method. |
| 52 // | 48 // |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 if (Call->getDest() != NULL) { | 588 if (Call->getDest() != NULL) { |
| 593 report_fatal_error( | 589 report_fatal_error( |
| 594 "Return value for intrinsic func w/ void return type."); | 590 "Return value for intrinsic func w/ void return type."); |
| 595 } | 591 } |
| 596 } else { | 592 } else { |
| 597 if (I->Signature[0] != Call->getDest()->getType()) { | 593 if (I->Signature[0] != Call->getDest()->getType()) { |
| 598 report_fatal_error("Mismatched return types."); | 594 report_fatal_error("Mismatched return types."); |
| 599 } | 595 } |
| 600 } | 596 } |
| 601 if (Call->getNumArgs() + 1 != I->NumTypes) { | 597 if (Call->getNumArgs() + 1 != I->NumTypes) { |
| 598 std::cerr << "Call->getNumArgs() " << (int)Call->getNumArgs() |
| 599 << " I->NumTypes " << (int)I->NumTypes << "\n"; |
| 602 report_fatal_error("Mismatched # of args."); | 600 report_fatal_error("Mismatched # of args."); |
| 603 } | 601 } |
| 604 for (size_t i = 1; i < I->NumTypes; ++i) { | 602 for (size_t i = 1; i < I->NumTypes; ++i) { |
| 605 if (Call->getArg(i - 1)->getType() != I->Signature[i]) { | 603 if (Call->getArg(i - 1)->getType() != I->Signature[i]) { |
| 606 report_fatal_error("Mismatched argument type."); | 604 report_fatal_error("Mismatched argument type."); |
| 607 } | 605 } |
| 608 } | 606 } |
| 609 } | 607 } |
| 610 | 608 |
| 611 private: | 609 private: |
| 612 // Data | 610 // Data |
| 613 Ice::GlobalContext *Ctx; | 611 Ice::GlobalContext *Ctx; |
| 614 Ice::Cfg *Func; | 612 Ice::Cfg *Func; |
| 615 Ice::CfgNode *CurrentNode; | 613 Ice::CfgNode *CurrentNode; |
| 616 Ice::Type SubzeroPointerType; | 614 Ice::Type SubzeroPointerType; |
| 617 std::map<const Value *, Ice::Variable *> VarMap; | 615 std::map<const Value *, Ice::Variable *> VarMap; |
| 618 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; | 616 std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; |
| 619 }; | 617 }; |
| 620 | 618 |
| 621 static cl::list<Ice::VerboseItem> VerboseList( | 619 } |
| 622 "verbose", cl::CommaSeparated, | |
| 623 cl::desc("Verbose options (can be comma-separated):"), | |
| 624 cl::values( | |
| 625 clEnumValN(Ice::IceV_Instructions, "inst", "Print basic instructions"), | |
| 626 clEnumValN(Ice::IceV_Deleted, "del", "Include deleted instructions"), | |
| 627 clEnumValN(Ice::IceV_InstNumbers, "instnum", | |
| 628 "Print instruction numbers"), | |
| 629 clEnumValN(Ice::IceV_Preds, "pred", "Show predecessors"), | |
| 630 clEnumValN(Ice::IceV_Succs, "succ", "Show successors"), | |
| 631 clEnumValN(Ice::IceV_Liveness, "live", "Liveness information"), | |
| 632 clEnumValN(Ice::IceV_RegManager, "rmgr", "Register manager status"), | |
| 633 clEnumValN(Ice::IceV_RegOrigins, "orig", "Physical register origins"), | |
| 634 clEnumValN(Ice::IceV_LinearScan, "regalloc", "Linear scan details"), | |
| 635 clEnumValN(Ice::IceV_Frame, "frame", "Stack frame layout details"), | |
| 636 clEnumValN(Ice::IceV_Timing, "time", "Pass timing details"), | |
| 637 clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), | |
| 638 clEnumValN(Ice::IceV_None, "none", "No verbosity"), clEnumValEnd)); | |
| 639 static cl::opt<Ice::TargetArch> TargetArch( | |
| 640 "target", cl::desc("Target architecture:"), cl::init(Ice::Target_X8632), | |
| 641 cl::values( | |
| 642 clEnumValN(Ice::Target_X8632, "x8632", "x86-32"), | |
| 643 clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"), | |
| 644 clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"), | |
| 645 clEnumValN(Ice::Target_X8664, "x8664", "x86-64"), | |
| 646 clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"), | |
| 647 clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"), | |
| 648 clEnumValN(Ice::Target_ARM32, "arm", "arm32"), | |
| 649 clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"), | |
| 650 clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd)); | |
| 651 static cl::opt<Ice::OptLevel> | |
| 652 OptLevel(cl::desc("Optimization level"), cl::init(Ice::Opt_m1), | |
| 653 cl::value_desc("level"), | |
| 654 cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"), | |
| 655 clEnumValN(Ice::Opt_m1, "O-1", "-1"), | |
| 656 clEnumValN(Ice::Opt_0, "O0", "0"), | |
| 657 clEnumValN(Ice::Opt_1, "O1", "1"), | |
| 658 clEnumValN(Ice::Opt_2, "O2", "2"), clEnumValEnd)); | |
| 659 static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), | |
| 660 cl::init("-")); | |
| 661 static cl::opt<std::string> OutputFilename("o", | |
| 662 cl::desc("Override output filename"), | |
| 663 cl::init("-"), | |
| 664 cl::value_desc("filename")); | |
| 665 static cl::opt<std::string> LogFilename("log", cl::desc("Set log filename"), | |
| 666 cl::init("-"), | |
| 667 cl::value_desc("filename")); | |
| 668 static cl::opt<std::string> | |
| 669 TestPrefix("prefix", cl::desc("Prepend a prefix to symbol names for testing"), | |
| 670 cl::init(""), cl::value_desc("prefix")); | |
| 671 static cl::opt<bool> | |
| 672 DisableInternal("external", | |
| 673 cl::desc("Disable 'internal' linkage type for testing")); | |
| 674 static cl::opt<bool> | |
| 675 DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); | |
| 676 | 620 |
| 677 static cl::opt<bool> SubzeroTimingEnabled( | 621 int Ice::Converter::convertToIce(llvm::Module *Mod) { |
| 678 "timing", cl::desc("Enable breakdown timing of Subzero translation")); | |
| 679 | |
| 680 static cl::opt<NaClFileFormat> InputFileFormat( | |
| 681 "bitcode-format", cl::desc("Define format of input file:"), | |
| 682 cl::values(clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"), | |
| 683 clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"), | |
| 684 clEnumValEnd), | |
| 685 cl::init(LLVMFormat)); | |
| 686 | |
| 687 int main(int argc, char **argv) { | |
| 688 int ExitStatus = 0; | 622 int ExitStatus = 0; |
| 689 | 623 |
| 690 cl::ParseCommandLineOptions(argc, argv); | |
| 691 | |
| 692 // Parse the input LLVM IR file into a module. | |
| 693 SMDiagnostic Err; | |
| 694 Module *Mod; | |
| 695 | |
| 696 { | |
| 697 Ice::Timer T; | |
| 698 Mod = NaClParseIRFile(IRFilename, InputFileFormat, Err, getGlobalContext()); | |
| 699 | |
| 700 if (SubzeroTimingEnabled) { | |
| 701 std::cerr << "[Subzero timing] IR Parsing: " << T.getElapsedSec() | |
| 702 << " sec\n"; | |
| 703 } | |
| 704 } | |
| 705 | |
| 706 if (!Mod) { | |
| 707 Err.print(argv[0], errs()); | |
| 708 return 1; | |
| 709 } | |
| 710 | |
| 711 Ice::VerboseMask VMask = Ice::IceV_None; | |
| 712 for (unsigned i = 0; i != VerboseList.size(); ++i) | |
| 713 VMask |= VerboseList[i]; | |
| 714 | |
| 715 std::ofstream Ofs; | |
| 716 if (OutputFilename != "-") { | |
| 717 Ofs.open(OutputFilename.c_str(), std::ofstream::out); | |
| 718 } | |
| 719 raw_os_ostream *Os = | |
| 720 new raw_os_ostream(OutputFilename == "-" ? std::cout : Ofs); | |
| 721 Os->SetUnbuffered(); | |
| 722 std::ofstream Lfs; | |
| 723 if (LogFilename != "-") { | |
| 724 Lfs.open(LogFilename.c_str(), std::ofstream::out); | |
| 725 } | |
| 726 raw_os_ostream *Ls = new raw_os_ostream(LogFilename == "-" ? std::cout : Lfs); | |
| 727 Ls->SetUnbuffered(); | |
| 728 | |
| 729 // Ideally, Func would be declared inside the loop and its object | 624 // Ideally, Func would be declared inside the loop and its object |
| 730 // would be automatically deleted at the end of the loop iteration. | 625 // would be automatically deleted at the end of the loop iteration. |
| 731 // However, emitting the constant pool requires a valid Cfg object, | 626 // However, emitting the constant pool requires a valid Cfg object, |
| 732 // so we need to defer deleting the last non-empty Cfg object until | 627 // so we need to defer deleting the last non-empty Cfg object until |
| 733 // outside the loop and after emitting the constant pool. TODO: | 628 // outside the loop and after emitting the constant pool. TODO: |
| 734 // Since all constants are globally pooled in the Ice::GlobalContext | 629 // Since all constants are globally pooled in the Ice::GlobalContext |
| 735 // object, change all Ice::Constant related functions to use | 630 // object, change all Ice::Constant related functions to use |
| 736 // GlobalContext instead of Cfg, and then clean up this loop. | 631 // GlobalContext instead of Cfg, and then clean up this loop. |
| 737 OwningPtr<Ice::Cfg> Func; | 632 OwningPtr<Ice::Cfg> Func; |
| 738 Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix); | |
| 739 | 633 |
| 740 for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { | 634 for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { |
| 741 if (I->empty()) | 635 if (I->empty()) |
| 742 continue; | 636 continue; |
| 743 LLVM2ICEConverter FunctionConverter(&Ctx); | 637 LLVM2ICEConverter FunctionConverter(Ctx); |
| 744 | 638 |
| 745 Ice::Timer TConvert; | 639 Ice::Timer TConvert; |
| 746 Func.reset(FunctionConverter.convertFunction(I)); | 640 Func.reset(FunctionConverter.convertFunction(I)); |
| 747 if (DisableInternal) | 641 if (DisableInternal) |
| 748 Func->setInternal(false); | 642 Func->setInternal(false); |
| 749 | 643 |
| 750 if (SubzeroTimingEnabled) { | 644 if (SubzeroTimingEnabled) { |
| 751 std::cerr << "[Subzero timing] Convert function " | 645 std::cerr << "[Subzero timing] Convert function " |
| 752 << Func->getFunctionName() << ": " << TConvert.getElapsedSec() | 646 << Func->getFunctionName() << ": " << TConvert.getElapsedSec() |
| 753 << " sec\n"; | 647 << " sec\n"; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 776 << " sec\n"; | 670 << " sec\n"; |
| 777 } | 671 } |
| 778 } | 672 } |
| 779 } | 673 } |
| 780 | 674 |
| 781 if (!DisableTranslation && Func) | 675 if (!DisableTranslation && Func) |
| 782 Func->getTarget()->emitConstants(); | 676 Func->getTarget()->emitConstants(); |
| 783 | 677 |
| 784 return ExitStatus; | 678 return ExitStatus; |
| 785 } | 679 } |
| OLD | NEW |