summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-06-04 01:14:24 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-06-04 01:14:24 +0800
commitf4af325caaa8acc53e2535338b93341ec9b982ff (patch)
tree5bd59fbcea6f29beee46c089f52f44f7675fcabc
parent1c03eb2f7320085469a06e3c5f49eb43e587e716 (diff)
dot output support
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt1
-rw-r--r--Log.cc2
-rw-r--r--Version.cc3
-rw-r--r--main.cc53
-rw-r--r--node/Node.cc4
-rw-r--r--traveler/AsciiTraveler.cc17
-rw-r--r--traveler/AsciiTraveler.hh6
-rw-r--r--traveler/DotTraveler.cc49
-rw-r--r--traveler/DotTraveler.hh22
-rw-r--r--traveler/Traveler.cc10
-rw-r--r--traveler/Traveler.hh6
12 files changed, 148 insertions, 26 deletions
diff --git a/.gitignore b/.gitignore
index fac49c0..862a601 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/Log.cc b/Log.cc
index f08cc05..a0ee758 100644
--- a/Log.cc
+++ b/Log.cc
@@ -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: ";
diff --git a/Version.cc b/Version.cc
index bb0007d..61f152c 100644
--- a/Version.cc
+++ b/Version.cc
@@ -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);
}
diff --git a/main.cc b/main.cc
index 57a0184..1e87d71 100644
--- a/main.cc
+++ b/main.cc
@@ -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