llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.15k stars 12.03k forks source link

Is there any plan to make flang available on 32-bit platforms? #57621

Open licy183 opened 2 years ago

licy183 commented 2 years ago

From flang's README.md:

The code has been compiled on AArch64, x86_64 and ppc64le servers with CentOS7, Ubuntu18.04, Rhel, MacOs, Mojave, XCode and Apple Clang version 10.0.1.

I tried to build flang for i686-pc-linux-gnu, and some error happened as the following.

error: constant expression evaluates to 9223372036854775807 which cannot be narrowed to type 'std::size_t' (aka 'unsigned int') [-Wc++11-narrowing]
    std::size_t max{std::numeric_limits<std::int64_t>::max()};
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: insert an explicit cast to silence this issue
    std::size_t max{std::numeric_limits<std::int64_t>::max()};
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    static_cast<size_t>(                    )
1 error generated.

It seems that flang is not available on 32-bit platforms, so is there any plan to support them?

brad0 commented 2 years ago

From elsewhere in Flang it looks like i386 is a supported target. So it looks like a oversight from a lack of CI. Looks like with the use of size_t that would build on *BSD/i386 but not Linux/i386 or other OS's not using 64-bit size_t on 32-bit archs.

You shouldn't have removed any context as to where that error is from.

That looks like line 34 of flang/runtime/command.cpp.

licy183 commented 2 years ago

From elsewhere in Flang it looks like i386 is a supported target. So it looks like a oversight from a lack of CI. Looks like with the use of size_t that would build on *BSD/i386 but not Linux/i386 or other OS's not using 64-bit size_t on 32-bit archs.

I'm using cross-compiling. Build platform is x86_64/Linux, host platform is i686/Linux and target platforms are X86;AArch64;ARM.

You shouldn't have removed any context as to where that error is from.

That looks like line 34 of flang/runtime/command.cpp.

Sorry for that. I cast some variables and then it can be built successfully. The files I modified are as following.

diff -uNr a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -70,6 +70,14 @@
     return mlir::IntegerType::get(context, 8 * sizeof(int));
   };
 }
