diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-06-04 01:14:24 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-06-04 01:14:24 +0800 |
| commit | f4af325caaa8acc53e2535338b93341ec9b982ff (patch) | |
| tree | 5bd59fbcea6f29beee46c089f52f44f7675fcabc | |
| parent | 1c03eb2f7320085469a06e3c5f49eb43e587e716 (diff) | |
dot output support
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Log.cc | 2 | ||||
| -rw-r--r-- | Version.cc | 3 | ||||
| -rw-r--r-- | main.cc | 53 | ||||
| -rw-r--r-- | node/Node.cc | 4 | ||||
| -rw-r--r-- | traveler/AsciiTraveler.cc | 17 | ||||
| -rw-r--r-- | traveler/AsciiTraveler.hh | 6 | ||||
| -rw-r--r-- | traveler/DotTraveler.cc | 49 | ||||
| -rw-r--r-- | traveler/DotTraveler.hh | 22 | ||||
| -rw-r--r-- | traveler/Traveler.cc | 10 | ||||
| -rw-r--r-- | traveler/Traveler.hh | 6 |
12 files changed, 148 insertions, 26 deletions
@@ -1,4 +1,5 @@ build +rel .vscode .vs CMakeSettings.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 902869a..3a6e4f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ list(APPEND PCC_SOURCE list(APPEND PCC_SOURCE traveler/AsciiTraveler.cc + traveler/DotTraveler.cc traveler/Traveler.cc) set(PCC_INCLUDE @@ -16,7 +16,7 @@ void Log(LogLevel level, const char* format, ...) { std::cerr << Color::RED << "error: "; break; case PCC_WARNING: - std::cerr << Color::YELLOW << "warning: "; + std::cerr << Color::MAGENTA << "warning: "; break; case PCC_INFO: std::cerr << Color::CYAN << "info: "; @@ -40,7 +40,8 @@ PCC_NORETURN void ShowHelp() { " -o <output> Specify output file name.\n" " -O <0,1,2,3> Specify optimization level.\n" "\n" - " -a Also dump the AST." + " -a Dump the AST.\n" + " -d Generate a dot file for AST." << std::endl; std::exit(0); } @@ -1,3 +1,4 @@ +#include <fstream> #include <iostream> #ifdef _MSC_VER @@ -6,13 +7,16 @@ #include <unistd.h> #endif +#include <llvm/IR/IRPrintingPasses.h> #include <llvm/IR/LegacyPassManager.h> #include <llvm/IR/Verifier.h> #include <llvm/Support/TargetRegistry.h> #include <llvm/Support/TargetSelect.h> #include <llvm/Target/TargetMachine.h> +#include <llvm/Transforms/Scalar.h> #include "AsciiTraveler.hh" +#include "DotTraveler.hh" #include "Driver.hh" #include "Log.hh" #include "Version.hh" @@ -26,10 +30,10 @@ int main(int argc, char* argv[]) { std::string OutputFileName; enum { IR, ASSEMBLY, OBJECT } CompileType = IR; int OptLevel = 2; - bool AsciiTravel = false; + bool AsciiTravel = false, DotTravel = false; pcc::SetExecutableName(argv[0]); - while ((rv = getopt(argc, argv, "vVhiScao:O:")) != -1) { + while ((rv = getopt(argc, argv, "vVhiScado:O:")) != -1) { switch (rv) { case 'v': level = (level == 0 ? 0 : level - 1); @@ -50,6 +54,9 @@ int main(int argc, char* argv[]) { case 'a': AsciiTravel = true; break; + case 'd': + DotTravel = true; + break; case 'o': OutputFileName = optarg; break; @@ -132,19 +139,29 @@ int main(int argc, char* argv[]) { } std::error_code ErrorCode; llvm::raw_fd_ostream output(OutputFileName, ErrorCode); + llvm::legacy::PassManager manager; + manager.add(llvm::createCFGSimplificationPass()); + manager.add(llvm::createMergedLoadStoreMotionPass()); + manager.add(llvm::createReassociatePass()); + manager.add(llvm::createLoopSimplifyCFGPass()); switch (CompileType) { case IR: - module->print(output, nullptr); + manager.add(llvm::createPrintModulePass(output)); break; case ASSEMBLY: - compile(module, output, llvm::CGFT_AssemblyFile, machine); + machine->addPassesToEmitFile( + manager, output, nullptr, + llvm::CodeGenFileType::CGFT_AssemblyFile); break; case OBJECT: - compile(module, output, llvm::CGFT_ObjectFile, machine); + machine->addPassesToEmitFile( + manager, output, nullptr, + llvm::CodeGenFileType::CGFT_ObjectFile); break; default: break; } + manager.run(*module); pcc::Log(pcc::PCC_INFO, "%s compiled to %s", argv[i], OutputFileName.c_str()); OutputFileName.clear(); @@ -152,15 +169,25 @@ int main(int argc, char* argv[]) { pcc::Log(pcc::PCC_INFO, "dumping abstract syntax tree of %s", argv[i]); pcc::AsciiTraveler traveler(std::cerr); - root->Travel(traveler); + traveler.Travel(root); + } + if (DotTravel == true) { + std::string DotOutputName; + size_t PostfixPos = filename.rfind(".pas"); + if (PostfixPos == std::string::npos) { + DotOutputName = filename + ".dot"; + } else { + DotOutputName = filename.substr(0, PostfixPos) + ".dot"; + } + std::ofstream DotOut(DotOutputName); + if (DotOut.is_open() == false) { + pcc::Log(pcc::PCC_ERROR, "failed to open dot outpt file %s", + DotOutputName.c_str()); + } + pcc::DotTraveler traveler(DotOut); + traveler.Travel(root); + DotOut.close(); } } return 0; } - -void compile(llvm::Module* module, llvm::raw_pwrite_stream& output, - llvm::CodeGenFileType type, llvm::TargetMachine* machine) { - llvm::legacy::PassManager manager; - machine->addPassesToEmitFile(manager, output, nullptr, type); - manager.run(*module); -} diff --git a/node/Node.cc b/node/Node.cc index 822dbfc..0dcf8ce 100644 --- a/node/Node.cc +++ b/node/Node.cc @@ -191,7 +191,6 @@ int PointerAccessNode::Travel(Traveler& traveler) { traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN; rhs_->Travel(traveler); traveler << TravelPart::LAST_CHILD_END << TravelPart::END; - traveler << TravelPart::END; return 0; } @@ -206,7 +205,6 @@ int ArrayAccessNode::Travel(Traveler& traveler) { traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN; rhs_->Travel(traveler); traveler << TravelPart::LAST_CHILD_END << TravelPart::END; - traveler << TravelPart::END; return 0; } @@ -368,7 +366,7 @@ int StringLiteralNode::Travel(Traveler& traveler) { if (std::isprint(c)) { escaped.push_back(c); } else { - auto hex = {'\\', 'x', HexChars[c & 0xf], HexChars[(c >> 4) & 0xf]}; + auto hex = {'\\', 'x', HexChars[(c >> 4) & 0xf], HexChars[c & 0xf]}; escaped.append(hex); } } diff --git a/traveler/AsciiTraveler.cc b/traveler/AsciiTraveler.cc index b20e53b..a44313b 100644 --- a/traveler/AsciiTraveler.cc +++ b/traveler/AsciiTraveler.cc @@ -1,4 +1,5 @@ #include "AsciiTraveler.hh" +#include "Color.hh" namespace pcc { const std::string AsciiTraveler::MiddleLevelPrefix_ = "|-"; @@ -10,28 +11,30 @@ const size_t AsciiTraveler::LevelWidth_ = AsciiTraveler::AsciiTraveler(std::ostream& out) : Traveler(out) - , prefix_("") { + , prefix_("") + , random_(13) + , dist_(0, 1) { IsLastChild_.push(true); } +void AsciiTraveler::PostTravel() { out_ << Color::DEFAULT; } + Traveler& AsciiTraveler::operator<<(TravelPart part) { switch (part) { case TravelPart::PREFIX: - out_ << prefix_ + out_ << Color::BLUE << prefix_ << (IsLastChild_.top() ? LastLevelPrefix_ : MiddleLevelPrefix_); break; case TravelPart::NAME_BEGIN: - out_ << '<'; + out_ << (dist_(random_) == 1 ? Color::MAGENTA : Color::GREEN); break; case TravelPart::NAME_END: - out_ << '>'; - break; break; case TravelPart::DESCRPTION_BEGIN: - out_ << '<'; + out_ << (dist_(random_) == 1 ? Color::CYAN : Color::YELLOW) << " "; break; case TravelPart::DESCRPTION_END: - out_ << ">\n"; + out_ << "\n"; break; case TravelPart::CHILD_BEGIN: prefix_.append(IsLastChild_.top() ? LastChildPrefix_ diff --git a/traveler/AsciiTraveler.hh b/traveler/AsciiTraveler.hh index 16e559f..8e8e7e1 100644 --- a/traveler/AsciiTraveler.hh +++ b/traveler/AsciiTraveler.hh @@ -1,6 +1,7 @@ #ifndef PCC_ASCIITRAVELER_HH #define PCC_ASCIITRAVELER_HH +#include <random> #include <stack> #include <string> @@ -10,11 +11,14 @@ namespace pcc { class AsciiTraveler : public Traveler { public: AsciiTraveler(std::ostream& out); - virtual Traveler& operator<<(TravelPart part); + virtual Traveler& operator<<(TravelPart part) override; protected: + void PostTravel() override; std::string prefix_; std::stack<bool> IsLastChild_; + std::mt19937 random_; + std::uniform_int_distribution<int> dist_; static const std::string MiddleLevelPrefix_; static const std::string LastLevelPrefix_; diff --git a/traveler/DotTraveler.cc b/traveler/DotTraveler.cc new file mode 100644 index 0000000..daf64ec --- /dev/null +++ b/traveler/DotTraveler.cc @@ -0,0 +1,49 @@ +#include "DotTraveler.hh" + +namespace pcc { +DotTraveler::DotTraveler(std::ostream& out) + : Traveler(out) + , CurrentIndex_(0) {} + +void DotTraveler::PreTravel() { + out_ << "digraph \"AST dump\"\n" + "{\n" + " node [fontname = courier, shape = box, colorscheme = paired6]\n" + " edge [fontname = courier]\n\n"; +} + +void DotTraveler::PostTravel() { out_ << "}\n"; } + +Traveler& DotTraveler::operator<<(TravelPart part) { + switch (part) { + case TravelPart::PREFIX: + out_ << " " << CurrentIndex_ << " [label=\""; + NodeIndex_.push(CurrentIndex_); + ++CurrentIndex_; + break; + case TravelPart::NAME_BEGIN: + case TravelPart::DESCRPTION_BEGIN: + break; + case TravelPart::NAME_END: + out_ << "\\n\\n"; + break; + case TravelPart::DESCRPTION_END: + out_ << "\"]\n"; + break; + case TravelPart::CHILD_BEGIN: + case TravelPart::LAST_CHILD_BEGIN: + out_ << " " << NodeIndex_.top() << " -> " << CurrentIndex_ + << " [style=solid]\n"; + break; + case TravelPart::CHILD_END: + case TravelPart::LAST_CHILD_END: + break; + case TravelPart::END: + NodeIndex_.pop(); + break; + default: + break; + } + return *this; +} +} // namespace pcc diff --git a/traveler/DotTraveler.hh b/traveler/DotTraveler.hh new file mode 100644 index 0000000..c80b15e --- /dev/null +++ b/traveler/DotTraveler.hh @@ -0,0 +1,22 @@ +#ifndef PCC_DOTTRAVELER_HH +#define PCC_DOTTRAVELER_HH + +#include <stack> + +#include "Traveler.hh" + +namespace pcc { +class DotTraveler : public Traveler { + public: + DotTraveler(std::ostream& out); + virtual Traveler& operator<<(TravelPart part) override; + + protected: + virtual void PreTravel() override; + virtual void PostTravel() override; + std::stack<int> NodeIndex_; + int CurrentIndex_; +}; +} // namespace pcc + +#endif // !PCC_DOTTRAVELER_HH diff --git a/traveler/Traveler.cc b/traveler/Traveler.cc index e365b28..f503f30 100644 --- a/traveler/Traveler.cc +++ b/traveler/Traveler.cc @@ -1,6 +1,16 @@ #include "Traveler.hh" +#include "BaseNode.hh" namespace pcc { Traveler::Traveler(std::ostream& out) : out_(out) {} + +void Traveler::Travel(std::shared_ptr<BaseNode> root) { + PreTravel(); + root->Travel(*this); + PostTravel(); +} + +void Traveler::PreTravel() {} +void Traveler::PostTravel() {} } // namespace pcc diff --git a/traveler/Traveler.hh b/traveler/Traveler.hh index 09f8d0d..92f5b99 100644 --- a/traveler/Traveler.hh +++ b/traveler/Traveler.hh @@ -19,9 +19,13 @@ enum class TravelPart { LAST_CHILD_END, END }; + +class BaseNode; + class Traveler { public: Traveler(std::ostream& out); + void Travel(std::shared_ptr<BaseNode> root); virtual Traveler& operator<<(TravelPart part) = 0; Traveler& operator<<(std::shared_ptr<Type> type); Traveler& operator<<(std::shared_ptr<TypeIdentifier> identifier); @@ -33,6 +37,8 @@ class Traveler { } protected: + virtual void PreTravel(); + virtual void PostTravel(); std::ostream& out_; }; } // namespace pcc |
