Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Sameer Rahmani | 6e6c8d8897 | |
Sameer Rahmani | 462074faa6 |
|
@ -509,7 +509,8 @@ This framework allows for transforming a set of illegal operations to a set of l
|
||||||
*** Rewrite Patterns
|
*** Rewrite Patterns
|
||||||
*** Type Converter
|
*** Type Converter
|
||||||
** Full vs Partial Conversion
|
** Full vs Partial Conversion
|
||||||
* Episode 12 - Target code generation
|
* DONE Episode 12 - Target code generation
|
||||||
|
CLOSED: [2021-11-04 Thu 00:57]
|
||||||
** Updates:
|
** Updates:
|
||||||
*** JIT work
|
*** JIT work
|
||||||
*** Emacs dev mode
|
*** Emacs dev mode
|
||||||
|
@ -561,3 +562,23 @@ and tries to =resolve= *undefined* symbols
|
||||||
** Let's look at some code
|
** Let's look at some code
|
||||||
** Resources:
|
** Resources:
|
||||||
- [[https://lwn.net/Articles/276782/][20 part linker essay]]
|
- [[https://lwn.net/Articles/276782/][20 part linker essay]]
|
||||||
|
* Episode 13 - Source Managers
|
||||||
|
** FAQ:
|
||||||
|
- What tools are you using?
|
||||||
|
|
||||||
|
** Updates:
|
||||||
|
- Still JIT
|
||||||
|
- We're going to start the JIT discussion from next EP
|
||||||
|
|
||||||
|
** Forgot to show case the code generation
|
||||||
|
I didn't show it in action
|
||||||
|
|
||||||
|
** What is a source manager
|
||||||
|
- It owns and manages are the source buffers
|
||||||
|
- All of our interactions with source files will happen though Source manager
|
||||||
|
- Including reading files
|
||||||
|
- Loading namespaces
|
||||||
|
- Including namespaces
|
||||||
|
- ...
|
||||||
|
|
||||||
|
- LLVM provides a =SourceMgr= class that we're not using it
|
||||||
|
|
|
@ -42,7 +42,7 @@ class SereneContext;
|
||||||
|
|
||||||
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
|
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
|
||||||
/// even borrowed some of the code from the original implementation but removed
|
/// even borrowed some of the code from the original implementation but removed
|
||||||
/// a lot of code that ar irrelevant to us.
|
/// a lot of code that were irrelevant to us.
|
||||||
///
|
///
|
||||||
/// SouceMgr is responsible for finding a namespace in the `loadPaths` and read
|
/// SouceMgr is responsible for finding a namespace in the `loadPaths` and read
|
||||||
/// the content of the `.srn` (or any of the `DEFAULT_SUFFIX`) into a
|
/// the content of the `.srn` (or any of the `DEFAULT_SUFFIX`) into a
|
||||||
|
@ -80,7 +80,7 @@ private:
|
||||||
/// dynamically based on the size of Buffer.
|
/// dynamically based on the size of Buffer.
|
||||||
mutable void *offsetCache = nullptr;
|
mutable void *offsetCache = nullptr;
|
||||||
|
|
||||||
/// Look up a given \p Ptr in in the buffer, determining which line it came
|
/// Look up a given \p ptr in in the buffer, determining which line it came
|
||||||
/// from.
|
/// from.
|
||||||
unsigned getLineNumber(const char *ptr) const;
|
unsigned getLineNumber(const char *ptr) const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -103,7 +103,7 @@ private:
|
||||||
SrcBuffer &operator=(const SrcBuffer &) = delete;
|
SrcBuffer &operator=(const SrcBuffer &) = delete;
|
||||||
~SrcBuffer();
|
~SrcBuffer();
|
||||||
};
|
};
|
||||||
using ErrorOrMemBufPtr = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
|
using MemBufPtr = std::unique_ptr<llvm::MemoryBuffer>;
|
||||||
|
|
||||||
/// This is all of the buffers that we are reading from.
|
/// This is all of the buffers that we are reading from.
|
||||||
std::vector<SrcBuffer> buffers;
|
std::vector<SrcBuffer> buffers;
|
||||||
|
@ -119,8 +119,8 @@ private:
|
||||||
// a unique pointer to the memory buffer containing the content or an error.
|
// a unique pointer to the memory buffer containing the content or an error.
|
||||||
// In the success case it will put the path of the file into the \p
|
// In the success case it will put the path of the file into the \p
|
||||||
// importedFile.
|
// importedFile.
|
||||||
ErrorOrMemBufPtr findFileInLoadPath(const std::string &name,
|
MemBufPtr findFileInLoadPath(const std::string &name,
|
||||||
std::string &importedFile);
|
std::string &importedFile);
|
||||||
|
|
||||||
bool isValidBufferID(unsigned i) const;
|
bool isValidBufferID(unsigned i) const;
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ public:
|
||||||
/// Set the `loadPaths` to the given \p dirs. `loadPaths` is a vector of
|
/// Set the `loadPaths` to the given \p dirs. `loadPaths` is a vector of
|
||||||
/// directories that Serene will look in order to find a file that constains a
|
/// directories that Serene will look in order to find a file that constains a
|
||||||
/// namespace which it is looking for.
|
/// namespace which it is looking for.
|
||||||
void setLoadPaths(const std::vector<std::string> &dirs) { loadPaths = dirs; }
|
void setLoadPaths(std::vector<std::string> &dirs) { loadPaths.swap(dirs); }
|
||||||
|
|
||||||
/// Return a reference to a `SrcBuffer` with the given ID \p i.
|
/// Return a reference to a `SrcBuffer` with the given ID \p i.
|
||||||
const SrcBuffer &getBufferInfo(unsigned i) const {
|
const SrcBuffer &getBufferInfo(unsigned i) const {
|
||||||
|
|
|
@ -28,15 +28,16 @@
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
#include "serene/reader/location.h"
|
#include "serene/reader/location.h"
|
||||||
#include "serene/reader/reader.h"
|
#include "serene/reader/reader.h"
|
||||||
#include "serene/reader/semantics.h"
|
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
#include <llvm/Support/FormatVariadic.h>
|
#include <llvm/Support/FormatVariadic.h>
|
||||||
#include <llvm/Support/Locale.h>
|
#include <llvm/Support/Locale.h>
|
||||||
#include <llvm/Support/MemoryBufferRef.h>
|
#include <llvm/Support/MemoryBufferRef.h>
|
||||||
#include <llvm/Support/Path.h>
|
#include <llvm/Support/Path.h>
|
||||||
|
#include <llvm/Support/raw_ostream.h>
|
||||||
#include <mlir/Support/LogicalResult.h>
|
#include <mlir/Support/LogicalResult.h>
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
@ -55,27 +56,30 @@ bool SourceMgr::isValidBufferID(unsigned i) const {
|
||||||
return i != 0 && i <= buffers.size();
|
return i != 0 && i <= buffers.size();
|
||||||
};
|
};
|
||||||
|
|
||||||
SourceMgr::ErrorOrMemBufPtr
|
SourceMgr::MemBufPtr SourceMgr::findFileInLoadPath(const std::string &name,
|
||||||
SourceMgr::findFileInLoadPath(const std::string &name,
|
std::string &importedFile) {
|
||||||
std::string &importedFile) {
|
|
||||||
|
|
||||||
auto path = convertNamespaceToPath(name);
|
auto path = convertNamespaceToPath(name);
|
||||||
// TODO: Fix this to enqueue a proper error instead
|
|
||||||
ErrorOrMemBufPtr newBufOrErr(
|
|
||||||
std::make_error_code(std::errc::no_such_file_or_directory));
|
|
||||||
|
|
||||||
// If the file didn't exist directly, see if it's in an include path.
|
// If the file didn't exist directly, see if it's in an include path.
|
||||||
for (unsigned i = 0, e = loadPaths.size(); i != e && !newBufOrErr; ++i) {
|
for (unsigned i = 0, e = loadPaths.size(); i != e; ++i) {
|
||||||
|
|
||||||
// TODO: Ugh, Udgly, fix this using llvm::sys::path functions
|
// TODO: Ugh, Udgly, fix this using llvm::sys::path functions
|
||||||
importedFile = loadPaths[i] + llvm::sys::path::get_separator().data() +
|
importedFile = loadPaths[i] + llvm::sys::path::get_separator().data() +
|
||||||
path + "." + DEFAULT_SUFFIX;
|
path + "." + DEFAULT_SUFFIX;
|
||||||
|
|
||||||
SMGR_LOG("Try to load the ns from: " + importedFile);
|
SMGR_LOG("Try to load the ns from: " + importedFile);
|
||||||
newBufOrErr = llvm::MemoryBuffer::getFile(importedFile);
|
auto newBufOrErr = llvm::MemoryBuffer::getFile(importedFile);
|
||||||
|
|
||||||
|
if (auto err = newBufOrErr.getError()) {
|
||||||
|
llvm::consumeError(llvm::errorCodeToError(err));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(*newBufOrErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newBufOrErr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
|
@ -83,16 +87,16 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
std::string importedFile;
|
std::string importedFile;
|
||||||
|
|
||||||
SMGR_LOG("Attempt to load namespace: " + name);
|
SMGR_LOG("Attempt to load namespace: " + name);
|
||||||
ErrorOrMemBufPtr newBufOrErr(findFileInLoadPath(name, importedFile));
|
MemBufPtr newBufOrErr(findFileInLoadPath(name, importedFile));
|
||||||
|
|
||||||
if (!newBufOrErr) {
|
if (newBufOrErr == nullptr) {
|
||||||
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
|
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
|
||||||
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
|
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
|
||||||
llvm::StringRef(msg));
|
llvm::StringRef(msg));
|
||||||
return MaybeNS::error(err);
|
return MaybeNS::error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bufferId = AddNewSourceBuffer(std::move(*newBufOrErr), importLoc);
|
auto bufferId = AddNewSourceBuffer(std::move(newBufOrErr), importLoc);
|
||||||
|
|
||||||
UNUSED(nsTable.insert_or_assign(name, bufferId));
|
UNUSED(nsTable.insert_or_assign(name, bufferId));
|
||||||
|
|
||||||
|
|
|
@ -249,147 +249,146 @@ int dumpAsObject(Namespace &ns) {
|
||||||
// failCommand.front().second->Print(llvm::errs(), "\n", false);
|
// failCommand.front().second->Print(llvm::errs(), "\n", false);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
return 0;
|
int main(int argc, char *argv[]) {
|
||||||
|
initCompiler();
|
||||||
|
registerSereneCLOptions();
|
||||||
|
|
||||||
|
cl::ParseCommandLineOptions(argc, argv, banner);
|
||||||
|
|
||||||
|
auto ctx = makeSereneContext();
|
||||||
|
auto userNS = makeNamespace(*ctx, "user", llvm::None);
|
||||||
|
|
||||||
|
applySereneCLOptions(*ctx);
|
||||||
|
|
||||||
|
// TODO: handle the outputDir by not forcing it. it should be
|
||||||
|
// default to the current working dir
|
||||||
|
if (outputDir == "-") {
|
||||||
|
llvm::errs() << "Error: The build directory is not set. Did you forget to "
|
||||||
|
"use '-b'?\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (emitAction) {
|
||||||
|
|
||||||
|
case Action::RunJIT: {
|
||||||
|
// TODO: Replace it by a proper jit configuration
|
||||||
|
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
// Just print out the raw AST
|
||||||
initCompiler();
|
case Action::DumpAST: {
|
||||||
registerSereneCLOptions();
|
ctx->setOperationPhase(CompilationPhase::Parse);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
cl::ParseCommandLineOptions(argc, argv, banner);
|
case Action::DumpSemantic: {
|
||||||
|
ctx->setOperationPhase(CompilationPhase::Analysis);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
auto ctx = makeSereneContext();
|
case Action::DumpSLIR: {
|
||||||
auto userNS = makeNamespace(*ctx, "user", llvm::None);
|
ctx->setOperationPhase(CompilationPhase::SLIR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
applySereneCLOptions(*ctx);
|
case Action::DumpMLIR: {
|
||||||
|
ctx->setOperationPhase(CompilationPhase::MLIR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: handle the outputDir by not forcing it. it should be
|
case Action::DumpLIR: {
|
||||||
// default to the current working dir
|
ctx->setOperationPhase(CompilationPhase::LIR);
|
||||||
if (outputDir == "-") {
|
break;
|
||||||
llvm::errs()
|
}
|
||||||
<< "Error: The build directory is not set. Did you forget to "
|
|
||||||
"use '-b'?\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (emitAction) {
|
case Action::DumpIR: {
|
||||||
|
ctx->setOperationPhase(CompilationPhase::IR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Action::RunJIT: {
|
case Action::CompileToObject: {
|
||||||
// TODO: Replace it by a proper jit configuration
|
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
||||||
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
break;
|
||||||
break;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Just print out the raw AST
|
case Action::Compile: {
|
||||||
case Action::DumpAST: {
|
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
||||||
ctx->setOperationPhase(CompilationPhase::Parse);
|
break;
|
||||||
break;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
case Action::DumpSemantic: {
|
default: {
|
||||||
ctx->setOperationPhase(CompilationPhase::Analysis);
|
llvm::errs() << "No action specified. TODO: Print out help here\n";
|
||||||
break;
|
return 1;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case Action::DumpSLIR: {
|
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
|
||||||
ctx->setOperationPhase(CompilationPhase::SLIR);
|
auto maybeNS = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Action::DumpMLIR: {
|
if (!maybeNS) {
|
||||||
ctx->setOperationPhase(CompilationPhase::MLIR);
|
throwErrors(*ctx, maybeNS.getError());
|
||||||
break;
|
return (int)std::errc::no_such_file_or_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Action::DumpLIR: {
|
auto ns = maybeNS.getValue();
|
||||||
ctx->setOperationPhase(CompilationPhase::LIR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Action::DumpIR: {
|
ctx->insertNS(ns);
|
||||||
ctx->setOperationPhase(CompilationPhase::IR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Action::CompileToObject: {
|
|
||||||
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Action::Compile: {
|
|
||||||
ctx->setOperationPhase(CompilationPhase::NoOptimization);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
llvm::errs() << "No action specified. TODO: Print out help here\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
|
|
||||||
auto maybeNS = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
|
|
||||||
|
|
||||||
if (!maybeNS) {
|
|
||||||
throwErrors(*ctx, maybeNS.getError());
|
|
||||||
return (int)std::errc::no_such_file_or_directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ns = maybeNS.getValue();
|
|
||||||
|
|
||||||
ctx->insertNS(ns);
|
|
||||||
|
|
||||||
switch (emitAction) {
|
|
||||||
case Action::DumpAST:
|
|
||||||
case Action::DumpSemantic: {
|
|
||||||
auto ast = ns->getTree();
|
|
||||||
llvm::outs() << exprs::astToString(&ast) << "\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Action::DumpSLIR:
|
|
||||||
case Action::DumpMLIR:
|
|
||||||
case Action::DumpLIR: {
|
|
||||||
ns->dump();
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
case Action::DumpIR: {
|
|
||||||
auto maybeModule = ns->compileToLLVM();
|
|
||||||
|
|
||||||
if (!maybeModule) {
|
|
||||||
llvm::errs() << "Failed to generate the IR.\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
maybeModule.getValue()->dump();
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Action::RunJIT: {
|
|
||||||
auto maybeJIT = JIT::make(*ns);
|
|
||||||
if (!maybeJIT) {
|
|
||||||
// TODO: panic in here: "Couldn't creat the JIT!"
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
auto jit = std::move(maybeJIT.getValue());
|
|
||||||
|
|
||||||
if (jit->invoke("main")) {
|
|
||||||
llvm::errs() << "Faild to invoke the 'main' function.\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
llvm::outs() << "Done!";
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Action::Compile:
|
|
||||||
case Action::CompileToObject: {
|
|
||||||
return dumpAsObject(*ns);
|
|
||||||
};
|
|
||||||
default: {
|
|
||||||
llvm::errs() << "Action is not supported yet!\n";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
switch (emitAction) {
|
||||||
|
case Action::DumpAST:
|
||||||
|
case Action::DumpSemantic: {
|
||||||
|
auto ast = ns->getTree();
|
||||||
|
llvm::outs() << exprs::astToString(&ast) << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Action::DumpSLIR:
|
||||||
|
case Action::DumpMLIR:
|
||||||
|
case Action::DumpLIR: {
|
||||||
|
ns->dump();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case Action::DumpIR: {
|
||||||
|
auto maybeModule = ns->compileToLLVM();
|
||||||
|
|
||||||
|
if (!maybeModule) {
|
||||||
|
llvm::errs() << "Failed to generate the IR.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
maybeModule.getValue()->dump();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case Action::RunJIT: {
|
||||||
|
auto maybeJIT = JIT::make(*ns);
|
||||||
|
if (!maybeJIT) {
|
||||||
|
// TODO: panic in here: "Couldn't creat the JIT!"
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto jit = std::move(maybeJIT.getValue());
|
||||||
|
|
||||||
|
if (jit->invoke("main")) {
|
||||||
|
llvm::errs() << "Faild to invoke the 'main' function.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
llvm::outs() << "Done!";
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case Action::Compile:
|
||||||
|
case Action::CompileToObject: {
|
||||||
|
return dumpAsObject(*ns);
|
||||||
|
};
|
||||||
|
default: {
|
||||||
|
llvm::errs() << "Action is not supported yet!\n";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue