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

Obliterate hl-structs-to-llvm conversion pass. #436

Merged
merged 6 commits into from
Nov 6, 2023
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
2 changes: 1 addition & 1 deletion include/vast/Conversion/Common/Passes.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/Conversion/Common/Passes.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (17, 22.04)

Run clang-format on include/vast/Conversion/Common/Passes.hpp

File include/vast/Conversion/Common/Passes.hpp does not conform to Custom style guidelines. (lines 226)

#pragma once

Expand Down Expand Up @@ -223,7 +223,7 @@
mlir::LowerToLLVMOptions llvm_options{ &ctx };
derived_t::set_llvm_opts(llvm_options);

auto tc = llvm_type_converter(&ctx, llvm_options, &dl_analysis);
auto tc = llvm_type_converter(getOperation(), &ctx, llvm_options, &dl_analysis);
auto cfg = config(
rewrite_pattern_set(&ctx), derived_t::create_conversion_target(ctx, tc), tc
);
Expand Down
3 changes: 0 additions & 3 deletions include/vast/Conversion/Passes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ namespace vast

std::unique_ptr< mlir::Pass > createHLToLLVarsPass();

std::unique_ptr< mlir::Pass > createHLStructsToLLVMPass();

std::unique_ptr< mlir::Pass > createHLEmitLazyRegionsPass();

std::unique_ptr< mlir::Pass > createHLToLLFuncPass();
Expand All @@ -79,7 +77,6 @@ namespace vast

static inline void build_to_llvm_pipeline(mlir::PassManager &pm)
{
pm.addPass(createHLStructsToLLVMPass());
pm.addPass(createIRsToLLVMPass());
pm.addPass(createCoreToLLVMPass());
}
Expand Down
13 changes: 0 additions & 13 deletions include/vast/Conversion/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,6 @@ def HLToLLFunc : Pass<"vast-hl-to-ll-func", "mlir::ModuleOp"> {
];
}

def HLStructsToLLVM : Pass<"vast-hl-structs-to-llvm", "mlir::ModuleOp"> {
let summary = "Transform hl.struct into llvm types without applying ABI conversions.";
let description = [{
This pass is still a work in progress.
}];

let constructor = "vast::createHLStructsToLLVMPass()";
let dependentDialects = [
"mlir::LLVM::LLVMDialect",
"vast::core::CoreDialect"
];
}

