Skip to content

Commit 9dd4ed0

Browse files
committed
Fix a segfault with procedure dummy arguments
Fix a fault with procedure dummy arguments and interfaces. Create a unique symbol for interfaces that are used in procedure pointer declarations because the LLVM bridge uses the interface as well as the argument ILI to generate arguments at a procedure pointer call. An interface symbol might turn into a procedure symbol in the back-end. Create a unique symbol so we can mark it with a new field called IS_PROC_PTR_IFACE. This field says that the symbol is used as an interface to a procedure pointer. When the bridge sees this field set, it knows to generate a closure pointer as the last argument at the call-site. This bug fix addresses Flang issue #577.
1 parent 4498b2b commit 9dd4ed0

File tree

11 files changed

+133
-7
lines changed

11 files changed

+133
-7
lines changed

tools/flang1/flang1exe/dtypeutl.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,20 @@ tk_match_arg(int formal_dt, int actual_dt, LOGICAL flag)
15171517
}
15181518
}
15191519
else if (!eq_dtype2(f_dt, a_dt, flag)) {
1520+
if (DTY(f_dt) == TY_PTR && DTY(a_dt) == TY_PTR &&
1521+
DTY(DTY(f_dt + 1)) == TY_PROC && DTY(DTY(a_dt + 1)) == TY_PROC) {
1522+
/* eq_dtype2 checks equality of the procedure pointers.
1523+
* If they are not the same (including the same name), then
1524+
* it returns false. This is correct for an equality test.
1525+
* However, in this case, we don't care about the names being
1526+
* the same if all other attributes are equal.
1527+
*/
1528+
DTYPE d1 = DTY(f_dt + 1);
1529+
DTYPE d2 = DTY(a_dt + 1);
1530+
if (cmp_interfaces(DTY(d1 + 2), DTY(d2 + 2), FALSE)) {
1531+
return TRUE;
1532+
}
1533+
}
15201534
return FALSE;
15211535
}
15221536

tools/flang1/flang1exe/lower.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
* 20.1 -- 1.55
141141
* All of 1.54 +
142142
* pass elemental field for subprogram when emitting ST_ENTRY.
143+
*
144+
* For ST_PROC, pass IS_PROC_PTR_IFACE flag.
143145
*/
144146
#define VersionMajor 1
145147
#define VersionMinor 55

tools/flang1/flang1exe/lowersym.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4043,6 +4043,7 @@ lower_symbol(int sptr)
40434043
putbit("is_interface", IS_INTERFACEG(sptr));
40444044
putval("assocptr", ASSOC_PTRG(sptr));
40454045
putval("ptrtarget",PTR_TARGETG(sptr));
4046+
putbit("prociface", IS_PROC_PTR_IFACEG(sptr));
40464047
}
40474048

40484049
strip = 1;
@@ -4273,6 +4274,7 @@ lower_symbol(int sptr)
42734274
#endif
42744275
putval("assocptr", ASSOC_PTRG(sptr));
42754276
putval("ptrtarget", PTR_TARGETG(sptr));
4277+
putbit("prociface", IS_PROC_PTR_IFACEG(sptr));
42764278
strip = 1;
42774279
break;
42784280

@@ -4322,6 +4324,7 @@ lower_symbol(int sptr)
43224324
putbit("is_interface", 0);
43234325
putval("assocptr", 0);
43244326
putval("ptrtarget", 0);
4327+
putbit("prociface", 0);
43254328
strip = 1;
43264329
break;
43274330

