[flang-commits] [flang] [flang][Runtime] Add SIGNAL intrinisic (PR #79337)

Tom Eccles via flang-commits flang-commits at lists.llvm.org
Thu Jan 25 03:16:17 PST 2024


================
@@ -235,3 +237,66 @@ void fir::runtime::genSystemClock(fir::FirOpBuilder &builder,
   if (max)
     makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
 }
+
+// CALL SIGNAL(NUMBER, HANDLER [, STATUS])
+// The definition of the SIGNAL intrinsic allows HANDLER to be a function
+// pointer or an integer. STATUS can be dynamically optional
+void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc,
+                             mlir::Value number, mlir::Value handler,
+                             mlir::Value status) {
+  assert(mlir::isa<mlir::IntegerType>(number.getType()));
+  if (status)
+    assert(mlir::isa<mlir::IntegerType>(fir::unwrapRefType(status.getType())));
+  mlir::Type int64 = builder.getIntegerType(64);
+  number = builder.create<fir::ConvertOp>(loc, int64, number);
+
+  // we can return like a function or via the status argument
+  auto returnStatus = [&](mlir::Value stat) -> mlir::Value {
+    if (status) {
+      // status might be dynamically optional, so test if it is present
+      mlir::Value isPresent =
+          builder.create<IsPresentOp>(loc, builder.getI1Type(), status);
+      builder.genIfOp(loc, /*results=*/{}, isPresent, /*withElseRegion=*/false)
+          .genThen([&]() {
+            stat = builder.create<fir::ConvertOp>(
+                loc, fir::unwrapRefType(status.getType()), stat);
+            builder.create<fir::StoreOp>(loc, stat, status);
+          })
+          .end();
+    }
+    return {};
+  };
+
+  mlir::Type handlerUnwrappedTy = fir::unwrapRefType(handler.getType());
+  if (mlir::isa_and_nonnull<mlir::IntegerType>(handlerUnwrappedTy)) {
+#if _WIN32
+    // The windows documentation doesn't mention any support for passing
+    // SIG_DFL or SIG_IGN as integer arguments, so just return an error.
+
+    // reinterpret cast: the GNU extension is defined with STATUS as an integer
+    // but on Windows SIG_ERR is a void *
+    const std::int64_t sigErrVal =
+        static_cast<std::int64_t>(reinterpret_cast<std::uintptr_t>(SIG_ERR));
+    mlir::Value sigErr = builder.createIntegerConstant(loc, int64, sigErrVal);
+    returnStatus(sigErr);
+    errno = EINVAL;
----------------
tblah wrote:

Ahh you are right. Oops!

I will remove the special case for windows. `SIG_IGN` and `SIG_DFL` are in C89 so the Windows implementation of signal may still support them, and if they aren't, presumably the programmer would realize while trying to look up/include the correct integer constants to use.

https://github.com/llvm/llvm-project/pull/79337


More information about the flang-commits mailing list