Tidy up the target files for episode 7
This commit is contained in:
parent
a1d3ae8c9c
commit
36b95fe1e5
4
dev.org
4
dev.org
|
@ -118,7 +118,9 @@ in python.
|
|||
*** TODO Error handling
|
||||
Create proper error handling for the internal infra
|
||||
*** TODO Replace =llvm::outs()= with debug statements
|
||||
* ** TODO Move the generatable logic out of its files and remove them
|
||||
*** TODO Move the generatable logic out of its files and remove them
|
||||
*** TODO Add a CLI option to get any extra pass
|
||||
*** TODO Add support for =sourcemgr= for input files
|
||||
*** TODO Language Spec :DOCS:
|
||||
*** TODO A proper List implementation
|
||||
*** TODO Vector implementation
|
||||
|
|
|
@ -130,7 +130,8 @@ a data structure describing the syntax.
|
|||
- Expressions vs Statements
|
||||
- Serene(Lisp) and expressions
|
||||
** Node & AST
|
||||
* Episode 6 - The Semantic Analyzer
|
||||
* DONE Episode 6 - The Semantic Analyzer
|
||||
CLOSED: [2021-08-21 Sat 18:44]
|
||||
** Qs
|
||||
- Why didn't we implement a linked list?
|
||||
- Why we are using the =std::vector= instead of llvm collections?
|
||||
|
@ -158,3 +159,13 @@ We need to reform the AST to reflect the semantics of Serene closly.
|
|||
|
||||
Let's run the compiler to see the semantic analysis in action.
|
||||
** Let's check out the code
|
||||
* Episode 7 - The Context and Namespace
|
||||
** Namespaces
|
||||
*** Unit of compilation
|
||||
*** Usually maps to a file
|
||||
*** keeps the state and evironment
|
||||
** SereneContext vs LLVM Context vs MLIR Context
|
||||
*** Compilers global state
|
||||
*** The owner of LLVM/MLIR contexts
|
||||
*** Holds the namespace table
|
||||
*** Probably will contain the primitive types as well
|
||||
|
|
|
@ -79,8 +79,11 @@ public:
|
|||
/// will fail if the namespace does not exist in the namespace table.
|
||||
bool setCurrentNS(llvm::StringRef ns_name);
|
||||
|
||||
/// Return the current namespace that is being processed at the moment
|
||||
std::shared_ptr<Namespace> getCurrentNS();
|
||||
|
||||
/// Lookup the namespace with the give name in the current context and
|
||||
/// return a shared pointer to it or a `nullptr` in it doesn't exist.
|
||||
std::shared_ptr<Namespace> getNS(llvm::StringRef ns_name);
|
||||
|
||||
SereneContext()
|
||||
|
@ -89,15 +92,24 @@ public:
|
|||
mlirContext.getOrLoadDialect<mlir::StandardOpsDialect>();
|
||||
// TODO: Get the crash report path dynamically from the cli
|
||||
// pm.enableCrashReproducerGeneration("/home/lxsameer/mlir.mlir");
|
||||
|
||||
// TODO: Set the target triple with respect to the CLI args
|
||||
targetTriple = llvm::sys::getDefaultTargetTriple();
|
||||
};
|
||||
|
||||
/// Set the target compilation phase of the compiler. The compilation
|
||||
/// phase dictates the behavior and the output type of the compiler.
|
||||
void setOperationPhase(CompilationPhase phase);
|
||||
|
||||
CompilationPhase getTargetPhase() { return targetPhase; };
|
||||
int getOptimizatioLevel();
|
||||
|
||||
private:
|
||||
CompilationPhase targetPhase;
|
||||
|
||||
// The namespace table. Every namespace that needs to be compiled has
|
||||
// to register itself with the context and appear on this table.
|
||||
// This table acts as a cache as well.
|
||||
std::map<std::string, std::shared_ptr<Namespace>> namespaces;
|
||||
|
||||
// Why string vs pointer? We might rewrite the namespace and
|
||||
|
|
|
@ -25,22 +25,29 @@
|
|||
#ifndef SERENE_ENVIRONMENT_H
|
||||
#define SERENE_ENVIRONMENT_H
|
||||
|
||||
#include "mlir/Support/LogicalResult.h"
|
||||
#include "serene/llvm/patches.h"
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <llvm/ADT/DenseMap.h>
|
||||
#include <mlir/Support/LogicalResult.h>
|
||||
|
||||
namespace serene {
|
||||
|
||||
/// This class represents a classic lisp environment (or scope) that holds the
|
||||
/// bindings from type `K` to type `V`. For example an environment of symbols
|
||||
/// to expressions would be `Environment<Symbol, Node>`
|
||||
template <typename K, typename V>
|
||||
class Environment {
|
||||
|
||||
Environment<K, V> *parent;
|
||||
|
||||
// The actual bindings storage
|
||||
llvm::DenseMap<K, V> pairs;
|
||||
|
||||
public:
|
||||
Environment() : parent(nullptr) {}
|
||||
Environment(Environment *parent) : parent(parent){};
|
||||
|
||||
/// Look up the given `key` in the environment and return it.
|
||||
llvm::Optional<V> lookup(K key) {
|
||||
if (auto value = pairs.lookup(key)) {
|
||||
return value;
|
||||
|
@ -53,6 +60,8 @@ public:
|
|||
return llvm::None;
|
||||
};
|
||||
|
||||
/// Insert the given `key` with the given `value` into the storage. This
|
||||
/// operation will shadow an aleady exist `key` in the parent environment
|
||||
mlir::LogicalResult insert_symbol(K key, V value) {
|
||||
pairs.insert(std::pair<K, V>(key, value));
|
||||
return mlir::success();
|
||||
|
|
|
@ -66,8 +66,13 @@ using MaybeModuleOp = Result<mlir::OwningOpRef<mlir::ModuleOp>, bool>;
|
|||
class Namespace {
|
||||
private:
|
||||
SereneContext &ctx;
|
||||
bool initialized = false;
|
||||
bool initialized = false;
|
||||
|
||||
// Anonymous function counter. We need to assing a unique name to each
|
||||
// anonymous function and we use this counter to generate those names
|
||||
std::atomic<uint> fn_counter = 0;
|
||||
|
||||
// The content of the namespace
|
||||
exprs::Ast tree;
|
||||
|
||||
public:
|
||||
|
@ -78,22 +83,30 @@ public:
|
|||
/// Which is a mapping from names to AST nodes ( no evaluation ).
|
||||
Environment<std::string, exprs::Node> semanticEnv;
|
||||
|
||||
/// Th root environmanet to store the MLIR value during the IR generation
|
||||
/// phase.
|
||||
Environment<llvm::StringRef, mlir::Value> symbolTable;
|
||||
|
||||
Namespace(SereneContext &ctx, llvm::StringRef ns_name,
|
||||
llvm::Optional<llvm::StringRef> filename);
|
||||
|
||||
exprs::Ast &getTree();
|
||||
mlir::LogicalResult setTree(exprs::Ast &);
|
||||
|
||||
/// Increase the function counter by one
|
||||
uint nextFnCounter();
|
||||
|
||||
SereneContext &getContext();
|
||||
|
||||
/// Generate the IR of the namespace with respect to the compilation phase
|
||||
/// Generate and return a MLIR ModuleOp tha contains the IR of the namespace
|
||||
/// with respect to the compilation phase
|
||||
MaybeModuleOp generate();
|
||||
/// Compile the given namespace to the llvm module. It will call the
|
||||
|
||||
/// Compile the namespace to a llvm module. It will call the
|
||||
/// `generate` method of the namespace to generate the IR.
|
||||
MaybeModule compileToLLVM();
|
||||
|
||||
/// Run all the passes specified in the context on the given MLIR ModuleOp.
|
||||
mlir::LogicalResult runPasses(mlir::ModuleOp &m);
|
||||
|
||||
/// Dumps the namespace with respect to the compilation phase
|
||||
|
@ -102,6 +115,10 @@ public:
|
|||
~Namespace();
|
||||
};
|
||||
|
||||
/// Create a naw namespace with the given `name` and optional `filename` and
|
||||
/// return a shared pointer to it in the given Serene context. If the
|
||||
/// `setCurrent` argument is set to true, the created NS will become the curret
|
||||
/// namespace in the context
|
||||
std::shared_ptr<Namespace>
|
||||
makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||
llvm::Optional<llvm::StringRef> filename, bool setCurrent = true);
|
||||
|
|
Loading…
Reference in New Issue