Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce semantizer module for an operation tree verification #124

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "compiler/optree/operation.hpp"
#include "compiler/optree/program.hpp"

namespace optree {
namespace semantizer {

class Semantizer {
public:
Semantizer() = delete;
Semantizer(const Semantizer &) = delete;
Semantizer(Semantizer &&) = delete;
~Semantizer() = delete;

static void process(const Program &program);
static void process(const Operation::Ptr &op);
};

} // namespace semantizer
} // namespace optree
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <string>

#include "compiler/optree/operation.hpp"
#include "compiler/utils/error_buffer.hpp"

#include "compiler/backend/optree/semantizer/semantizer_error.hpp"

namespace optree {
namespace semantizer {

struct SemantizerContext {
ErrorBuffer errors;

void pushError(const Operation::Ptr &op, const std::string &message = {}) {
errors.push<SemantizerError>(op, message);
}

void pushOpError(const Operation::Ptr &op, const std::string &message = {}) {
errors.push<SemantizerError>(op, std::string(op->name) + " operation " + message);
}
};

} // namespace semantizer
} // namespace optree
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <string>

#include "compiler/optree/operation.hpp"
#include "compiler/utils/base_error.hpp"

namespace optree {
namespace semantizer {

class SemantizerError : public BaseError {
public:
using BaseError::BaseError;

explicit SemantizerError(const Operation::Ptr &op, const std::string &message = {}) : BaseError(op->ref, message){};
~SemantizerError() override = default;
};

} // namespace semantizer
} // namespace optree
106 changes: 106 additions & 0 deletions compiler/include/compiler/backend/optree/semantizer/traits.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#pragma once

#include "compiler/optree/operation.hpp"
#include "compiler/optree/types.hpp"

Check failure

Code scanning / clang-tidy

included header types.hpp is not used directly [misc-include-cleaner,-warnings-as-errors] Error

included header types.hpp is not used directly [misc-include-cleaner,-warnings-as-errors]

#include "compiler/backend/optree/semantizer/semantizer_context.hpp"

namespace optree {
namespace semantizer {

class TraitVerifier {
const Operation::Ptr &op;
SemantizerContext &ctx;
bool acc;

public:
TraitVerifier() = delete;
TraitVerifier(const TraitVerifier &) = delete;
TraitVerifier(TraitVerifier &&) = delete;
~TraitVerifier() = default;

TraitVerifier(const Operation::Ptr &op, SemantizerContext &ctx) : op(op), ctx(ctx), acc(true){};

bool verified() const {
return acc;
}

template <typename TraitType, typename... Args>
TraitVerifier &verify(Args... args) {
TraitType trait(op, ctx);
acc &= trait.verify(std::forward<Args>(args)...);
}
};

class Trait {
const Operation::Ptr &op;
SemantizerContext &ctx;

public:
Trait() = delete;
Trait(const Trait &) = delete;
Trait(Trait &&) = delete;
~Trait() = default;

Trait(const Operation::Ptr &op, SemantizerContext &ctx) : op(op), ctx(ctx){};

bool verify() {
ctx.pushOpError(op) << "was not registered for verification: " << op->name;

Check failure

Code scanning / clang-tidy

invalid operands to binary expression ('void' and 'const char[38]') [clang-diagnostic-error] Error

invalid operands to binary expression ('void' and 'const char[38]') [clang-diagnostic-error]
return false;
}
};

struct HasOperands : Trait {
using Trait::Trait;
bool verify(size_t numOperands) {

Check failure

Code scanning / clang-tidy

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors]
if (op->numOperands() != numOperands) {

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]
ctx.pushOpError(op) << "must have " << numOperands " operands";

Check failure

Code scanning / clang-tidy

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error] Error

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

expected ';' after expression [clang-diagnostic-error] Error

expected ';' after expression [clang-diagnostic-error]
return false;
}
return true;
}
}

Check failure

Code scanning / clang-tidy

expected ';' after struct [clang-diagnostic-error] Error

expected ';' after struct [clang-diagnostic-error]

struct HasResults : Trait {
using Trait::Trait;
bool verify(size_t numResults) {

Check failure

Code scanning / clang-tidy

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors]
if (op->numResults() == numResults)

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]
return true;
ctx.pushOpError(op) << "must have " << numResults " results";

Check failure

Code scanning / clang-tidy

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error] Error

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

expected ';' after expression [clang-diagnostic-error] Error

expected ';' after expression [clang-diagnostic-error]
return false;
}
}

Check failure

Code scanning / clang-tidy

expected ';' after struct [clang-diagnostic-error] Error

expected ';' after struct [clang-diagnostic-error]

struct HasInwards : Trait {
using Trait::Trait;
bool verify(size_t numInwards) {

Check failure

Code scanning / clang-tidy

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors]
if (op->numInwards() == numInwards)

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]
return true;
ctx.pushOpError(op) << "must have " << numInwards " inwards";

Check failure

Code scanning / clang-tidy

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'ctx' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error] Error

'op' is a private member of 'optree::semantizer::Trait' [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error] Error

