forked from emscripten-forge/recipes
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7e1a958
commit 3782f5a
Showing
9 changed files
with
2,116 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
48 changes: 48 additions & 0 deletions
48
...emscripten-wasm32/patches/0001-Instructions-for-building-a-functional-Flang-cross-c.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
+``` |
69 changes: 69 additions & 0 deletions
69
recipes/recipes/flang_emscripten-wasm32/patches/0002-Minimal-WASM-support-for-flang.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} |
206 changes: 206 additions & 0 deletions
206
recipes/recipes/flang_emscripten-wasm32/patches/0003-Specialize-Flang-to-target-WASM.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
|
36 changes: 36 additions & 0 deletions
36
...emscripten-wasm32/patches/0004-Flang-Runtime-Explicitly-convert-shift-value-to-Subs.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { |
Oops, something went wrong.