Skip to content

Commit a0503d9

Browse files
committed
Add options for generating contiguous pointer checks
Make sure a pointer target or actual argument is contiguous when the destination pointer or dummy argument has the contiguous attribute. Right now, the checks are enabled through the following XBITs: XBIT(54,0x40) - enable the check for pointer assignments and actual arguments inside callees. XBIT(54,0x80) - enable the check at call-sites. XBIT(54,0x100) - use an alternate inline check (see xflag.n for more information). XBIT(54,0x200) - do not flag null pointer targets as noncontiguous.
1 parent 2f12861 commit a0503d9

File tree

10 files changed

+346
-12
lines changed

10 files changed

+346
-12
lines changed

runtime/flang/rdst.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ I8(local_copy)(char *db, F90_Desc *dd, __INT_T doffset, char *ab,
220220
}
221221
}
222222

223+
/** \brief check if a descriptor is associated with a non-contiguous
224+
* section.
225+
*
226+
* \param a is the descriptor we are checking.
227+
* \param dim is the rank of the array we are checking.
228+
*
229+
* \returns 0 if contiguous, else the dimension that is non-contiguous.
230+
*/
223231
__INT_T
224232
I8(is_nonsequential_section)(F90_Desc *a, __INT_T dim)
225233
{
@@ -233,7 +241,7 @@ I8(is_nonsequential_section)(F90_Desc *a, __INT_T dim)
233241
for (i = 0; i < dim; i++) {
234242
SET_DIM_PTRS(ad, a, i);
235243
if (F90_DPTR_LSTRIDE_G(ad) != tmp_lstride || F90_DPTR_SSTRIDE_G(ad) != 1) {
236-
is_nonseq_section = 1;
244+
is_nonseq_section = i + 1;
237245
break;
238246
}
239247
tmp_lstride *= F90_DPTR_EXTENT_G(ad);
@@ -2744,3 +2752,60 @@ ENTF90(IS_CONTIGUOUS, is_contiguous)(char *ab, F90_Desc *ad)
27442752
return GET_DIST_TRUE_LOG;
27452753
}
27462754

2755+
/** \brief Print a contiguous error message and abort.
2756+
*
2757+
* This function will also call is_nonsequential_section() to get the
2758+
* first dimension of the array that is non-contiguous and include it in the
2759+
* error message.
2760+
*
2761+
* \param ptr is the pointer we are checking.
2762+
* \param pd is the descriptor we are checking.
2763+
* \param lineno is the source line number we are checking.
2764+
* \param ptrnam is the name of pointer, null-terminated string.
2765+
* \param srcfil is the name of source file, null-terminated string.
2766+
* \param flags is currently 1 when ptr is an optional argument, else 0.
2767+
*/
2768+
void
2769+
ENTF90(CONTIGERROR, contigerror)(void *ptr, F90_Desc *pd, __INT_T lineno,
2770+
char *ptrnam, char *srcfil, __INT_T flags)
2771+
{
2772+
char str[200];
2773+
int dim;
2774+
2775+
if (flags == 1 && ptr == NULL) {
2776+
/* ignore non-present optional argument */
2777+
return;
2778+
}
2779+
dim = I8(is_nonsequential_section)(pd, F90_RANK_G(pd));
2780+
sprintf(str, "Runtime Error at %s, line %d: Pointer assignment of "
2781+
"noncontiguous target (dimension %d) to CONTIGUOUS pointer "
2782+
"%s\n", srcfil, lineno, dim, ptrnam);
2783+
__fort_abort(str);
2784+
}
2785+
2786+
/** \brief Check whether a pointer is associated with a contiguous array object.
2787+
*
2788+
* If the pointer is not associated with a contiguous array object, then a
2789+
* message is printed to stderr and the user program aborts.
2790+
*
2791+
* \param ptr is the pointer we are checking.
2792+
* \param pd is the descriptor we are checking.
2793+
* \param lineno is the source line number we are checking.
2794+
* \param ptrnam is the name of pointer, null-terminated string.
2795+
* \param srcfil is the name of source file, null-terminated string.
2796+
* \param flags is currently 1 when ptr is an optional argument, else 0.
2797+
*/
2798+
void
2799+
ENTF90(CONTIGCHK, contigchk)(void *ptr, F90_Desc *pd, __INT_T lineno,
2800+
char *ptrnam, char *srcfil, __INT_T flags)
2801+
{
2802+
if (flags == 1 && ptr == NULL) {
2803+
/* ignore non-present optional argument */
2804+
return;
2805+
}
2806+
2807+
if (!(ENTF90(IS_CONTIGUOUS, is_contiguous)(ptr, pd))) {
2808+
ENTF90(CONTIGERROR, contigerror)(ptr, pd, lineno, ptrnam, srcfil, flags);
2809+
}
2810+
}
2811+

tools/flang1/flang1exe/dpm_out.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2639,6 +2639,22 @@ newargs_for_entry(int this_entry)
26392639
NEWDSCP(arg, newdsc);
26402640
}
26412641
}
2642+
if (XBIT(54, 0x40) && CONTIGATTRG(arg)
2643+
&& STYPEG(newdsc) != ST_UNKNOWN
2644+
) {
2645+
/* Generate contiguity check on this argument.
2646+
*
2647+
* NOTE: For LLVM targets, this function gets called by
2648+
* newargs_for_llvmiface() to set up placeholder descriptor
2649+
* arguments in the interface. We do not want to
2650+
* generate contiguity checks in this case since an interface
2651+
* block is non-executable code. The sym_get_arg_sec() function
2652+
* above returns a newdsc without any STYPE when we're processing
2653+
* an interface. Therefore, we check whether STYPEG(newdsc) != ST_UNKNOWN.
2654+
*/
2655+
int ast = mk_id(arg);
2656+
gen_contig_check(ast, ast, newdsc, FUNCLINEG(gbl.currsub), false, Gbegin);
2657+
}
26422658
SCP(newdsc, SC_DUMMY);
26432659
OPTARGP(newdsc, OPTARGG(arg));
26442660
NEWARGP(newdsc, 0);