@@ -4523,6 +4526,7 @@ lower_symbol(int sptr)
45234526
putval("descriptor", IS_PROC_DUMMYG(sptr) ? SDSCG(sptr) : 0);
45244527
putsym("assocptr", ASSOC_PTRG(sptr));
45254528
putsym("ptrtarget", PTR_TARGETG(sptr));
4529+
putbit("prociface", IS_PROC_PTR_IFACEG(sptr));
45264530
if (gbl.stbfil && DTY(DTYPEG(sptr) + 2)) {
45274531
if (fvalfirst) {
45284532
putsym(NULL, FVALG(sptr));

tools/flang1/flang1exe/semant.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2479,7 +2479,7 @@ semant1(int rednum, SST *top)
24792479
* body should never contain a procedure defined by a subprogram,
24802480
* so this flag should never be set for an interface. Because
24812481
* getsym() does not have access to sem.interface, we reset the
2482-
* NTERNAL flag here.
2482+
* INTERNAL flag here.
24832483
*/
24842484
INTERNALP(sptr, 0);
24852485
}
@@ -11343,6 +11343,49 @@ semant1(int rednum, SST *top)
1134311343
if (POINTERG(sptr)) {
1134411344
attr |= ET_B(ET_POINTER);
1134511345
}
11346+
if (!IS_PROC_DUMMYG(sptr) && IS_INTERFACEG(proc_interf_sptr) &&
11347+
!IS_PROC_PTR_IFACEG(proc_interf_sptr)) {
11348+
/* Create a unique symbol for the interface so it does not conflict with
11349+
* an external procedure symbol. For non-procedure dummy arguments,
11350+
* we need a unique symbol for the interface in order to preserve
11351+
* the interface flag (IS_PROC_PTR_IFACE). We need the interface flag in
11352+
* the back-end so we properly generate the procedure descriptor
11353+
* actual arguments on the call-site (when we call the procedure pointer).
11354+
* This is only needed by the LLVM back-end because the bridge uses the
11355+
* interface to generate the LLVM IR for the actual arguments.
11356+
*/
11357+
char * buf;
11358+
int len;
11359+
SPTR sym;
11360+
11361+
/* First, let's see if we aleady have a unique interface symbol */
11362+
len = strlen(SYMNAME(proc_interf_sptr)) + strlen("iface") + 1;
11363+
buf = getitem(0, len);
11364+
sprintf(buf,"%s$iface",SYMNAME(proc_interf_sptr));
11365+
sym = findByNameStypeScope(buf, ST_PROC, 0);
11366+
if (sym > NOSYM && !cmp_interfaces_strict(sym, proc_interf_sptr, 0)) {
11367+
/* The interface is not compatible. We will now try to find one that
11368+
* is compatible in the symbol table.
11369+
*/
11370+
SPTR sym2 = sym;
11371+
get_next_hash_link(sym2, 0);
11372+
while ((sym2=get_next_hash_link(sym2, 1)) > NOSYM) {
11373+
if (cmp_interfaces_strict(sym2, proc_interf_sptr, 0)) {
11374+
break;
11375+
}
11376+
}
11377+
sym = sym2;
11378+
}
11379+
if (sym <= NOSYM) {
11380+
/* We don't yet have a unique interface symbol, so create it now */
11381+
sym = get_next_sym(SYMNAME(proc_interf_sptr), "iface");
11382+
/* Propagate flags from the original symbol to the new symbol */
11383+
copy_sym_flags(sym, proc_interf_sptr);
11384+
HCCSYMP(sym, 1);
11385+
IS_PROC_PTR_IFACEP(sym, 1);
11386+
}
11387+
proc_interf_sptr = sym;
11388+
}
1134611389
sptr = decl_procedure_sym(sptr, proc_interf_sptr, attr);
1134711390
sptr =
1134811391
setup_procedure_sym(sptr, proc_interf_sptr, attr, entity_attr.access);

tools/flang1/flang1exe/symtab.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,6 +2802,41 @@ cmp_interfaces_strict(SPTR sym1, SPTR sym2, cmp_interface_flags flag)
28022802
return true;
28032803
}
28042804

