Skip to content

Commit

Permalink
Add flang
Browse files Browse the repository at this point in the history
  • Loading branch information
IsabelParedes committed Jan 3, 2025
1 parent 7e1a958 commit 3782f5a
Show file tree
Hide file tree
Showing 9 changed files with 2,116 additions and 0 deletions.
12 changes: 12 additions & 0 deletions recipes/recipes/flang_emscripten-wasm32/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

set -ex

cmake -S llvm -B _fbuild -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DLLVM_DEFAULT_TARGET_TRIPLE=wasm32-unknown-emscripten \
-DLLVM_TARGETS_TO_BUILD=WebAssembly \
-DLLVM_ENABLE_PROJECTS="clang;flang;mlir"
cmake --build _fbuild
cmake --build _fbuild --target install
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
From 9832ab8489970b1b872ada88e21e2cea9f4925bd Mon Sep 17 00:00:00 2001
From: serge-sans-paille <[email protected]>
Date: Fri, 5 Jul 2024 22:45:47 +0200
Subject: [PATCH 1/7] Instructions for building a functional Flang cross
compiler

---
README.wasm.md | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 README.wasm.md

diff --git a/README.wasm.md b/README.wasm.md
new file mode 100644
index 000000000000..4f6e64a4766d
--- /dev/null
+++ b/README.wasm.md
@@ -0,0 +1,31 @@
+# Building Flang as a WASM cross-compiler
+
+From the branch ``feature/flang-wasm`` of
+https://github.com/serge-sans-paille/llvm-project.
+
+This work is inspired by https://gws.phd/posts/fortran_wasm/.
+
+## Building the compiler itself
+
+```
+$ cmake -S llvm -B _fbuild -GNinja \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=_finstall \
+ -DLLVM_DEFAULT_TARGET_TRIPLE=wasm32-unknown-emscripten \
+ -DLLVM_TARGETS_TO_BUILD=WebAssembly \
+ -DLLVM_ENABLE_PROJECTS="clang;flang;mlir"
+$ cmake --build _fbuild
+$ cmake --build _fbuild --target install
+```
+
+## Building Flang runtmine
+
+Assuming you have ``emcmake`` available somewhere in your ``PATH``.
+
+```
+$ emcmake cmake -S flang/runtime -B _fbuild_runtime -GNinja \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=_finstall
+$ cmake --build _fbuild_runtime
+$ cmake --build _fbuild_runtime --target install
+```
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
From 50a109a4f3a37b27daf5b05503edc5a918f6a826 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <[email protected]>
Date: Tue, 18 Jun 2024 22:19:09 +0200
Subject: [PATCH 2/7] Minimal WASM support for flang

Original patch from https://gws.phd/posts/fortran_wasm/
---
flang/lib/Optimizer/CodeGen/Target.cpp | 41 ++++++++++++++++++++++++++
1 file changed, 41 insertions(+)

diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp
index 25141102a8c4..715daefc0ba5 100644
--- a/flang/lib/Optimizer/CodeGen/Target.cpp
+++ b/flang/lib/Optimizer/CodeGen/Target.cpp
@@ -1055,6 +1055,44 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
};
} // namespace

+//===----------------------------------------------------------------------===//
+// WebAssembly (wasm32) target specifics.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct TargetWasm32 : public GenericTarget<TargetWasm32> {
+ using GenericTarget::GenericTarget;
+
+ static constexpr int defaultWidth = 32;
+
+ CodeGenSpecifics::Marshalling
+ complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
+ assert(fir::isa_real(eleTy));
+ CodeGenSpecifics::Marshalling marshal;
+ // Use a type that will be translated into LLVM as:
+ // { t, t } struct of 2 eleTy, byval, align 4
+ auto structTy =
+ mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
+ marshal.emplace_back(fir::ReferenceType::get(structTy),
+ AT{/*alignment=*/4, /*byval=*/true});
+ return marshal;
+ }
+
+ CodeGenSpecifics::Marshalling
+ complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
+ assert(fir::isa_real(eleTy));
+ CodeGenSpecifics::Marshalling marshal;
+ // Use a type that will be translated into LLVM as:
+ // { t, t } struct of 2 eleTy, sret, align 4
+ auto structTy =
+ mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
+ marshal.emplace_back(fir::ReferenceType::get(structTy),
+ AT{/*alignment=*/4, /*byval=*/false, /*sret=*/true});
+ return marshal;
+ }
+};
+} // namespace
+
// Instantiate the overloaded target instance based on the triple value.
// TODO: Add other targets to this file as needed.
std::unique_ptr<fir::CodeGenSpecifics>
@@ -1110,6 +1148,9 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
case llvm::Triple::ArchType::loongarch64:
return std::make_unique<TargetLoongArch64>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
+ case llvm::Triple::ArchType::wasm32:
+ return std::make_unique<TargetWasm32>(
+ ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
}
TODO(mlir::UnknownLoc::get(ctx), "target not implemented");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
From a15e14e27fdbb7e874f51d02e06b4c6c9349f798 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <[email protected]>
Date: Wed, 10 Jul 2024 22:42:19 +0200
Subject: [PATCH 3/7] Specialize Flang to target WASM

