Skip to content

Commit 443c9ca

Browse files
jeanPerierschweitzpgi
authored andcommitted
DATE_AND_TIME TIME and ZONE args lowering
1 parent 92d6533 commit 443c9ca

File tree

5 files changed

+94
-38
lines changed

5 files changed

+94
-38
lines changed

flang/include/flang/Lower/Runtime.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ void genUnlockStatement(AbstractConverter &, const parser::UnlockStmt &);
7070
void genPauseStatement(AbstractConverter &, const parser::PauseStmt &);
7171

7272
void genDateAndTime(FirOpBuilder &, mlir::Location,
73-
llvm::Optional<fir::CharBoxValue> date);
73+
llvm::Optional<fir::CharBoxValue> date,
74+
llvm::Optional<fir::CharBoxValue> time,
75+
llvm::Optional<fir::CharBoxValue> zone);
7476

7577
} // namespace lower
7678
} // namespace Fortran

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,15 +1167,17 @@ mlir::Value IntrinsicLibrary::genConjg(mlir::Type resultType,
11671167
// DATE_AND_TIME
11681168
void IntrinsicLibrary::genDateAndTime(llvm::ArrayRef<fir::ExtendedValue> args) {
11691169
assert(args.size() == 4 && "date_and_time has 4 args");
1170-
llvm::Optional<fir::CharBoxValue> date;
1171-
if (auto *charBox = args[0].getCharBox())
1172-
date = *charBox;
1173-
for (auto i = 1; i < 4; ++i)
1174-
if (fir::getBase(args[i]))
1175-
llvm::errs() << "TODO: lowering of DATE_AND_TIME arguments other than "
1176-
"DATE not yet implemented\n";
1177-
1178-
Fortran::lower::genDateAndTime(builder, loc, date);
1170+
llvm::SmallVector<llvm::Optional<fir::CharBoxValue>, 3> charArgs(3);
1171+
for (auto i = 0; i < 3; ++i)
1172+
if (auto *charBox = args[i].getCharBox())
1173+
charArgs[i] = *charBox;
1174+
// TODO: build descriptor for VALUES (also update runtime)
1175+
if (fir::getBase(args[3]))
1176+
mlir::emitError(loc, "TODO: lowering of DATE_AND_TIME VALUES argument not "
1177+
"yet implemented\n");
1178+
1179+
Fortran::lower::genDateAndTime(builder, loc, charArgs[0], charArgs[1],
1180+
charArgs[2]);
11791181
}
11801182

11811183
// DIM

flang/lib/Lower/Runtime.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,36 @@ void Fortran::lower::genPauseStatement(
183183

184184
void Fortran::lower::genDateAndTime(Fortran::lower::FirOpBuilder &builder,
185185
mlir::Location loc,
186-
llvm::Optional<fir::CharBoxValue> date) {
186+
llvm::Optional<fir::CharBoxValue> date,
187+
llvm::Optional<fir::CharBoxValue> time,
188+
llvm::Optional<fir::CharBoxValue> zone) {
187189
auto callee = genRuntimeFunction<mkRTKey(DateAndTime)>(loc, builder);
188190
mlir::Type idxTy = builder.getIndexType();
191+
mlir::Value zero;
192+
auto splitArg = [&](llvm::Optional<fir::CharBoxValue> arg,
193+
mlir::Value &buffer, mlir::Value &len) {
194+
if (arg) {
195+
buffer = arg->getBuffer();
196+
len = arg->getLen();
197+
} else {
198+
if (!zero)
199+
zero = builder.createIntegerConstant(loc, idxTy, 0);
200+
buffer = zero;
201+
len = zero;
202+
}
203+
};
189204
mlir::Value dateBuffer;
190205
mlir::Value dateLen;
191-
if (date) {
192-
dateBuffer = date->getBuffer();
193-
dateLen = date->getLen();
194-
} else {
195-
auto zero = builder.createIntegerConstant(loc, idxTy, 0);
196-
dateBuffer = zero;
197-
dateLen = zero;
198-
}
199-
llvm::SmallVector<mlir::Value, 2> args{dateBuffer, dateLen};
206+
splitArg(date, dateBuffer, dateLen);
207+
mlir::Value timeBuffer;
208+
mlir::Value timeLen;
209+
splitArg(time, timeBuffer, timeLen);
210+
mlir::Value zoneBuffer;
211+
mlir::Value zoneLen;
212+
splitArg(zone, zoneBuffer, zoneLen);
213+
214+
llvm::SmallVector<mlir::Value, 2> args{dateBuffer, timeBuffer, zoneBuffer,
215+
dateLen, timeLen, zoneLen};
200216
llvm::SmallVector<mlir::Value, 2> operands;
201217
for (const auto &op : llvm::zip(args, callee.getType().getInputs()))
202218
operands.emplace_back(

flang/runtime/clock.cpp

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,59 @@
1212
#include <algorithm>
1313
#include <cstdlib>
1414
#include <cstring>
15+
#include <stdio.h>
1516
#include <time.h>
16-
// FIXME: windows
17+
// TODO: windows, localtime_r/gettimeofday do not exists/ are different.
18+
#ifndef _WIN32
1719
#include <sys/time.h>
1820

1921
namespace Fortran::runtime {
2022

21-
void RTNAME(DateAndTime)(char *date, std::size_t dateChars) {
22-
static constexpr int buffSize{16};
23-
char buffer[buffSize];
23+
void RTNAME(DateAndTime)(char *date, char *time, char *zone,
24+
std::size_t dateChars, std::size_t timeChars, std::size_t zoneChars) {
2425
timeval t;
25-
time_t timer;
26-
tm time;
26+
::gettimeofday(&t, nullptr);
27+
time_t timer{t.tv_sec};
28+
tm localTime;
29+
::localtime_r(&timer, &localTime);
2730

28-
gettimeofday(&t, nullptr);
29-
timer = t.tv_sec;
30-
// TODO windows
31-
localtime_r(&timer, &time);
31+
static constexpr int buffSize{16};
32+
char buffer[buffSize];
33+
auto copyBufferAndPad{
34+
[&](char *dest, std::size_t destChars, std::size_t len) {
35+
auto copyLen{std::min(len, destChars)};
36+
std::memcpy(dest, buffer, copyLen);
37+
for (auto i{copyLen}; i < destChars; ++i) {
38+
dest[i] = ' ';
39+
}
40+
}};
3241
if (date) {
33-
auto len = strftime(buffer, buffSize, "%Y%m%d", &time);
34-
auto copyLen = std::min(len, dateChars);
35-
std::memcpy(date, buffer, copyLen);
36-
for (auto i{copyLen}; i < dateChars; ++i) {
37-
date[i] = ' ';
38-
}
42+
auto len = ::strftime(buffer, buffSize, "%Y%m%d", &localTime);
43+
copyBufferAndPad(date, dateChars, len);
44+
}
45+
if (time) {
46+
auto ms{t.tv_usec / 1000};
47+
auto len{::snprintf(buffer, buffSize, "%02d%02d%02d.%03ld",
48+
localTime.tm_hour, localTime.tm_min, localTime.tm_sec, ms)};
49+
copyBufferAndPad(time, timeChars, len);
3950
}
51+
if (zone) {
52+
// Note: this may leave the buffer empty on many platforms. Classic flang
53+
// has a much more complex way of doing this (see __io_timezone in classic
54+
// flang).
55+
auto len{::strftime(buffer, buffSize, "%z", &localTime)};
56+
copyBufferAndPad(zone, zoneChars, len);
57+
}
58+
}
59+
} // namespace Fortran::runtime
60+
61+
#else /* Windows */
62+
// TODO: implement windows version (probably best to try merging implementations
63+
// as much as possible).
64+
namespace Fortran::runtime {
65+
void RTNAME(DateAndTime)(
66+
char *, char *, char *, std::size_t, std::size_t, std::size_t) {
67+
// TODO
4068
}
4169
} // namespace Fortran::runtime
70+
#endif

flang/runtime/clock.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===-- runtime/clock.h -------------------------------------*- C++ -*-===//
1+
//===-- runtime/clock.h -----------------------------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,7 +20,14 @@ class Descriptor;
2020

2121
extern "C" {
2222

23-
void RTNAME(DateAndTime)(char *date, std::size_t dateChars);
23+
/// Implement runtime for DATE_AND_TIME intrinsic.
24+
/// TODO:
25+
/// - Add VALUES argument (through descriptor).
26+
/// - Windows implementation (currently does nothing)
27+
void RTNAME(DateAndTime)(char *date, char *time, char *zone,
28+
std::size_t dateChars, std::size_t timeChars, std::size_t zoneChars);
2429
}
30+
31+
// TODO: CPU_TIME, SYSTEM_CLOCK
2532
} // namespace Fortran::runtime
2633
#endif // FORTRAN_RUNTIME_CLOCK_H_

0 commit comments

Comments
 (0)