2805+
/** \brief Copy flags from one symbol to another symbol.
2806+
*
2807+
* This routine is the same as dup_sym() except it preserves the symbol's
2808+
* name, hash link, scope, and name pointer. In other words, it copies all but
2809+
* 4 flags from one symbol to another. The 4 flags that are not copied are
2810+
* the hashlk, symlk, scope, and nmptr.
2811+
*
2812+
* \param dest is the receiving symbol table pointer of the flags.
2813+
* \param src is the source symbol table pointer of the flags.
2814+
*/
2815+
void
2816+
copy_sym_flags(SPTR dest, SPTR src)
2817+
{
2818+
2819+
SYM *destSym;
2820+
SPTR hashlk;
2821+
SPTR symlk;
2822+
INT nmptr;
2823+
INT scope;
2824+
2825+
destSym = (stb.stg_base + dest);
2826+
hashlk = destSym->hashlk;
2827+
symlk = destSym->symlk;
2828+
nmptr = destSym->nmptr;
2829+
scope = destSym->scope;
2830+
2831+
*destSym = *(stb.stg_base + src);
2832+
2833+
destSym->hashlk = hashlk;
2834+
destSym->symlk = symlk;
2835+
destSym->nmptr = nmptr;
2836+
destSym->scope = scope;
2837+
2838+
}
2839+
28052840
/**
28062841
* replace contents of a symbol with values defining every field while ensuring
28072842
* values necessary for the hashing function are saved and restored.

tools/flang1/utils/symtab/symtab.in.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ LOGICAL is_arg_in_entry(int, int);
414414
int resolve_sym_aliases(int);
415415
LOGICAL is_procedure_ptr(int);
416416
void proc_arginfo(int, int *, int *, int *);
417+
void copy_sym_flags(SPTR, SPTR);
417418
void dup_sym(int, struct SYM *);
418419
int insert_dup_sym(int);
419420
int get_align_desc(int, int);

tools/flang1/utils/symtab/symtab.n

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,9 @@ for this symbol.
15921592
.lp
15931593
.ul
15941594
Flags
1595+
.FL IS_PROC_PTR_IFACE f117
1596+
This is set when this procedure symbol is used as an interface for a procedure
1597+
pointer. IS_INTERFACE should also be set in this case.
15951598
.FL SEPARATEMP
15961599
MODULE SUBROUTINE, MODULE FUNCTION for a separate module procedure.
15971600
.FL TBP_BOUND_TO_SMP f112

tools/flang2/flang2exe/ll_ftn.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "cgmain.h"
3737
#include "symfun.h"
3838

39+
static SPTR create_display_temp_arg(DTYPE ref_dtype);
40+
3941
/* debug switches:
4042
-Mq,11,16 dump ili right before ILI -> LLVM translation
4143
-Mq,12,16 provides dinit info, ilt trace, and some basic preprocessing info
@@ -233,6 +235,21 @@ gen_ref_arg(SPTR param_sptr, SPTR func_sptr, LL_Type *ref_dummy, int param_num,
233235
addag_llvm_argdtlist(gblsym, param_num, param_sptr, llt);
234236
}
235237

238+
/** \brief Create a procedure DUMMY argument to hold a closure/display pointer.
239+
*
240+
* \param ref_dtype is a dtype for the display argument.
241+
*
242+
* \return the symbol table pointer of the newly created display argument.
243+
*/
244+
static SPTR
245+
create_display_temp_arg(DTYPE ref_dtype)
246+
{
247+
SPTR display_temp = getccsym('S', gbl.currsub, ST_VAR);
248+
SCP(display_temp, SC_DUMMY);
249+
DTYPEP(display_temp, ref_dtype);
250+
return display_temp;
251+
}
252+
236253
void
237254
ll_process_routine_parameters(SPTR func_sptr)
238255
{
@@ -325,14 +342,13 @@ ll_process_routine_parameters(SPTR func_sptr)
325342
display_temp = aux.curr_entry->display;
326343
DTYPEP(display_temp, ref_dtype); /* fake type */
327344
} else {
328-
display_temp = getccsym('S', gbl.currsub, ST_VAR);
329345
/* we won't make type as at the time we generate the prototype, we don't
330-
* know
331-
* what members it has.
346+
* know what members it has.
332347
*/
333-
SCP(display_temp, SC_DUMMY);
334-
DTYPEP(display_temp, ref_dtype); /* fake type */
348+
display_temp = create_display_temp_arg(ref_dtype);
335349
}
350+
} else if (IS_PROC_PTR_IFACEG(func_sptr)) {
351+
display_temp = create_display_temp_arg(ref_dtype);
336352
}
337353

338354
if (fval) {

tools/flang2/flang2exe/upper.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,7 @@ read_symbol(void)
20452045
int alldefaultinit;
20462046
int tpalloc, procdummy, procdesc, has_opts;
20472047
SPTR assocptr, ptrtarget;
2048+
int prociface;
20482049
ISZ_T address, size;
20492050
SPTR sptr = getSptrVal("symbol");
20502051
bool has_alias = false;
@@ -2764,7 +2765,7 @@ read_symbol(void)
27642765
tpalloc = getbit("tpalloc");
27652766
assocptr = getSptrVal("assocptr");
27662767
ptrtarget = getSptrVal("ptrtarget");
2767-
2768+
prociface = getbit("prociface");
27682769
newsptr = get_or_create_symbol(sptr);
27692770

27702771
STYPEP(newsptr, stype);
@@ -2812,6 +2813,7 @@ read_symbol(void)
28122813
if (assocptr > NOSYM || ptrtarget > NOSYM) {
28132814
PTR_INITIALIZERP(newsptr, 1);
28142815
}
2816+
IS_PROC_PTR_IFACEP(newsptr, prociface);
28152817
break;
28162818

28172819
case ST_NML:
@@ -2944,6 +2946,7 @@ read_symbol(void)
29442946
descriptor = (sclass == SC_DUMMY) ? getSptrVal("descriptor") : SPTR_NULL;
29452947
assocptr = getSptrVal("assocptr");
29462948
ptrtarget = getSptrVal("ptrtarget");
2949+
prociface = getbit("prociface");
29472950

29482951
if (paramcount == 0) {
29492952
dpdsc = 0;
@@ -3123,6 +3126,7 @@ read_symbol(void)
31233126
if (assocptr > NOSYM || ptrtarget > NOSYM) {
31243127
PTR_INITIALIZERP(newsptr, 1);
31253128
}
3129+
IS_PROC_PTR_IFACEP(newsptr, prociface);
31263130
break;
31273131

31283132
case ST_GENERIC:

tools/flang2/flang2exe/upper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@
144144
* 20.1 -- 1.55
145145
* All of 1.54 +
146146
* pass elemental field for subprogram when emitting ST_ENTRY.
147+
*
148+
* For ST_PROC, receive IS_PROC_PTR_IFACE flag.
147149
*/
148150

149151
#include "gbldefs.h"

0 commit comments

Comments
 (0)