Many values were explicitly encoded under the assumation that host and target have
the same architecture.
---
.../Optimizer/Builder/Runtime/RTBuilder.h | 31 ++++++++++---------
.../flang/Optimizer/Support/DataLayout.h | 16 ++++++++++
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 8 +++--
3 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 845ba385918d..adc6479f9cbf 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -22,6 +22,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Runtime/reduce.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
@@ -85,7 +86,7 @@ using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *);
auto voidTy = fir::LLVMPointerType::get( \
context, mlir::IntegerType::get(context, 8)); \
auto size_tTy = \
- mlir::IntegerType::get(context, 8 * sizeof(std::size_t)); \
+ mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_SIZE_T); \
auto refTy = fir::ReferenceType::get(f(context)); \
return mlir::FunctionType::get( \
context, {refTy, size_tTy, refTy, refTy, size_tTy, size_tTy}, \
@@ -113,13 +114,13 @@ static constexpr TypeBuilderFunc getModel();
template <>
constexpr TypeBuilderFunc getModel<unsigned int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(unsigned int));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_UINT);
};
}
template <>
constexpr TypeBuilderFunc getModel<short int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(short int));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_SHORT);
};
}
template <>
@@ -136,7 +137,7 @@ constexpr TypeBuilderFunc getModel<const short int *>() {
template <>
constexpr TypeBuilderFunc getModel<int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(int));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_INT);
};
}
template <>
@@ -182,13 +183,13 @@ constexpr TypeBuilderFunc getModel<const char32_t *>() {
template <>
constexpr TypeBuilderFunc getModel<char>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(char));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_CHAR);
};
}
template <>
constexpr TypeBuilderFunc getModel<signed char>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(signed char));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_SCHAR);
};
}
template <>
@@ -205,7 +206,7 @@ constexpr TypeBuilderFunc getModel<const signed char *>() {
template <>
constexpr TypeBuilderFunc getModel<char16_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(char16_t));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_CHAR16);
};
}
template <>
@@ -218,7 +219,7 @@ constexpr TypeBuilderFunc getModel<char16_t *>() {
template <>
constexpr TypeBuilderFunc getModel<char32_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(char32_t));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_CHAR32);
};
}
template <>
@@ -231,7 +232,7 @@ constexpr TypeBuilderFunc getModel<char32_t *>() {
template <>
constexpr TypeBuilderFunc getModel<unsigned char>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(unsigned char));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_UCHAR);
};
}
template <>
@@ -259,7 +260,7 @@ constexpr TypeBuilderFunc getModel<void **>() {
template <>
constexpr TypeBuilderFunc getModel<long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(long));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_LONG);
};
}
template <>
@@ -280,7 +281,7 @@ constexpr TypeBuilderFunc getModel<const long *>() {
template <>
constexpr TypeBuilderFunc getModel<long long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(long long));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_LONGLONG);
};
}
template <>
@@ -308,13 +309,13 @@ constexpr TypeBuilderFunc getModel<const long long *>() {
template <>
constexpr TypeBuilderFunc getModel<unsigned long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(unsigned long));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_ULONG);
};
}
template <>
constexpr TypeBuilderFunc getModel<unsigned long long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return mlir::IntegerType::get(context, 8 * sizeof(unsigned long long));
+ return mlir::IntegerType::get(context, 8 * FLANG_TARGET_SIZEOF_ULONGLONG);
};
}
template <>
@@ -434,13 +435,13 @@ constexpr TypeBuilderFunc getModel<const std::complex<double> *>() {
template <>
constexpr TypeBuilderFunc getModel<c_float_complex_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return fir::ComplexType::get(context, sizeof(float));
+ return fir::ComplexType::get(context, FLANG_TARGET_SIZEOF_FLOAT);
};
}
template <>
constexpr TypeBuilderFunc getModel<c_double_complex_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
- return fir::ComplexType::get(context, sizeof(double));
+ return fir::ComplexType::get(context, FLANG_TARGET_SIZEOF_DOUBLE);
};
}
template <>
diff --git a/flang/include/flang/Optimizer/Support/DataLayout.h b/flang/include/flang/Optimizer/Support/DataLayout.h
index d21576bb95f7..5372039d8702 100644
--- a/flang/include/flang/Optimizer/Support/DataLayout.h
+++ b/flang/include/flang/Optimizer/Support/DataLayout.h
@@ -23,6 +23,22 @@ namespace llvm {
class DataLayout;
}