invalid operands to binary expression ('void' and 'const char[11]') [clang-diagnostic-error]

Check failure

Code scanning / clang-tidy

expected ';' after expression [clang-diagnostic-error] Error

expected ';' after expression [clang-diagnostic-error]
return false;
}
}

Check failure

Code scanning / clang-tidy

expected ';' after struct [clang-diagnostic-error] Error

expected ';' after struct [clang-diagnostic-error]

struct HasAttributes : Trait {
using Trait::Trait;
bool verify(size_t numAttrs) {

Check failure

Code scanning / clang-tidy

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors]
if (op->numAttrs() == numAttrs)
return true;
ctx.pushOpError(op) << "must have " << numAttrs " attributes";
return false;
}
}

template <typename T>
struct HasNthAttrOfType : Trait {
using Trait::Trait;
bool verify(size_t index) {

Check failure

Code scanning / clang-tidy

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "size_t" is directly included [misc-include-cleaner,-warnings-as-errors]
if (op->attr(index).is<T>())
return true;
ctx.pushOpError(op) << "must have attribute #" << index " of other type";
return false;
}
}

} // namespace semantizer
} // namespace optree
5 changes: 3 additions & 2 deletions compiler/include/compiler/optree/base_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#include "compiler/utils/source_ref.hpp"

#define OPTREE_ADAPTOR_HELPER(BASE_ADAPTOR_CLASS, OPERATION_NAME) \
using BASE_ADAPTOR_CLASS::BASE_ADAPTOR_CLASS; \
using BASE_ADAPTOR_CLASS::operator bool; \
using Base = BASE_ADAPTOR_CLASS; \
using Base::Base; \
using Base::operator bool; \
static std::string_view getOperationName() { \
return (OPERATION_NAME); \
} \
Expand Down
15 changes: 12 additions & 3 deletions compiler/include/compiler/utils/base_error.hpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
#pragma once

#include <sstream>
#include <stdexcept>
#include <string>

#include "compiler/utils/source_ref.hpp"

class BaseError : public std::exception {
std::string what_str;
std::stringstream messageStr;

public:
BaseError(const utils::SourceRef &ref, const std::string &message);
BaseError(const std::string &message);
BaseError(BaseError &&) = default;
~BaseError() = default;

BaseError(const BaseError &other);
explicit BaseError(const utils::SourceRef &ref, const std::string &message = {});
explicit BaseError(const std::string &message = {});

virtual const char *what() const noexcept;

template <typename T>
std::stringstream &operator<<(const T &value) {
return messageStr << value;
}
};
38 changes: 38 additions & 0 deletions compiler/lib/backend/optree/semantizer/semantizer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "semantizer/semantizer.hpp"

#include "compiler/optree/adaptors.hpp"
#include "compiler/optree/operation.hpp"
#include "compiler/optree/program.hpp"

#include "semantizer/semantizer_context.hpp"

#define VERIFY(ADAPTOR_CLASS_NAME) \
template <> \
void verify<ADAPTOR_CLASS_NAME>(const Operation::Ptr &op, SemantizerContext &ctx)

using namespace optree;
using namespace optree::semantizer;

template <typename AdaptorType>
void verify(const Operation::Ptr &op, SemantizerContext &ctx) {

Check failure

Code scanning / clang-tidy

parameter 'op' is unused [misc-unused-parameters,-warnings-as-errors] Error

parameter 'op' is unused [misc-unused-parameters,-warnings-as-errors]

Check failure

Code scanning / clang-tidy

parameter 'ctx' is unused [misc-unused-parameters,-warnings-as-errors] Error

parameter 'ctx' is unused [misc-unused-parameters,-warnings-as-errors]
std::terminate();

Check failure

Code scanning / clang-tidy

no header providing "std::terminate" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "std::terminate" is directly included [misc-include-cleaner,-warnings-as-errors]
}

VERIFY(ModuleOp) {
}

void verify(const Operation::Ptr &op, SemantizerContext &ctx) {
if (op->is<ModuleOp>())
return verify<ModuleOp>(op, ctx);
}

void Semantizer::process(const Program &program) {
process(program.root);
}

void Semantizer::process(const Operation::Ptr &op) {
Fixed Show fixed Hide fixed
SemantizerContext ctx;

if (!ctx.errors.empty())
throw ctx.errors;
}
12 changes: 7 additions & 5 deletions compiler/lib/utils/base_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@

using utils::SourceRef;

BaseError::BaseError(const BaseError &other) : BaseError() {
messageStr << other.messageStr.view();
}

BaseError::BaseError(const SourceRef &ref, const std::string &message) {
std::stringstream str;
str << "In line " << ref.line << " in column " << ref.column << " error:\n" << message;
what_str = str.str();
messageStr << "In line " << ref.line << " in column " << ref.column << " error:\n" << message;
}

BaseError::BaseError(const std::string &message) {
what_str = "Error:\n" + message;
messageStr << "Error:\n" + message;
}

const char *BaseError::what() const noexcept {
return what_str.c_str();
return messageStr.view().data();
}
Loading