Skip to content

Commit

Permalink
Improve test framework (#202)
Browse files Browse the repository at this point in the history
* Start implementing new test suite

* Extend

* Catch exceptions properly

* Extend test runner

* Extend test runner

* Cleanup
  • Loading branch information
marcauberer authored Sep 13, 2022
1 parent 90e6dec commit 103eb08
Show file tree
Hide file tree
Showing 22 changed files with 426 additions and 1,149 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
java-version: 11

- name: Uninstall potential other versions of LLVM
run: sudo apt-get purge llvm-12 clang-12 llvm-11 clang-11 llvm-10 clang-10
run: sudo apt-get purge llvm-14 clang-14 llvm-13 clang-13 llvm-12 clang-12

- name: Setup latest GCC and build dependencies
run: |
Expand Down
23 changes: 3 additions & 20 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
f<int> main() {
printf("Test: %s", "Hi " + "World!");
}

/*import "std/data/vector" as vec;
import "std/data/pair" as pair;

Expand All @@ -21,12 +17,12 @@ f<int> main() {
server.serve("/test", "Hello World!");
}*/

/*import "std/runtime/string_rt" as _rt_str;
import "std/runtime/string_rt" as _rt_str;

f<int> main() {
//_rt_str::String s = _rt_str::String("Test");
//printf("%s", s.getRaw());
// Plus
// Plus
printf("Result: %s\n", "Hello " + "World!");
string s1 = "Hello " + "World!";
printf("Result: %s\n", s1);
Expand All @@ -38,17 +34,4 @@ f<int> main() {
string s3 = 2 * 'c' * 7;
printf("Result: %s\n", s3);
//printf("%s", s1 + s2);
}*/

/*public f<int> src(int x, int y) {
return x + (x | -x);
}

public f<int> tgt(int x) {
return x & (x - 1);
}

f<int> main() {
printf("Src: %d\n", src(21, 10));
printf("Tgt: %d\n", tgt(21));
}*/
}
5 changes: 2 additions & 3 deletions src/analyzer/AnalyzerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
#include <util/CommonUtil.h>
#include <util/CompilerWarning.h>

