[flang-commits] [flang] [flang] Use the target index width during FIR-to-LLVM lowering (PR #226424)

Anutosh Bhat via flang-commits flang-commits at lists.llvm.org
Fri Sep 25 03:08:06 PDT 2026


https://github.com/anutosh491 created https://github.com/llvm/llvm-project/pull/226424

I'm interested in Flang cross-compilation to wasm32/wasm64 (as my [RFC](https://discourse.llvm.org/t/rfc-proposing-an-interactive-fortran-workflow-with-flang-using-jupyter-notebooks/89116) here says).

While working on it I noticed that FIR-to-LLVM lowering still hard-coded `i64` as its aggregate/index type, even when the target uses 32-bit indices.

This patch:

- uses the index width configured by `LowerToLLVMOptions`;
- materializes target conversions before emitting LLVM integer operations;

This is a general cross-compilation fix and does not contain any Wasm-specific logic. Tested with `fir-opt` for i386, x86-64 and other targets.

>From c9d7ebd024f4ba917f6cea5b3b0a08ec811fe7a7 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Fri, 25 Sep 2026 15:34:33 +0530
Subject: [PATCH] [flang] Use the target index width during FIR-to-LLVM
 lowering

---
 flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp | 14 ++++++++++----
 flang/lib/Optimizer/CodeGen/TypeConverter.cpp | 10 +++++++---
 flang/test/Fir/convert-to-llvm-target.fir     | 19 +++++++++++++++++++
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
index 995a2efba25a4d..6ad44901345338 100644
--- a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
+++ b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
@@ -66,10 +66,16 @@ mlir::Value ConvertFIRToLLVMPattern::integerCast(
     mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
     mlir::Type ty, mlir::Value val, bool fold) const {
   auto valTy = val.getType();
-  // If the value was not yet lowered, lower its type so that it can
-  // be used in getPrimitiveTypeSizeInBits.
-  if (!mlir::isa<mlir::IntegerType>(valTy))
-    valTy = convertType(valTy);
+  // If the value was not yet lowered, convert it to the LLVM integer type.
+  if (!mlir::isa<mlir::IntegerType>(valTy)) {
+    mlir::Type llvmValTy = convertType(valTy);
+    if (llvmValTy && llvmValTy != valTy) {
+      val = getTypeConverter()->materializeTargetConversion(rewriter, loc,
+                                                            llvmValTy, val);
+      assert(val && "failed to materialize integer target conversion");
+      valTy = llvmValTy;
+    }
+  }
   auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty);
   auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy);
   if (fold) {
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
index 31194f9c274f36..c901bf4b2f453d 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
@@ -37,7 +37,10 @@ static mlir::LowerToLLVMOptions MakeLowerOptions(mlir::ModuleOp module) {
 
   auto options = mlir::LowerToLLVMOptions(module.getContext());
   auto llvmDL = llvm::DataLayout(dataLayoutString);
-  if (llvmDL.getPointerSizeInBits(0) == 32) {
+  bool use32BitIndices = dataLayoutString.empty()
+                             ? fir::getTargetTriple(module).isArch32Bit()
+                             : llvmDL.getPointerSizeInBits(0) == 32;
+  if (use32BitIndices) {
     // FIXME: Should translateDataLayout in the MLIR layer be doing this?
     options.overrideIndexBitwidth(32);
   }
@@ -174,9 +177,10 @@ mlir::Type LLVMTypeConverter::offsetType() const {
   return mlir::IntegerType::get(&getContext(), 32);
 }
 
-// i64 can be used to index into aggregates like arrays
+// Index width follows the LLVM lowering options / data layout (i32 on
+// 32-bit targets, i64 otherwise).
 mlir::Type LLVMTypeConverter::indexType() const {
-  return mlir::IntegerType::get(&getContext(), 64);
+  return mlir::IntegerType::get(&getContext(), getIndexTypeBitwidth());
 }
 
 // fir.type<name(p : TY'...){f : TY...}>  -->  llvm<"%name = { ty... }">
diff --git a/flang/test/Fir/convert-to-llvm-target.fir b/flang/test/Fir/convert-to-llvm-target.fir
index 6adc5cd4b737fc..c37c27e4489efa 100644
--- a/flang/test/Fir/convert-to-llvm-target.fir
+++ b/flang/test/Fir/convert-to-llvm-target.fir
@@ -147,3 +147,22 @@ func.func @boxchar_len_i32_i64(%arg0 : !fir.boxchar<4>) -> (i64) {
 // INT32:  %[[len:.*]] = llvm.extractvalue %[[box_char]][1] : !llvm.struct<(ptr, i32)>
 // INT32:  %{{.*}} = llvm.sext %0 : i32 to i64
 // INT32-NEXT:  llvm.return
+
+// -----
+
+// Test that dynamic allocation uses the target index width.
+
+func.func @dynamic_alloca(%extent : index) {
+  %0 = fir.alloca !fir.array<?xi32>, %extent
+  return
+}
+
+// INT64-LABEL: llvm.func @dynamic_alloca
+// INT64-SAME: %[[extent:.*]]: i64
+// INT64: %[[count:.*]] = llvm.mul %[[extent]], %{{.*}} : i64
+// INT64: llvm.alloca %[[count]] x i32 : (i64) -> !llvm.ptr
+
+// INT32-LABEL: llvm.func @dynamic_alloca
+// INT32-SAME: %[[extent:.*]]: i32
+// INT32: %[[count:.*]] = llvm.mul %[[extent]], %{{.*}} : i32
+// INT32: llvm.alloca %[[count]] x i32 : (i32) -> !llvm.ptr



More information about the flang-commits mailing list