Skip to content

Commit 2bb97d1

Browse files
committed
[flang] Implement CHDIR intrinsic
1 parent 95ff3b5 commit 2bb97d1

File tree

8 files changed

+63
-0
lines changed

8 files changed

+63
-0
lines changed

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ struct IntrinsicLibrary {
202202
mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
203203
mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
204204
fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
205+
void genChdir(llvm::ArrayRef<fir::ExtendedValue>);
205206
template <mlir::arith::CmpIPredicate pred>
206207
fir::ExtendedValue genCharacterCompare(mlir::Type,
207208
llvm::ArrayRef<fir::ExtendedValue>);

flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ void genSignal(fir::FirOpBuilder &builder, mlir::Location loc,
9090
void genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
9191
mlir::Value seconds);
9292

93+
/// generate chdir runtime call
94+
void genChdir(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value dir,
95+
mlir::Value status);
96+
9397
} // namespace runtime
9498
} // namespace fir
9599

flang/include/flang/Runtime/extensions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ std::int64_t RTNAME(Signal)(std::int64_t number, void (*handler)(int));
6262
// GNU extension subroutine SLEEP(SECONDS)
6363
void RTNAME(Sleep)(std::int64_t seconds);
6464

65+
// GNU extension subroutine CHDIR(DIR, [STATUS])
66+
void RTNAME(Chdir)(const char *dir, int *status);
67+
6568
// GNU extension function ACCESS(NAME, MODE)
6669
// TODO: not supported on Windows
6770
#ifndef _WIN32

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,11 @@ static const IntrinsicInterface intrinsicSubroutine[]{
14031403
{"stat", AnyInt, Rank::scalar, Optionality::optional,
14041404
common::Intent::Out}},
14051405
{}, Rank::elemental, IntrinsicClass::atomicSubroutine},
1406+
{"chdir",
1407+
{{"dir", AnyChar, Rank::anyOrAssumedRank},
1408+
{"stat", AnyInt, Rank::scalar, Optionality::optional,
1409+
common::Intent::Out}},
1410+
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
14061411
{"co_broadcast",
14071412
{{"a", AnyData, Rank::anyOrAssumedRank, Optionality::required,
14081413
common::Intent::InOut},

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ static constexpr IntrinsicHandler handlers[]{
185185
{"c_ptr_ne", &I::genCPtrCompare<mlir::arith::CmpIPredicate::ne>},
186186
{"ceiling", &I::genCeiling},
187187
{"char", &I::genChar},
188+
{"chdir",
189+
&I::genChdir,
190+
{{{"dir", asValue}, {"status", asAddr, handleDynamicOptional}}},
191+
/*isElemental=*/false},
188192
{"cmplx",
189193
&I::genCmplx,
190194
{{{"x", asValue}, {"y", asValue, handleDynamicOptional}}}},
@@ -3075,6 +3079,19 @@ IntrinsicLibrary::genChar(mlir::Type type,
30753079
return fir::CharBoxValue{cast, len};
30763080
}
30773081

3082+
// CHDIR
3083+
void IntrinsicLibrary::genChdir(llvm::ArrayRef<fir::ExtendedValue> args) {
3084+
assert(args.size() == 2);
3085+
mlir::Value status =
3086+
isStaticallyAbsent(args[1])
3087+
? builder
3088+
.create<fir::AbsentOp>(
3089+
loc, builder.getRefType(builder.getNoneType()))
3090+
.getResult()
3091+
: fir::getBase(args[1]);
3092+
fir::runtime::genChdir(builder, loc, fir::getBase(args[0]), status);
3093+
}
3094+
30783095
// CMPLX
30793096
mlir::Value IntrinsicLibrary::genCmplx(mlir::Type resultType,
30803097
llvm::ArrayRef<mlir::Value> args) {

flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,3 +385,13 @@ void fir::runtime::genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
385385
fir::runtime::getRuntimeFunc<mkRTKey(Sleep)>(loc, builder)};
386386
builder.create<fir::CallOp>(loc, func, seconds);
387387
}
388+
389+
/// generate chdir runtime call
390+
void fir::runtime::genChdir(fir::FirOpBuilder &builder, mlir::Location loc,
391+
mlir::Value dir, mlir::Value status) {
392+
mlir::func::FuncOp func{
393+
fir::runtime::getRuntimeFunc<mkRTKey(Chdir)>(loc, builder)};
394+
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
395+
builder, loc, func.getFunctionType(), dir, status);
396+
builder.create<fir::CallOp>(loc, func, args);
397+
}

flang/runtime/extensions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <ctime>
2222
#include <signal.h>
2323
#include <thread>
24+
#include <unistd.h>
2425

2526
#ifdef _WIN32
2627
#define WIN32_LEAN_AND_MEAN
@@ -248,5 +249,12 @@ std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name,
248249
}
249250
#endif
250251

252+
// CHDIR(DIR)
253+
void RTNAME(Chdir)(const char *dir, int *status) {
254+
int stat = chdir(dir);
255+
if (status)
256+
*status = stat;
257+
}
258+
251259
} // namespace Fortran::runtime
252260
} // extern "C"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
2+
3+
subroutine test_chdir()
4+
implicit none
5+
! CHECK-LABEL: func.func @_QPtest_chdir() {
6+
7+
call chdir("..")
8+
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QQclX2E2E) : !fir.ref<!fir.char<1,2>>
9+
! CHECK: %[[C_2:.*]] = arith.constant 2 : index
10+
! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] typeparams %[[C_2]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX2E2E"} : (!fir.ref<!fir.char<1,2>>, index) -> (!fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,2>>)
11+
! CHECK: %[[VAL_2:.*]] = fir.absent !fir.ref<none>
12+
! CHECK: %[[VAL_3:.*]] = fir.convert %{{.*}} : (!fir.ref<!fir.char<1,2>>) -> !fir.ref<i8>
13+
! CHECK: %[[VAL_4:.*]] = fir.convert %{{.*}} : (!fir.ref<none>) -> !fir.ref<i32>
14+
! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAChdir(%[[VAL_3]], %[[VAL_4]]) fastmath<contract> : (!fir.ref<i8>, !fir.ref<i32>) -> none
15+
end subroutine

0 commit comments

Comments
 (0)