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

VarDecl to Parser lowering #760

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions include/vast/Dialect/Parser/Ops.td
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,19 @@ def Parse_Ref
}];
}

// TODO: Types should match
def Parse_Assign
: Parser_Op< "assign" >
, Arguments< (ins
Parser_AnyDataType:$value,
Parser_AnyDataType:$target
) >
{
let summary = "Assignment to referenced value.";

let assemblyFormat = [{
$value `to` $target attr-dict functional-type($value, $target)
}];
}

#endif // VAST_DIALECT_PARSER_OPS
96 changes: 42 additions & 54 deletions include/vast/Util/Terminator.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-present, Trail of Bits, Inc.

Check notice on line 1 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

Run clang-format on include/vast/Util/Terminator.hpp

File include/vast/Util/Terminator.hpp does not conform to Custom style guidelines. (lines 71, 79)

#pragma once

Expand All @@ -6,104 +6,92 @@

VAST_RELAX_WARNINGS
#include <mlir/IR/Block.h>
#include <mlir/IR/Operation.h>
#include <mlir/IR/OpDefinition.h>
#include <mlir/IR/Operation.h>
VAST_UNRELAX_WARNINGS

#include <limits>
#include <optional>
#include <type_traits>

namespace vast
{
namespace detail
{
namespace vast {
namespace detail {

template< typename self_t >
struct terminator_base
{
auto &self() { return static_cast< self_t & >( *this ); }
auto &self() const { return static_cast< const self_t & >( *this ); }
auto &self() { return static_cast< self_t & >(*this); }

auto &self() const { return static_cast< const self_t & >(*this); }

template< typename T >
T cast() const
{
if ( !self().has_value() )
T cast() const {
if (!self().has_value()) {
return {};
return mlir::dyn_cast< T >( self().op_ptr() );
}
return mlir::dyn_cast< T >(self().op_ptr());
}

template< typename T >
T op() const
{
T op() const {
auto out = self().template cast< T >();
VAST_ASSERT( out );
VAST_ASSERT(out);
return out;
}

template< typename ... Args >
bool is_one_of()
{
return self().has_value() && (mlir::isa< Args >( self().op_ptr() ) || ... );
template< typename... Args >
bool is_one_of() {
return self().has_value() && (mlir::isa< Args >(self().op_ptr()) || ...);
}

static bool has( mlir::Block &block )
{
if ( std::distance( block.begin(), block.end() ) == 0 )
static bool has(block_t &block) {

Check failure on line 47 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:47:29 [clang-diagnostic-error]

unknown type name 'block_t'; did you mean 'clock_t'?
if (std::distance(block.begin(), block.end()) == 0) {

Check failure on line 48 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:48:40 [clang-diagnostic-error]

member reference base type 'clock_t' (aka 'long') is not a structure or union

Check failure on line 48 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:48:55 [clang-diagnostic-error]

member reference base type 'clock_t' (aka 'long') is not a structure or union
return false;
return self_t::is( &block.back() );
}
return self_t::is(&block.back());

Check failure on line 51 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:51:41 [clang-diagnostic-error]

member reference base type 'clock_t' (aka 'long') is not a structure or union
}

static self_t get( mlir::Block &block )
{
if ( !has( block ) )
static self_t get(block_t &block) {

Check failure on line 54 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:54:31 [clang-diagnostic-error]

unknown type name 'block_t'; did you mean 'clock_t'?
if (!has(block)) {
return self_t{};
}
return self_t{ &block.back() };

Check failure on line 58 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:58:38 [clang-diagnostic-error]

member reference base type 'clock_t' (aka 'long') is not a structure or union
}

};
} // detail
} // namespace detail

static inline bool is_terminator( mlir::Operation *op )
{
static inline bool is_terminator(operation op) {

Check failure on line 63 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:63:38 [clang-diagnostic-error]

unknown type name 'operation'; did you mean 'mlir::Operation'?
return op->hasTrait< mlir::OpTrait::IsTerminator >();

Check failure on line 64 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:64:18 [clang-diagnostic-error]

member reference type 'mlir::Operation' is not a pointer; did you mean to use '.'?
}

struct hard_terminator_t : std::optional< mlir::Operation * >,
detail::terminator_base< hard_terminator_t >
struct hard_terminator
: std::optional< operation >

Check failure on line 68 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:68:26 [clang-diagnostic-error]

use of undeclared 'operator>'

Check failure on line 68 in include/vast/Util/Terminator.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

include/vast/Util/Terminator.hpp:68:26 [clang-diagnostic-error]

use of undeclared identifier 'operation'; did you mean 'operator'?
, detail::terminator_base< hard_terminator >
{
mlir::Operation *op_ptr() const { return **this; }

static bool is( mlir::Operation *op )
{
return is_terminator( op );
}
operation op_ptr() const { return **this; }
static bool is(operation op) { return is_terminator(op); }
};


struct any_terminator_t : std::optional< Operation * >,
detail::terminator_base< any_terminator_t >
struct any_terminator
: std::optional< operation >
, detail::terminator_base< any_terminator >
{
mlir::Operation *op_ptr() const { return **this; }

static bool is( mlir::Operation *op )
{
return is_terminator( op ) || core::is_soft_terminator( op );
operation op_ptr() const { return **this; }
static bool is(operation op) {
return is_terminator(op) || core::is_soft_terminator(op);
}

};

template< typename op_t >
struct terminator_t : std::optional< Operation * >,
detail::terminator_base< terminator_t< op_t > >
struct terminator
: std::optional< operation >
, detail::terminator_base< terminator< op_t > >
{
using impl = detail::terminator_base< terminator_t< op_t > >;
using impl = detail::terminator_base< terminator< op_t > >;

mlir::Operation *op_ptr() const { return **this; }
operation op_ptr() const { return **this; }

static bool is( mlir::Operation *op )
{
return mlir::isa< op_t >( op );
}
static bool is(operation op) { return mlir::isa< op_t >(op); }

op_t op() { return this->impl::template op< op_t >(); }
};
Expand Down
4 changes: 2 additions & 2 deletions lib/vast/Conversion/FromHL/EmitLazyRegions.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-present, Trail of Bits, Inc.

Check notice on line 1 in lib/vast/Conversion/FromHL/EmitLazyRegions.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

Run clang-format on lib/vast/Conversion/FromHL/EmitLazyRegions.cpp

File lib/vast/Conversion/FromHL/EmitLazyRegions.cpp does not conform to Custom style guidelines. (lines 42)

#include "vast/Util/Warnings.hpp"

Expand Down Expand Up @@ -39,7 +39,7 @@

auto lazy_op = [&]
{
if (!terminator_t< hl::ValueYieldOp >::get(side.front()))
if (!terminator< hl::ValueYieldOp >::get(side.front()))
{
return mk_lazy_op(mlir::NoneType::get(rewriter.getContext()));
}
Expand Down Expand Up @@ -93,7 +93,7 @@
VAST_PATTERN_CHECK(conv::size(op.getCondRegion()) == 1,
"Unsupported shape of cond region of hl::CondOp:\n{0}", op);

auto yield = terminator_t< hl::CondYieldOp >::get(cond_block);
auto yield = terminator< hl::CondYieldOp >::get(cond_block);
VAST_PATTERN_CHECK(yield, "Was not able to retrieve cond yield, {0}.", op);

rewriter.inlineBlockBefore(&cond_block, op, std::nullopt);
Expand Down
8 changes: 4 additions & 4 deletions lib/vast/Conversion/FromHL/ToLLCF.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-present, Trail of Bits, Inc.

Check notice on line 1 in lib/vast/Conversion/FromHL/ToLLCF.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

Run clang-format on lib/vast/Conversion/FromHL/ToLLCF.cpp

File lib/vast/Conversion/FromHL/ToLLCF.cpp does not conform to Custom style guidelines. (lines 66)

#include "vast/Conversion/Passes.hpp"

Expand Down Expand Up @@ -63,7 +63,7 @@
}

auto cond_yield(mlir::Block *block) {
auto cond_yield = mlir::cast< hl::CondYieldOp >(hard_terminator_t::get(*block).value());
auto cond_yield = mlir::cast< hl::CondYieldOp >(hard_terminator::get(*block).value());
VAST_CHECK(cond_yield, "Block does not have a hl::CondYieldOp as terminator.");
return cond_yield;
}
Expand Down Expand Up @@ -98,7 +98,7 @@

namespace pattern {
auto get_cond_yield(mlir::Block &block) {
return terminator_t< hl::CondYieldOp >::get(block).op();
return terminator< hl::CondYieldOp >::get(block).op();
}

// We do not use patterns, because for example `hl.continue` in for loop is kinda tricky
Expand Down Expand Up @@ -214,7 +214,7 @@

static logical_result
tie(auto &&bld, auto loc, mlir::Block &from, mlir::Block &to) {
if (!empty(from) && any_terminator_t::get(from)) {
if (!empty(from) && any_terminator::get(from)) {
return mlir::success();
}

Expand Down Expand Up @@ -287,7 +287,7 @@
// verification.
// We are using any_terminator as it can have for example `hl.return`
// or other soft terminator that will get eliminated in this pass.
if (!any_terminator_t::has(*tail_block)) {
if (!any_terminator::has(*tail_block)) {
bld.guarded_at_end(tail_block, [&]() {
bld->template create< ll::ScopeRet >(op.getLoc());
});
Expand Down
2 changes: 1 addition & 1 deletion lib/vast/Conversion/Generic/LowerValueCategories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ namespace vast::conv {
if (!body)
return logical_result::success();

auto yield = terminator_t< yield_op_t >::get(*body);
auto yield = terminator< yield_op_t >::get(*body);
VAST_PATTERN_CHECK(yield, "Expected yield in: {0}", op);

rewriter.inlineBlockBefore(body, op);
Expand Down
89 changes: 87 additions & 2 deletions lib/vast/Conversion/Parser/ToParser.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

Check notice on line 1 in lib/vast/Conversion/Parser/ToParser.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter (19, 22.04)

Run clang-format on lib/vast/Conversion/Parser/ToParser.cpp

File lib/vast/Conversion/Parser/ToParser.cpp does not conform to Custom style guidelines. (lines 497, 529, 542, 545, 546, 547, 575, 579, 580, 583, 587)
#include "vast/Util/Warnings.hpp"

#include "vast/Conversion/Parser/Passes.hpp"
Expand All @@ -21,6 +21,7 @@
#include "vast/Conversion/TypeConverters/TypeConvertingPattern.hpp"

#include "vast/Util/Common.hpp"
#include "vast/Util/Terminator.hpp"

#include "vast/Dialect/Parser/Ops.hpp"
#include "vast/Dialect/Parser/Types.hpp"
Expand Down Expand Up @@ -493,13 +494,97 @@
}
};

struct ExprConversion
: parser_conversion_pattern_base< hl::ExprOp >
{
using op_t = hl::ExprOp;
using base = parser_conversion_pattern_base< op_t >;
using base::base;

using adaptor_t = typename op_t::Adaptor;

logical_result matchAndRewrite(
op_t op, adaptor_t adaptor, conversion_rewriter &rewriter
) const override {
auto body = op.getBody();
if (!body) {
return mlir::failure();
}

auto yield = terminator< hl::ValueYieldOp >::get(*body);
VAST_PATTERN_CHECK(yield, "Expected yield in: {0}", op);

rewriter.inlineBlockBefore(body, op);
rewriter.replaceOp(op, yield.op().getResult());
rewriter.eraseOp(yield.op());

return mlir::success();
}

static void legalize(parser_conversion_config &cfg) {
cfg.target.addLegalOp< mlir::UnrealizedConversionCastOp >();
xlauko marked this conversation as resolved.
Show resolved Hide resolved
}
};

struct VarDeclConversion
: parser_conversion_pattern_base< hl::VarDeclOp >
{
using op_t = hl::VarDeclOp;
using base = parser_conversion_pattern_base< op_t >;
using base::base;

using adaptor_t = typename op_t::Adaptor;

logical_result matchAndRewrite(
op_t op, adaptor_t adaptor, conversion_rewriter &rewriter
) const override {
auto maybe = to_mlir_type(data_type::maybedata, rewriter.getContext());
/* auto decl = */ rewriter.create< pr::Decl >(op.getLoc(), op.getSymName(), maybe);

if (auto &init_region = op.getInitializer(); !init_region.empty()) {
VAST_PATTERN_CHECK(init_region.getBlocks().size() == 1, "Expected single block in: {0}", op);
auto &init_block = init_region.back();
auto yield = terminator< hl::ValueYieldOp >::get(init_block);
VAST_PATTERN_CHECK(yield, "Expected yield in: {0}", op);

rewriter.inlineBlockBefore(&init_block, op);
rewriter.setInsertionPointAfter(op);
auto ref = rewriter.create< pr::Ref >(op.getLoc(), maybe, op.getSymName());
auto value = rewriter.create< mlir::UnrealizedConversionCastOp >(
yield.op().getLoc(), maybe, yield.op().getResult()
);
rewriter.create< pr::Assign >(yield.op().getLoc(), value.getResult(0), ref);
rewriter.eraseOp(yield.op());
}

rewriter.eraseOp(op);
return mlir::success();
}

static void legalize(parser_conversion_config &cfg) {
cfg.target.addLegalOp< pr::Decl, pr::Ref, pr::Assign >();
cfg.target.addLegalOp< mlir::UnrealizedConversionCastOp >();
}
};

using operation_conversions = util::type_list<
ToNoParse< hl::ConstantOp >,
ToNoParse< hl::ImplicitCastOp >,
ToNoParse< hl::CmpOp>, ToNoParse< hl::FCmpOp >,
ToNoParse< hl::CmpOp >, ToNoParse< hl::FCmpOp >,
// Integer arithmetic
ToNoParse< hl::MulIOp >,
ToNoParse< hl::DivSOp >, ToNoParse< hl::DivUOp >,
ToNoParse< hl::RemSOp >, ToNoParse< hl::RemUOp >,
// Floating point arithmetic
ToNoParse< hl::AddFOp >, ToNoParse< hl::SubFOp >,
ToNoParse< hl::MulFOp >, ToNoParse< hl::DivFOp >,
ToNoParse< hl::RemFOp >,
// Other operations
ExprConversion,
FuncConversion,
ParamConversion,
// DeclRefConversion,
DeclRefConversion,
VarDeclConversion,
ReturnConversion,
CallConversion
>;
Expand Down
2 changes: 1 addition & 1 deletion lib/vast/Conversion/ToLLVM/IRsToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@ namespace vast::conv::irstollvm
if (!body)
return logical_result::success();

auto yield = terminator_t< yield_op_t >::get(*body);
auto yield = terminator< yield_op_t >::get(*body);
VAST_PATTERN_CHECK(yield, "Expected yield in: {0}", op);

rewriter.inlineBlockBefore(body, op);
Expand Down
Loading