tools/flang1/flang1exe/rest.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,11 @@ transform_call(int std, int ast)
13561356
inface_arg = aux.dpdsc_base[dscptr + i];
13571357
needdescr = needs_descriptor(inface_arg);
13581358
/* actually, only for pointer or assumed-shape arguments dummy */
1359+
if (XBIT(54, 0x80) && inface_arg > NOSYM && ast_is_sym(ele) &&
1360+
needs_descriptor(memsym_of_ast(ele))) {
1361+
/* Generate contiguity check at call-site */
1362+
gen_contig_check(mk_id(inface_arg), ele, 0, gbl.lineno, true, std);
1363+
}
13591364
}
13601365
if (ele == 0) {
13611366
ARGT_ARG(newargt, newi) = ele;

tools/flang1/flang1exe/rte.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,41 @@ get_header_member(int sdsc, int info)
827827
return ast;
828828
}
829829

830+
831+
/** \brief Generate an AST for accessing a particular field in a descriptor
832+
* header.
833+
*
834+
* Note: This is similar to get_header_member() above except it also
835+
* operates on descriptors that are embedded in derived type objects.
836+
*
837+
* \param parent is the ast of the expression with the descriptor that
838+
* we want to access. This is needed if the descriptor is embedded
839+
* in a derived type object.
840+
* \param sdsc is the symbol table pointer of the descriptor we want to
841+
* access.
842+
* \param info is the field we want to access in the descriptor.
843+
*
844+
* \return an ast expression of the descriptor access.
845+
*/
846+
int
847+
get_header_member_with_parent(int parent, int sdsc, int info)
848+
{
849+
int ast;
850+
int subs[1];
851+
852+
#if DEBUG
853+
if (!sdsc)
854+
interr("get_header_member, blank static descriptor", 0, 3);
855+
else if (STYPEG(sdsc) != ST_ARRDSC && STYPEG(sdsc) != ST_DESCRIPTOR &&
856+
DTY(DTYPEG(sdsc)) != TY_ARRAY)
857+
interr("get_header_member, bad static descriptor", sdsc, 3);
858+
#endif
859+
subs[0] = mk_isz_cval(info, astb.bnd.dtype);
860+
ast = mk_subscr(check_member(parent, mk_id(sdsc)), subs, 1, astb.bnd.dtype);
861+
return ast;
862+
}
863+
864+
830865
static int
831866
get_array_rank(int sdsc)
832867
{

tools/flang1/flang1exe/semant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ int do_distbegin(DOINFO *, int, int);
15171517
/* semutil.c */
15181518
void check_derived_type_array_section(int);
15191519
int add_ptr_assign(int, int, int);
1520+
void gen_contig_check(int dest, int src, SPTR sdsc, int lineno, bool cs, int std);
15201521
int collapse_begin(DOINFO *);
15211522
int collapse_add(DOINFO *);
15221523
void link_parents(STSK *, int);

0 commit comments

Comments
 (0)