+#ifndef __LP64__
+template <>
+constexpr TypeBuilderFunc getModel<unsigned int>() {
+  return [](mlir::MLIRContext *context) -> mlir::Type {
+    return mlir::IntegerType::get(context, 8 * sizeof(unsigned int));
+  };
+}
+#endif // __LP64__
 template <>
 constexpr TypeBuilderFunc getModel<int &>() {
   return [](mlir::MLIRContext *context) -> mlir::Type {
diff -uNr a/flang/lib/Evaluate/constant.cpp b/flang/lib/Evaluate/constant.cpp
--- a/flang/lib/Evaluate/constant.cpp
+++ b/flang/lib/Evaluate/constant.cpp
@@ -293,7 +293,11 @@
     return count;
   } else {
     std::size_t copied{0};
+#ifndef __LP64__
+    std::size_t elementBytes{static_cast<std::size_t>(length_ * sizeof(decltype(values_[0])))};
+#else
     std::size_t elementBytes{length_ * sizeof(decltype(values_[0]))};
+#endif // __LP64__
     ConstantSubscripts sourceSubscripts{source.lbounds()};
     while (copied < count) {
       auto *dest{&values_.at(SubscriptsToOffset(resultSubscripts) * length_)};
--- a/flang/runtime/command.cpp
+++ b/flang/runtime/command.cpp
@@ -31,7 +31,11 @@
   if constexpr (sizeof(std::size_t) < sizeof(std::int64_t)) {
     return static_cast<std::int64_t>(length);
   } else {
+#ifndef __LP64__
+    std::size_t max{static_cast<std::size_t>(std::numeric_limits<std::int64_t>::max())};
+#else
     std::size_t max{std::numeric_limits<std::int64_t>::max()};
+#endif // __LP64__
     return length > max ? 0 // Just fail.
                         : static_cast<std::int64_t>(length);
   }
diff -uNr a/flang/runtime/derived.cpp b/flang/runtime/derived.cpp
--- a/flang/runtime/derived.cpp
+++ b/flang/runtime/derived.cpp
@@ -188,9 +188,15 @@
       SubscriptValue extent[maxRank];
       const typeInfo::Value *bounds{comp.bounds()};
       for (int dim{0}; dim < comp.rank(); ++dim) {
+#ifndef __LP64__
+        SubscriptValue lb{static_cast<SubscriptValue>(bounds[2 * dim].GetValue(&descriptor).value_or(0))};
+        SubscriptValue ub{static_cast<SubscriptValue>(
+            bounds[2 * dim + 1].GetValue(&descriptor).value_or(0))};
+#else
         SubscriptValue lb{bounds[2 * dim].GetValue(&descriptor).value_or(0)};
         SubscriptValue ub{
             bounds[2 * dim + 1].GetValue(&descriptor).value_or(0)};
+#endif // __LP64__
         extent[dim] = ub >= lb ? ub - lb + 1 : 0;
       }
       StaticDescriptor<maxRank, true, 0> staticDescriptor;
diff -uNr a/flang/runtime/transformational.cpp b/flang/runtime/transformational.cpp
--- a/flang/runtime/transformational.cpp
+++ b/flang/runtime/transformational.cpp
@@ -191,7 +191,11 @@
   SubscriptValue lb{sourceDim.LowerBound()};
   for (SubscriptValue j{0}; j < extent; ++j) {
     SubscriptValue resultAt{1 + j};
+#ifndef __LP64__
+    SubscriptValue sourceAt{lb + (j + static_cast<SubscriptValue>(shift)) % extent};
+#else
     SubscriptValue sourceAt{lb + (j + shift) % extent};
+#endif // __LP64__
     if (sourceAt < lb) {
       sourceAt += extent;
     }
@@ -302,7 +306,11 @@
   }
   SubscriptValue lb{source.GetDimension(0).LowerBound()};
   for (SubscriptValue j{1}; j <= extent; ++j) {
+#ifndef __LP64__
+    SubscriptValue sourceAt{lb + j - 1 + static_cast<SubscriptValue>(shift)};
+#else
     SubscriptValue sourceAt{lb + j - 1 + shift};
+#endif // __LP64__
     if (sourceAt >= lb && sourceAt < lb + extent) {
       CopyElement(result, &j, source, &sourceAt, terminator);
     } else if (boundary) {
banach-space commented 2 years ago

Hi @licy183 , thanks for bringing this up!

From flang's README.md

AFAIK, that document is not being been kept up to date :(

From elsewhere in Flang it looks like i386 is a supported target.

Yes, there's a handful of tests, e.g. in convert-to-llvm-target.fir.

So it looks like a oversight from a lack of CI.

Yes and no. This is a "patches welcome" situation :) Simply put, i386 is not a priority for any of the organisations contributing to LLVM Flang. In principle, any target supported by LLVM (i.e. one of LLVM hardware backends) should be supported by LLVM Flang. But the devil is always in the fine details ;-)

IMHO, the README file is misleading and should be updated to better reflect the situation in LLVM Flang.

HTH, -Andrzej

klausler commented 2 years ago

There's two questions here, really: (1) can the f18 compiler itself be built as a 32-bit program?, and (2) can f18 target a 32-bit architecture and can its runtime support library be built for that target?

One might have a fighting chance at accomplishing (2) with a fair amount of work; but there are lots of areas where 64-bit integers are assumed to be used on the target for sizes, counts, strides, offsets, &c. For example, there's only a 64-bit definition of the single descriptor format. Adapting the runtime and lowering for a 32-bit target would be a major project (maybe a year for a capable developer) and would also be a major complication going forward supporting a code base that would work in both modes.

I don't see much point attempting question (1) without having a solution for (2).

DavidSpickett commented 2 months ago

Note that since the last update, CMake was updated to explicitly block 32 bit builds: https://github.com/llvm/llvm-project/commit/8e20cb6bb8d0b6cf91cc25204eb29620a5040ba4