Skip to content

Commit 39997ea

Browse files
LittleMeepobryanpkc
authored andcommitted
[flang1][flang2] Fix a bug in implied DO loop with substring
Add support for implied DO loop with substring in initialization.
1 parent 706438f commit 39997ea

File tree

8 files changed

+342
-2
lines changed

8 files changed

+342
-2
lines changed

test/f90_correct/inc/substr.mk

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
# See https://llvm.org/LICENSE.txt for license information.
4+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
#
6+
7+
$(TEST): run
8+
9+
10+
build: $(SRC)/$(TEST).f90
11+
-$(RM) $(TEST).$(EXESUFFIX) core *.d *.mod FOR*.DAT FTN* ftn* fort.*
12+
@echo ------------------------------------ building test $@
13+
-$(CC) -c $(CFLAGS) $(SRC)/check.c -o check.$(OBJX)
14+
-$(FC) -c $(FFLAGS) $(LDFLAGS) $(SRC)/$(TEST).f90 -o $(TEST).$(OBJX)
15+
-$(FC) $(FFLAGS) $(LDFLAGS) $(TEST).$(OBJX) check.$(OBJX) $(LIBS) -o $(TEST).$(EXESUFFIX)
16+
17+
18+
run:
19+
@echo ------------------------------------ executing test $(TEST)
20+
$(TEST).$(EXESUFFIX)
21+
22+
verify: ;
23+

test/f90_correct/lit/substr.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
# See https://llvm.org/LICENSE.txt for license information.
4+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
6+
# Shared lit script for each tests. Run bash commands that run tests with make.
7+
8+
# RUN: KEEP_FILES=%keep FLAGS=%flags TEST_SRC=%s MAKE_FILE_DIR=%S/.. bash %S/runmake | tee %t
9+
# RUN: cat %t | FileCheck %S/runmake

test/f90_correct/src/substr.f90

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
!
2+
! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
! See https://llvm.org/LICENSE.txt for license information.
4+
! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
!
6+
! Test for implied do-loop contains substring in initialization.
7+
8+
program test
9+
implicit none
10+
integer :: i
11+
integer, parameter :: n = 8
12+
character(*), parameter :: a = "Hello world!"
13+
character(10), parameter :: z = ""
14+
character(*), parameter :: b1(2) = [(a(i:i+4),i=1,7,6)]
15+
character(5) :: b2(2) = [(a(i:i+4),i=1,7,6)]
16+
character(*), parameter :: c1 = transfer([(a(i:i),i=1,len(a))], a)
17+
character(12) :: c2 = transfer([(a(i:i),i=1,len(a))], a)
18+
character(*), parameter :: d1 = transfer([(a(i:i),i=len(a),1,-1)], a)
19+
character(12) :: d2 = transfer([(a(i:i),i=len(a),1,-1)], a)
20+
character(*), parameter :: e1 = transfer([(a(i:i+4),i=1,7,6)], z)
21+
character(10) :: e2 = transfer([(a(i:i+4),i=1,7,6)], z)
22+
character(5) :: cmp1(2)
23+
character(12) :: cmp2
24+
character(10) :: cmp3
25+
integer :: rslts(n), expect(n)
26+
27+
DATA cmp1 /"Hello", "world"/
28+
DATA cmp2 /"!dlrow olleH"/
29+
DATA cmp3 /"Helloworld"/
30+
31+
rslts = 0
32+
expect = 1
33+
34+
if (len(b1) == 5 .and. all(b1 == cmp1)) rslts(1) = 1
35+
if (all(b2 == cmp1)) rslts(2) = 1
36+
if (len(c1) == 12 .and. c1 == a) rslts(3) = 1
37+
if (c2 == a) rslts(4) = 1
38+
if (len(d1) == 12 .and. d1 == cmp2) rslts(5) = 1
39+
if (d2 == cmp2) rslts(6) = 1
40+
if (len(e1) == 10 .and. e1 == cmp3) rslts(7) = 1
41+
if (e2 == cmp3) rslts(8) = 1
42+
43+
call check(rslts, expect, n)
44+
end program