def HLEmitLazyRegions : Pass<"vast-hl-to-lazy-regions", "mlir::ModuleOp"> {
let summary = "Transform hl operations that have short-circuiting into lazy operations.";
let description = [{
Expand Down
68 changes: 65 additions & 3 deletions include/vast/Conversion/TypeConverters/LLVMTypeConverter.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022, Trail of Bits, Inc.

Check notice on line 1 in include/vast/Conversion/TypeConverters/LLVMTypeConverter.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter (17, 22.04)

Run clang-format on include/vast/Conversion/TypeConverters/LLVMTypeConverter.hpp

File include/vast/Conversion/TypeConverters/LLVMTypeConverter.hpp does not conform to Custom style guidelines. (lines 187, 188, 204, 224, 232, 233, 234, 241, 242)

#pragma once

Expand All @@ -10,6 +10,7 @@
VAST_UNRELAX_WARNINGS

#include "vast/Dialect/HighLevel/HighLevelTypes.hpp"
#include "vast/Dialect/HighLevel/HighLevelUtils.hpp"
#include "vast/Util/Maybe.hpp"

#include "vast/Conversion/TypeConverters/TypeConverter.hpp"
Expand Down Expand Up @@ -174,16 +175,77 @@
}
};

template< typename self_t >
struct LLVMStruct
{
private:
self_t &self() { return static_cast< self_t & >(*this); }

public:
maybe_types_t convert_field_types(mlir_type t) {
auto field_types = self().get_field_types(t);
if (!field_types)
return {};

mlir::SmallVector< mlir_type, 4 > out;
for (auto field_type : *field_types) {
auto c = self().convert_type_to_type(field_type);
VAST_ASSERT(c);
out.push_back(*c);
}
return { std::move(out) };
}

template< typename op_t >
auto convert_recordlike() {
// We need this prototype to handle recursive types.
return [&](op_t t, mlir::SmallVectorImpl< mlir_type > &out,
mlir::ArrayRef< mlir_type > stack) -> logical_result {
auto core = mlir::LLVM::LLVMStructType::getIdentified(
t.getContext(), t.getName());
// Last element is `t`.
auto bt = stack.drop_back();

if (core.isOpaque() && std::ranges::find(bt, t) == bt.end()) {
if (auto body = convert_field_types(t)) {
// Multithreading may cause some issues?
auto status = core.setBody(*body, false);
VAST_ASSERT(mlir::succeeded(status));
}
}
out.push_back(core);
return mlir::success();
};
}
};

// Requires that the named types *always* map to llvm struct types.
// TODO(lukas): What about type aliases.
struct FullLLVMTypeConverter : LLVMTypeConverter
struct FullLLVMTypeConverter : LLVMTypeConverter,
LLVMStruct< FullLLVMTypeConverter >
{
using base = LLVMTypeConverter;

vast_module mod;

template< typename... Args >
FullLLVMTypeConverter(Args &&...args) : base(std::forward< Args >(args)...) {
addConversion([&](hl::RecordType t) { return convert_record_type(t); });
FullLLVMTypeConverter(vast_module mod,
Args &&...args)
: base(std::forward< Args >(args)...),
mod(mod) {
addConversion([&](hl::ElaboratedType t) { return convert_elaborated_type(t); });
addConversion(convert_recordlike< hl::RecordType >());
}

auto get_field_types(mlir_type t) -> std::optional< gap::generator< mlir_type > > {
if (!mlir::isa< hl::RecordType >(t))
return {};
auto def = hl::definition_of(t, mod);
// Nothing found, leave the structure opaque.
if (!def) {
return {};
}
return { hl::field_types(*def) };
}

maybe_type_t convert_elaborated_type(hl::ElaboratedType t) {
Expand Down
6 changes: 4 additions & 2 deletions lib/vast/Conversion/Common/IRsToLLVM.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/Common/IRsToLLVM.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter (17, 22.04)

Run clang-format on lib/vast/Conversion/Common/IRsToLLVM.cpp

File lib/vast/Conversion/Common/IRsToLLVM.cpp does not conform to Custom style guidelines. (lines 46, 47, 329)

#include "vast/Conversion/Passes.hpp"

Expand Down Expand Up @@ -42,7 +42,9 @@
{
using ignore_patterns = util::type_list<
ignore_pattern< hl::DeclRefOp >,
ignore_pattern< hl::PredefinedExpr >
ignore_pattern< hl::PredefinedExpr >,
erase_pattern< hl::StructDeclOp >,
erase_pattern< hl::TypeDeclOp >
>;

struct ll_struct_gep : base_pattern< ll::StructGEPOp >
Expand Down Expand Up @@ -324,7 +326,7 @@
for (auto [i, element] : llvm::enumerate(init_list.getElements()))
{
auto e_type = LLVM::LLVMPointerType::get(element.getType());
std::vector< mlir::LLVM::GEPArg > indices { 0ul, i + 1 };
std::vector< mlir::LLVM::GEPArg > indices { 0ul, i };

auto gep = rewriter.template create< LLVM::GEPOp >(
element.getLoc(), e_type, ptr, indices);
Expand Down
1 change: 0 additions & 1 deletion lib/vast/Conversion/FromHL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
add_vast_conversion_library(HighLevelConversionPasses
ToLLCF.cpp
EmitLazyRegions.cpp
StructsToLLVM.cpp
ToLLGEPs.cpp
ToLLVars.cpp
ToLLFunc.cpp
Expand Down
184 changes: 0 additions & 184 deletions lib/vast/Conversion/FromHL/StructsToLLVM.cpp

This file was deleted.

10 changes: 10 additions & 0 deletions test/vast/Conversion/Common/IRsToLLVM/struct-a.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %vast-cc1 -vast-emit-mlir=hl %s -o - | %vast-opt --vast-hl-lower-types --vast-hl-to-ll-cf --vast-hl-to-ll-vars --vast-irs-to-llvm | %file-check %s

struct X { int x; };

int main()
{
// CHECK: {{.*}} = llvm.alloca {{.*}} x !llvm.struct<"X", (i32)> : (i64) -> !llvm.ptr<struct<"X", (i32)>>
struct X x;
return 0;
}
11 changes: 11 additions & 0 deletions test/vast/Conversion/Common/IRsToLLVM/struct-b.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %vast-cc1 -vast-emit-mlir=hl %s -o - | %vast-opt --vast-hl-lower-types --vast-hl-to-ll-cf --vast-hl-to-ll-vars --vast-irs-to-llvm | %file-check %s

struct Y;
struct X { int x; struct Y *y; };

int main()
{
// CHECK: {{.*}} = llvm.alloca {{.*}} x !llvm.struct<"X", (i32, ptr<struct<"Y", opaque>>)> : (i64) -> !llvm.ptr<struct<"X", (i32, ptr<struct<"Y", opaque>>)>>
struct X x = { 2, 0 };
return 0;
}
18 changes: 18 additions & 0 deletions test/vast/Conversion/Common/IRsToLLVM/struct-c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %vast-cc1 -vast-emit-mlir=hl %s -o - | %vast-opt --vast-hl-lower-types --vast-hl-to-ll-cf --vast-hl-to-ll-vars --vast-irs-to-llvm | %file-check %s

struct Y;

struct X { const int x; struct Y *y; };

struct Y { const float x; };

int main()
{
// CHECK: {{.*}} = llvm.alloca {{.*}} x !llvm.struct<"X", (i32, ptr<struct<"Y", (f32)>>)> : (i64) -> !llvm.ptr<struct<"X", (i32, ptr<struct<"Y", (f32)>>)>>
struct X x = { 2, 0 };

// CHECK: {{.*}} = llvm.alloca {{.*}} x !llvm.struct<"Y", (f32)> : (i64) -> !llvm.ptr<struct<"Y", (f32)>>
struct Y y = { 2.0f };

return 0;
}
Loading