+constexpr size_t FLANG_TARGET_SIZEOF_UINT = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_INT = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_SHORT = 2;
+constexpr size_t FLANG_TARGET_SIZEOF_CHAR = 1;
+constexpr size_t FLANG_TARGET_SIZEOF_SCHAR = 1;
+constexpr size_t FLANG_TARGET_SIZEOF_UCHAR = 1;
+constexpr size_t FLANG_TARGET_SIZEOF_CHAR16 = 2;
+constexpr size_t FLANG_TARGET_SIZEOF_CHAR32 = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_LONG = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_LONGLONG = 8;
+constexpr size_t FLANG_TARGET_SIZEOF_ULONG = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_ULONGLONG = 8;
+constexpr size_t FLANG_TARGET_SIZEOF_SIZE_T = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_FLOAT = 4;
+constexpr size_t FLANG_TARGET_SIZEOF_DOUBLE = 8;
+
namespace fir::support {
/// Create an mlir::DataLayoutSpecInterface attribute from an llvm::DataLayout
/// and set it on the provided mlir::ModuleOp.
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index f9ea92a843b2..ca72d67400b0 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -909,7 +909,8 @@ getMalloc(fir::AllocMemOp op, mlir::ConversionPatternRewriter &rewriter) {
return mlir::SymbolRefAttr::get(userMalloc);
mlir::OpBuilder moduleBuilder(
op->getParentOfType<mlir::ModuleOp>().getBodyRegion());
- auto indexType = mlir::IntegerType::get(op.getContext(), 64);
+ auto indexType =
+ mlir::IntegerType::get(op.getContext(), 8 * FLANG_TARGET_SIZEOF_SIZE_T);
auto mallocDecl = moduleBuilder.create<mlir::LLVM::LLVMFuncOp>(
op.getLoc(), mallocName,
mlir::LLVM::LLVMFunctionType::get(getLlvmPtrType(op.getContext()),
@@ -976,8 +977,11 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
size = rewriter.create<mlir::LLVM::MulOp>(
loc, ity, size, integerCast(loc, rewriter, ity, opnd));
heap->setAttr("callee", getMalloc(heap, rewriter));
+ auto szt_ty = mlir::IntegerType::get(rewriter.getContext(),
+ 8 * FLANG_TARGET_SIZEOF_SIZE_T);
+ auto size_szt = integerCast(loc, rewriter, szt_ty, size);
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
- heap, ::getLlvmPtrType(heap.getContext()), size, heap->getAttrs());
+ heap, ::getLlvmPtrType(heap.getContext()), size_szt, heap->getAttrs());
return mlir::success();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
From d248b70f49ae63689962b0f8bd0cab8e2f35a592 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <[email protected]>
Date: Fri, 26 Jul 2024 07:34:39 +0000
Subject: [PATCH 4/7] [Flang][Runtime] Explicitly convert shift value to
SubscriptValue (#99822)

Shift value are within the range of SubscriptValue but the API forces
them to 64bits. This assumption doesn't hold for 32bit machine, so add
an explicit cast.
---
flang/runtime/transformational.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/flang/runtime/transformational.cpp b/flang/runtime/transformational.cpp
index cf1e61c0844d..b6b204be4418 100644
--- a/flang/runtime/transformational.cpp
+++ b/flang/runtime/transformational.cpp
@@ -508,7 +508,8 @@ void RTDEF(CshiftVector)(Descriptor &result, const Descriptor &source,
SubscriptValue lb{sourceDim.LowerBound()};
for (SubscriptValue j{0}; j < extent; ++j) {
SubscriptValue resultAt{1 + j};
- SubscriptValue sourceAt{lb + (j + shift) % extent};
+ SubscriptValue sourceAt{
+ lb + static_cast<SubscriptValue>(j + shift) % extent};
if (sourceAt < lb) {
sourceAt += extent;
}
@@ -619,7 +620,7 @@ void RTDEF(EoshiftVector)(Descriptor &result, const Descriptor &source,
}
SubscriptValue lb{source.GetDimension(0).LowerBound()};
for (SubscriptValue j{1}; j <= extent; ++j) {
- SubscriptValue sourceAt{lb + j - 1 + shift};
+ SubscriptValue sourceAt{lb + j - 1 + static_cast<SubscriptValue>(shift)};
if (sourceAt >= lb && sourceAt < lb + extent) {
CopyElement(result, &j, source, &sourceAt, terminator);
} else if (boundary) {
Loading

0 comments on commit 3782f5a

Please sign in to comment.