tools/flang1/flang1exe/dinit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,9 @@ ac_opname(int id)
13501350
case AC_TRIPLE:
13511351
strcpy(bf, "TRIPLE");
13521352
break;
1353+
case AC_SUBSTR:
1354+
strcpy(bf, "SUBSTR");
1355+
break;
13531356
default:
13541357
sprintf(bf, "ac_opnameUNK_%d", id);
13551358
break;

tools/flang1/flang1exe/semant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ struct _aexpr {
574574
#define AC_LNOT 23
575575
#define AC_EXPX 24
576576
#define AC_TRIPLE 25
577+
#define AC_SUBSTR 26
577578

578579
typedef enum {
579580
AC_I_NONE = 0,

tools/flang1/flang1exe/semutil2.c

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static AC_INTRINSIC map_I_to_AC(int intrin);
7575
static AC_INTRINSIC map_PD_to_AC(int pdnum);
7676
static bool is_illegal_expr_in_init(SPTR, int ast, DTYPE);
7777
static int init_intrin_type_desc(int ast, SPTR sptr, int std);
78+
static SPTR get_substring(SPTR str, int lb, int rb);
7879

7980
/*
8081
* semant-created temporaries which are re-used across statements.
@@ -1025,7 +1026,7 @@ static const char *_iexpr_op[] = {
10251026
"?0?", "ADD", "SUB", "MUL", "DIV", "EXP", "NEG",
10261027
"INTR_CALL", "ARRAYREF", "MEMBR_SEL", "CONV", "CAT", "EXPK", "LEQV",
10271028
"LNEQV", "LOR", "LAND", "EQ", "GE", "GT", "LE",
1028-
"LT", "NE", "LNOT", "EXPX", "TRIPLE",
1029+
"LT", "NE", "LNOT", "EXPX", "TRIPLE", "SUBSTR",
10291030
};
10301031

10311032
static const char *
@@ -1951,7 +1952,20 @@ compute_size_expr(bool add_flag, ACL *aclp, DTYPE dtype)
19511952
dtype = SST_DTYPEG(stkp);
19521953
}
19531954
}
1954-
acs.eltype = dt;
1955+
if (sem.dinit_data && id == S_EXPR && A_TYPEG(SST_ASTG(stkp)) == A_SUBSTR) {
1956+
int ast, leftval, rightval, lenval, len;
1957+
DTYPE newdtype;
1958+
ast = SST_ASTG(stkp);
1959+
leftval = dinit_eval(A_LEFTG(ast));
1960+
rightval = dinit_eval(A_RIGHTG(ast));
1961+
lenval = rightval - leftval + 1;
1962+
len = lenval <= 0 ? astb.i0 : mk_cval(lenval, DT_INT4);
1963+
newdtype = get_type(2, DTY(dt), len);
1964+
acs.eltype = newdtype;
1965+
A_DTYPEP(ast, newdtype);
1966+
} else {
1967+
acs.eltype = dt;
1968+
}
19551969
switch (DTY(acs.eltype)) {
19561970
case TY_CHAR:
19571971
case TY_NCHAR:
@@ -4855,7 +4869,31 @@ construct_acl_from_ast(int ast, DTYPE dtype, int parent_acltype)
48554869
aclp->is_const = 1;
48564870
aclp->subc = prev;
48574871
}
4872+
break;
4873+
case A_SUBSTR:
4874+
aclp = GET_ACL(15);
4875+
aclp->id = AC_IEXPR;
4876+
aclp->u1.expr = (AEXPR *)getitem(15, sizeof(AEXPR));
4877+
aclp->u1.expr->op = AC_SUBSTR;
4878+
aclp->u1.expr->lop = construct_acl_from_ast(A_LOPG(ast), 0, 0);
4879+
if (!aclp->u1.expr->lop) {
4880+
return 0;
4881+
}
4882+
aclp->dtype = A_DTYPEG(ast);
4883+
l = GET_ACL(15);
4884+
l->id = AC_AST;
4885+
l->is_const = 1;
4886+
l->u1.ast = A_LEFTG(ast);
4887+
l->dtype = A_DTYPEG(A_LEFTG(ast));
4888+
4889+
u = GET_ACL(15);
4890+
u->id = AC_AST;
4891+
u->is_const = 1;
4892+
u->u1.ast = A_RIGHTG(ast);
4893+
u->dtype = A_DTYPEG(A_RIGHTG(ast));
48584894

4895+
l->next = u;
4896+
aclp->u1.expr->rop = l;
48594897
break;
48604898
default:
48614899
interr("unexpected ast type in initialization expr", ast, 3);
@@ -7337,6 +7375,20 @@ add_array_init(ASTLIST *list, int ast, DTYPE dtype, int sptr)
73377375
}
73387376
} /* add_array_init */
73397377

7378+
static void
7379+
add_substr_init(ASTLIST *list, int ast, DTYPE dtype, int sptr)
7380+
{
7381+
SPTR src, substr;
7382+
int lb, ub, substr_ast;
7383+
7384+
src = A_SPTRG(A_LOPG(ast));
7385+
lb = (int)dinit_eval(A_LEFTG(ast));
7386+
ub = (int)dinit_eval(A_RIGHTG(ast));
7387+
substr = get_substring(src, lb, ub);
7388+
substr_ast = mk_cval(substr, DTYPEG(substr));
7389+
add_init(list, substr_ast, dtype, sptr);
7390+
}
7391+
73407392
static ACL *
73417393
dinit_fill_struct(ASTLIST *list, ACL *aclp, int sdtype, int sptr,
73427394
int memberlist, int init_single)
@@ -7412,6 +7464,8 @@ dinit_fill_struct(ASTLIST *list, ACL *aclp, int sdtype, int sptr,
74127464
aa = mk_init(PARAMVALG(A_SPTRG(aast)), dtype);
74137465
A_SPTRP(aa, sptr);
74147466
add_init(list, aast, dtype, sptr);
7467+
} else if (A_TYPEG(aast) == A_SUBSTR) {
7468+
add_substr_init(list, aast, sdtype, sptr);
74157469
} else {
74167470
if (DTY(sdtype) == TY_ARRAY) {
74177471
aast = dinit_getval1(aast, DTY(sdtype + 1));
@@ -7517,6 +7571,7 @@ dinit_fill_struct(ASTLIST *list, ACL *aclp, int sdtype, int sptr,
75177571
save_conval1 = CONVAL1G(idx_sptr);
75187572
if (stepval >= 0) {
75197573
for (i = initval; i <= limitval; i += stepval) {
7574+
sem.dostack->currval = i;
75207575
switch (DTY(DTYPEG(idx_sptr))) {
75217576
case TY_INT8:
75227577
case TY_LOG8:
@@ -7532,6 +7587,7 @@ dinit_fill_struct(ASTLIST *list, ACL *aclp, int sdtype, int sptr,
75327587
}
75337588
} else {
75347589
for (i = initval; i >= limitval; i += stepval) {
7590+
sem.dostack->currval = i;
75357591
switch (DTY(DTYPEG(idx_sptr))) {
75367592
case TY_INT8:
75377593
case TY_LOG8:
@@ -11155,6 +11211,66 @@ eval_const_array_section(ACL *lop, int ldtype)
1115511211
return sb.root;
1115611212
}
1115711213

11214+
static SPTR
11215+
get_static_str(SPTR sptr)
11216+
{
11217+
DREC *p = NULL;
11218+
SPTR cnst_sptr;
11219+
LOGICAL found;
11220+
DTYPE dtype;
11221+
11222+
cnst_sptr = 0;
11223+
found = FALSE;
11224+
dtype = DTYPEG(sptr);
11225+
dinit_save();
11226+
while((p = dinit_read())) {
11227+
int tdtype = p->dtype;
11228+
INT tconval = p->conval;
11229+
if (tdtype == DINIT_LOC) {
11230+
if (tconval == sptr) {
11231+
found = TRUE;
11232+
} else {
11233+
found = FALSE;
11234+
}
11235+
continue;
11236+
}
11237+
if (tdtype == DINIT_STR) {
11238+
if (found) {
11239+
cnst_sptr = tconval;
11240+
break;
11241+
}
11242+
}
11243+
found = FALSE;
11244+
}
11245+
dinit_restore();
11246+
11247+
if (cnst_sptr == 0 || STYPEG(cnst_sptr) != ST_CONST) {
11248+
return 0;
11249+
}
11250+
return cnst_sptr;
11251+
}
11252+
11253+
static ACL *
11254+
eval_substr(ACL *lop, ACL *rop)
11255+
{
11256+
SPTR p;
11257+
int lb, ub;
11258+
ACL *ret = NULL;
11259+
11260+
lb = rop->conval;
11261+
ub = rop->next->conval;
11262+
p = get_substring(lop->conval, lb, ub);
11263+
11264+
ret = GET_ACL(15);
11265+
BZERO(ret, ACL, 1);
11266+
ret->id = AC_CONST;
11267+
ret->dtype = DTYPEG(p);
11268+
ret->repeatc = astb.i1;
11269+
ret->conval = ret->sptr = p;
11270+
ret->u1.ast = mk_cnst(ret->conval);
11271+
return ret;
11272+
}
11273+
1115811274
static ISZ_T
1115911275
get_ival(DTYPE dtype, INT conval)
1116011276
{
@@ -11404,6 +11520,8 @@ eval_init_op(int op, ACL *lop, DTYPE ldtype, ACL *rop, DTYPE rdtype, SPTR sptr,
1140411520

1140511521
root = clone_init_const(c, TRUE);
1140611522
root = eval_init_expr(root);
11523+
} else if (op == AC_SUBSTR) {
11524+
root = eval_substr(lop, rop);
1140711525
} else if (op == AC_INTR_CALL) {
1140811526
AC_INTRINSIC intrin = lop->u1.i;
1140911527
switch (intrin) {
@@ -11901,6 +12019,12 @@ eval_do(ACL *ido)
1190112019
INT sav_conval1 = CONVAL1G(idx_sptr);
1190212020
int inflag = 0;
1190312021

12022+
if (sem.top == &sem.dostack[MAX_DOSTACK]) {
12023+
errsev(34);
12024+
return 0;
12025+
}
12026+
++sem.top;
12027+
1190412028
initval = dinit_eval(di->init_expr);
1190512029
if (sem.dinit_error) {
1190612030
interr("Non-constant implied DO initial value", di->init_expr, 3);
@@ -11921,6 +12045,7 @@ eval_do(ACL *ido)
1192112045

1192212046
if (stepval >= 0) {
1192312047
for (i = initval; i <= limitval; i += stepval) {
12048+
sem.dostack->currval = i;
1192412049
switch (DTY(DTYPEG(idx_sptr))) {
1192512050
case TY_INT8:
1192612051
case TY_LOG8:
@@ -11946,6 +12071,7 @@ eval_do(ACL *ido)
1194612071
}
1194712072
} else {
1194812073
for (i = initval; i >= limitval; i += stepval) {
12074+
sem.dostack->currval = i;
1194912075
switch (DTY(DTYPEG(idx_sptr))) {
1195012076
case TY_INT8:
1195112077
case TY_LOG8:
@@ -11971,6 +12097,7 @@ eval_do(ACL *ido)
1197112097
}
1197212098

1197312099
CONVAL1P(idx_sptr, sav_conval1);
12100+
--sem.top;
1197412101

1197512102
return root;
1197612103
}
@@ -14836,3 +14963,33 @@ gen_set_type(int dest_ast, int src_ast, int std, LOGICAL insert_before,
1483614963

1483714964
return std;
1483814965
}
14966+
14967+
static SPTR
14968+
get_substring(SPTR src, int lb, int ub)
14969+
{
14970+
char *char_cnst = NULL;
14971+
char *str = NULL;
14972+
int cvlen, len;
14973+
SPTR p;
14974+
14975+
if (DINITG(src) && SCG(src) == SC_STATIC) {
14976+
src = get_static_str(src);
14977+
}
14978+
char_cnst = stb.n_base + CONVAL1G(src);
14979+
cvlen = ub - lb + 1;
14980+
if (cvlen < 1) {
14981+
p = getstring("", 0);
14982+
} else {
14983+
str = getitem(0, cvlen + 1);
14984+
memset(str, '\0', cvlen);
14985+
len = strlen(char_cnst);
14986+
if (lb - 1 + cvlen < len) {
14987+
memcpy(str, char_cnst + lb - 1, sizeof(char) * cvlen);
14988+
} else if (lb - 1 < len ) {
14989+
memcpy(str, char_cnst + lb - 1, sizeof(char) * (len - lb + 1));
14990+
}
14991+
str[cvlen] = '\0';
14992+
p = getstring(str, cvlen);
14993+
}
14994+
return p;
14995+
}

0 commit comments

Comments
 (0)