AnalyzerVisitor::AnalyzerVisitor(std::shared_ptr<llvm::LLVMContext> context, std::shared_ptr<llvm::IRBuilder<>> builder,
AnalyzerVisitor::AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder,
const ThreadFactory &threadFactory, const SourceFile &sourceFile, CliOptions &options,
bool requiresMainFct, bool isStdFile)
: context(std::move(context)), builder(std::move(builder)), threadFactory(threadFactory), requiresMainFct(requiresMainFct),
isStdFile(isStdFile) {
: context(context), builder(builder), threadFactory(threadFactory), requiresMainFct(requiresMainFct), isStdFile(isStdFile) {
// Retrieve symbol table
this->currentScope = this->rootScope = sourceFile.symbolTable.get();

Expand Down
9 changes: 4 additions & 5 deletions src/analyzer/AnalyzerVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ class SourceFile;
class AnalyzerVisitor : public AstVisitor {
public:
// Constructors
explicit AnalyzerVisitor(std::shared_ptr<llvm::LLVMContext> context, std::shared_ptr<llvm::IRBuilder<>> builder,
const ThreadFactory &threadFactory, const SourceFile &sourceFile, CliOptions &options,
bool requiresMainFct, bool stdFile);
explicit AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, const ThreadFactory &threadFactory,
const SourceFile &sourceFile, CliOptions &options, bool requiresMainFct, bool stdFile);

// Friend classes
friend class OpRuleManager;
Expand Down Expand Up @@ -109,8 +108,8 @@ class AnalyzerVisitor : public AstVisitor {

private:
// Members
std::shared_ptr<llvm::LLVMContext> context;
std::shared_ptr<llvm::IRBuilder<>> builder;
const llvm::LLVMContext *context;
const llvm::IRBuilder<> *builder;
std::unique_ptr<OpRuleManager> opRuleManager;
const ThreadFactory &threadFactory;
bool requiresMainFct = true;
Expand Down
80 changes: 47 additions & 33 deletions src/dependency/SourceFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
#include <visualizer/ASTVisualizerVisitor.h>
#include <visualizer/CSTVisualizerVisitor.h>

SourceFile::SourceFile(CliOptions &options, SourceFile *parent, std::string name, const std::string &filePath, bool stdFile)
: name(std::move(name)), filePath(filePath), stdFile(stdFile), parent(parent), options(options) {
SourceFile::SourceFile(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory,
LinkerInterface &linker, CliOptions &options, SourceFile *parent, std::string name,
const std::string &filePath, bool stdFile)
: context(context), builder(builder), threadFactory(threadFactory), linker(linker), name(std::move(name)), filePath(filePath),
stdFile(stdFile), parent(parent), options(options) {
this->objectFilePath = options.outputDir + FileUtil::DIR_SEPARATOR + FileUtil::getFileName(filePath) + ".o";

// Deduce fileName and fileDir
Expand Down Expand Up @@ -57,7 +60,7 @@ SourceFile::SourceFile(CliOptions &options, SourceFile *parent, std::string name
symbolTable = std::make_shared<SymbolTable>(nullptr, SCOPE_GLOBAL, parent == nullptr, true);
}

void SourceFile::visualizeCST(std::string *output) {
void SourceFile::visualizeCST() {
// Only execute if enabled
if (!options.dumpCST && !options.testMode)
return;
Expand All @@ -69,7 +72,7 @@ void SourceFile::visualizeCST(std::string *output) {

// Visualize the imported source files
for (const auto &[_, sourceFile] : dependencies)
sourceFile.first->visualizeCST(output);
sourceFile.first->visualizeCST();

// Generate dot code for this source file
CSTVisualizerVisitor visualizerVisitor(antlrCtx.lexer, antlrCtx.parser);
Expand Down Expand Up @@ -112,7 +115,7 @@ void SourceFile::buildAST() {
antlrCtx.parser->reset();
}

void SourceFile::visualizeAST(std::string *output) {
void SourceFile::visualizeAST() {
// Only execute if enabled
if (!options.dumpAST && !options.testMode)
return;
Expand All @@ -124,7 +127,7 @@ void SourceFile::visualizeAST(std::string *output) {

// Visualize the imported source files
for (const auto &[_, sourceFile] : dependencies)
sourceFile.first->visualizeAST(output);
sourceFile.first->visualizeAST();

// Generate dot code for this source file
ASTVisualizerVisitor visualizerVisitor(ast.get());
Expand Down Expand Up @@ -168,12 +171,11 @@ void SourceFile::preAnalyze() {
}
}

void SourceFile::analyze(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
const ThreadFactory &threadFactory) {
void SourceFile::analyze() {
// Analyze the imported source files
for (const auto &[importName, sourceFile] : dependencies) {
// Analyze the imported source file
sourceFile.first->analyze(context, builder, threadFactory);
sourceFile.first->analyze();

// Mount symbol table to the current one
sourceFile.first->symbolTable->setParent(symbolTable.get());
Expand All @@ -191,8 +193,7 @@ void SourceFile::analyze(const std::shared_ptr<llvm::LLVMContext> &context, cons
antlrCtx.parser->reset();
}

void SourceFile::reAnalyze(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
ThreadFactory &threadFactory) {
void SourceFile::reAnalyze() {
// Re-Analyze this source file
bool repetitionRequired;
unsigned int analyzeCount = 0;
Expand All @@ -207,7 +208,7 @@ void SourceFile::reAnalyze(const std::shared_ptr<llvm::LLVMContext> &context, co

// Re-analyze the imported source files
for (const auto &[importName, sourceFile] : dependencies)
sourceFile.first->reAnalyze(context, builder, threadFactory);
sourceFile.first->reAnalyze();

// Save the JSON version in the compiler output
compilerOutput.symbolTableString = symbolTable->toJSON().dump(2);
Expand All @@ -219,11 +220,10 @@ void SourceFile::reAnalyze(const std::shared_ptr<llvm::LLVMContext> &context, co
} // GCOV_EXCL_STOP
}

void SourceFile::generate(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
ThreadFactory &threadFactory, LinkerInterface &linker) {
void SourceFile::generate() {
// Generate the imported source files
for (const auto &[_, sourceFile] : dependencies)
sourceFile.first->generate(context, builder, threadFactory, linker);
sourceFile.first->generate();

// Generate this source file
generator = std::make_shared<GeneratorVisitor>(context, builder, threadFactory, linker, options, *this, objectFilePath);
Expand All @@ -238,6 +238,8 @@ void SourceFile::generate(const std::shared_ptr<llvm::LLVMContext> &context, con
"this as a bug on GitHub.");
} while (repetitionRequired);

antlrCtx.parser->reset();

// Save the JSON version in the compiler output
compilerOutput.irString = generator->getIRString();

Expand All @@ -247,34 +249,43 @@ void SourceFile::generate(const std::shared_ptr<llvm::LLVMContext> &context, con
generator->dumpIR();
std::cout << "\n";
} // GCOV_EXCL_STOP
}

void SourceFile::optimize() {
// Skip this stage if optimization is disabled
if (options.optLevel < 1 || options.optLevel > 5)
return;

// Optimize IR code
if (options.optLevel >= 1 && options.optLevel <= 5) {
generator->optimize();
// Optimize the imported source files
for (const auto &[_, sourceFile] : dependencies)
sourceFile.first->optimize();

// Save the JSON version in the compiler output
compilerOutput.irOptString = generator->getIRString();
generator->optimize();

// Dump optimized IR code
if (options.dumpIR) { // GCOV_EXCL_START
std::cout << "\nOptimized IR code:\n";
generator->dumpIR();
std::cout << "\n";
} // GCOV_EXCL_STOP
}
// Save the JSON version in the compiler output
compilerOutput.irOptString = generator->getIRString();

// Dump optimized IR code
if (options.dumpIR) { // GCOV_EXCL_START
std::cout << "\nOptimized IR code:\n";
generator->dumpIR();
std::cout << "\n";
} // GCOV_EXCL_STOP
}

void SourceFile::emitObjectFile() {
// Optimize the imported source files
for (const auto &[_, sourceFile] : dependencies)
sourceFile.first->emitObjectFile();

// Dump assembly code
if (options.dumpAssembly) { // GCOV_EXCL_START
std::cout << "\nAssembly code:\n";
generator->dumpAsm();
} // GCOV_EXCL_STOP

// Emit object file
// Emit object file and add object file to the linker interface
generator->emit();

antlrCtx.parser->reset();

// Add object file to the linker interface
linker.addObjectFilePath(objectFilePath);

// Print warning if verifier is disabled
Expand All @@ -291,7 +302,10 @@ void SourceFile::addDependency(const AstNode *declAstNode, const std::string &na
throw SemanticError(declAstNode->codeLoc, CIRCULAR_DEPENDENCY, "Circular import detected while importing '" + filePath + "'");

// Add the dependency
dependencies.insert({name, {std::make_shared<SourceFile>(options, this, name, filePath, stdFile), declAstNode}});
dependencies.insert(
{name,
{std::make_shared<SourceFile>(context, builder, threadFactory, linker, options, this, name, filePath, stdFile),
declAstNode}});
}

bool SourceFile::isAlreadyImported(const std::string &filePathSearch) const {
Expand Down
31 changes: 19 additions & 12 deletions src/dependency/SourceFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ struct CompilerOutput {
class SourceFile {
public:
// Constructors
explicit SourceFile(CliOptions &options, SourceFile *parent, std::string name, const std::string &filePath, bool stdFile);
explicit SourceFile(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory,
LinkerInterface &linker, CliOptions &options, SourceFile *parent, std::string name,
const std::string &filePath, bool stdFile);

// Public methods
void visualizeCST(std::string *output);
void visualizeCST();
void buildAST();
void visualizeAST(std::string *output);
void visualizeAST();
void preAnalyze();
void analyze(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
const ThreadFactory &threadFactory);
void reAnalyze(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
ThreadFactory &threadFactory);
void generate(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
ThreadFactory &threadFactory, LinkerInterface &linker);
void addDependency(const AstNode *declAstNode, const std::string &name, const std::string &filePath,
bool stdFile);
void analyze();
void reAnalyze();
void generate();
void optimize();
void emitObjectFile();
void addDependency(const AstNode *declAstNode, const std::string &name, const std::string &filePath, bool stdFile);
[[nodiscard]] bool isAlreadyImported(const std::string &filePathSearch) const;

// Fields
// Public fields
std::string name;
std::string fileName;
std::string filePath;
Expand All @@ -78,4 +78,11 @@ class SourceFile {
std::shared_ptr<AnalyzerVisitor> analyzer;
std::shared_ptr<GeneratorVisitor> generator;
std::map<std::string, std::pair<std::shared_ptr<SourceFile>, const AstNode *>> dependencies;

private:
// Private fields
llvm::LLVMContext *context;
llvm::IRBuilder<> *builder;
ThreadFactory &threadFactory;
LinkerInterface &linker;
};
3 changes: 1 addition & 2 deletions src/generator/GeneratorVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
#include <llvm/Target/TargetOptions.h>
#include <llvm/Transforms/IPO/AlwaysInliner.h>

GeneratorVisitor::GeneratorVisitor(const std::shared_ptr<llvm::LLVMContext> &context,
const std::shared_ptr<llvm::IRBuilder<>> &builder, ThreadFactory &threadFactory,
GeneratorVisitor::GeneratorVisitor(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory,
const LinkerInterface &linker, const CliOptions &cliOptions, const SourceFile &sourceFile,
const std::string &objectFile)
: objectFile(objectFile), cliOptions(cliOptions), linker(linker), context(context), builder(builder),
Expand Down
12 changes: 6 additions & 6 deletions src/generator/GeneratorVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#include <ast/AstNodes.h>
#include <ast/AstVisitor.h>

#include <generator/StdFunctionManager.h>
#include <generator/OpRuleConversionsManager.h>
#include <generator/StdFunctionManager.h>
#include <symbol/ScopePath.h>
#include <symbol/SymbolType.h>

Expand Down Expand Up @@ -39,9 +39,9 @@ class Struct;
class GeneratorVisitor : public AstVisitor {
public:
// Constructors
explicit GeneratorVisitor(const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder,
ThreadFactory &threadFactory, const LinkerInterface &linker, const CliOptions &cliOptions,
const SourceFile &sourceFile, const std::string &objectFile);
explicit GeneratorVisitor(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory,
const LinkerInterface &linker, const CliOptions &cliOptions, const SourceFile &sourceFile,
const std::string &objectFile);

// Friend classes
friend class StdFunctionManager;
Expand Down Expand Up @@ -112,8 +112,8 @@ class GeneratorVisitor : public AstVisitor {
const CliOptions &cliOptions;
const LinkerInterface &linker;
bool requiresMainFct = true;
std::shared_ptr<llvm::LLVMContext> context;
std::shared_ptr<llvm::IRBuilder<>> builder;
llvm::LLVMContext *context;
llvm::IRBuilder<> *builder;
std::unique_ptr<llvm::Module> module;
std::unique_ptr<llvm::DIBuilder> diBuilder;
SymbolTable *currentScope;
Expand Down
6 changes: 3 additions & 3 deletions src/generator/OpRuleConversionsManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include <util/CodeLoc.h>

OpRuleConversionsManager::OpRuleConversionsManager(GeneratorVisitor *generator) : generator(generator) {
builder = generator->builder.get();
context = generator->context.get();
builder = generator->builder;
context = generator->context;
stdFunctionManager = generator->stdFunctionManager.get();
}

Expand Down Expand Up @@ -1535,4 +1535,4 @@ llvm::Value *OpRuleConversionsManager::propagateValueToStringObject(SymbolTable
assert(anonEntry != nullptr);
anonEntry->updateAddress(thisPtr);
return thisPtr;
}
}
4 changes: 2 additions & 2 deletions src/generator/StdFunctionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include <generator/GeneratorVisitor.h>

StdFunctionManager::StdFunctionManager(GeneratorVisitor *generator) {
context = generator->context.get();
builder = generator->builder.get();
context = generator->context;
builder = generator->builder;
module = generator->module.get();
}

Expand Down
Loading

0 comments on commit 103eb08

Please sign in to comment.