Skip to content

Commit 5670a43

Browse files
committed
Fix an issue with final subroutines and shared libraries
The problem occurs when the compiler tries to finalize a type extended object that's defined in a shared library. Pointers to its parent type descriptors are defined before the object's type descriptor. Using a negative pointer offet from the object's type descriptor object to reference its parent pointers is incorrect. In a shared library, the dynamic linker may not load these groups of pointers if they are not directly referenced. To fix this problem, we add a "parent pointer" label in front of the parent pointers and use this label to access the parent pointers instead of a negative offset. This requires that we add this label to the type descriptor. So, we took over the unused but reserved "constructor" field in the type descriptor. For backward compatibility, we will use the negative offset if the parent pointer field is NULL.
1 parent 8efdbb1 commit 5670a43

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

runtime/flang/type.c

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2010-2019, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@ static struct type_desc *I8(__f03_ty_to_id)[];
3030
void ENTF90(SET_INTRIN_TYPE, set_intrin_type)(F90_Desc *dd,
3131
__INT_T intrin_type);
3232

33+
static TYPE_DESC * get_parent_pointer(TYPE_DESC *src_td, __INT_T level);
34+
3335
#define ARG1_PTR 0x1
3436
#define ARG1_ALLOC 0x2
3537
#define ARG2_PTR 0x4
@@ -135,8 +137,7 @@ ENTF90(EXTENDS_TYPE_OF, extends_type_of)
135137
return GET_DIST_TRUE_LOG;
136138

137139
if (atd->obj.level > btd->obj.level) {
138-
__INT_T offset = (btd->obj.level + 1) * sizeof(__POINT_T);
139-
TYPE_DESC *parent = *((TYPE_DESC **)(((char *)atd) - offset));
140+
TYPE_DESC *parent = get_parent_pointer(atd, btd->obj.level+1);
140141
if (btd == parent)
141142
return GET_DIST_TRUE_LOG;
142143
}
@@ -245,8 +246,7 @@ ENTF90(KEXTENDS_TYPE_OF, kextends_type_of)
245246
return GET_DIST_TRUE_LOG;
246247

247248
if (atd->obj.level > btd->obj.level) {
248-
__INT_T offset = (btd->obj.level + 1) * sizeof(__POINT_T);
249-
TYPE_DESC *parent = *((TYPE_DESC **)(((char *)atd) - offset));
249+
TYPE_DESC *parent = get_parent_pointer(atd, btd->obj.level+1);
250250
if (btd == parent)
251251
return GET_DIST_TRUE_LOG;
252252
}
@@ -310,6 +310,50 @@ ENTF90(KGET_OBJECT_SIZE, kget_object_size)(F90_Desc *d)
310310
return (__INT8_T)(td ? td->obj.size : od->size);
311311
}
312312

313+
/** \brief Returns a type descriptor pointer of a specified ancestor of
314+
* a type descriptor.
315+
*
316+
* \param src_td is the type descriptor used to locate the ancestor type
317+
* type descriptor.
318+
* \param level specifies the heirarchical position in the inheritance graph
319+
* of the desired ancestor type descriptor. To find its immediate
320+
* parent, specify a level equal to src_td's level.
321+
*
322+
* \return a type descriptor representing the ancestor or NULL if there is no
323+
* ancestor.
324+
*/
325+
static TYPE_DESC *
326+
get_parent_pointer(TYPE_DESC *src_td, __INT_T level)
327+
{
328+
329+
__INT_T offset, src_td_level;
330+
TYPE_DESC *parent;
331+
332+
if (level <= 0 || src_td == NULL)
333+
return NULL;
334+
335+
src_td_level = src_td->obj.level;
336+
if (src_td_level < 0 || level > src_td_level)
337+
return NULL;
338+
339+
if (src_td->parents != NULL) {
340+
/* The parents field is filled in, so use it to get the desired parent */
341+
offset = (src_td_level - level) * sizeof(__POINT_T);
342+
parent = *((TYPE_DESC **)(((char *)src_td->parents) + offset));
343+
} else {
344+
/* The parents field is not filled in, so find the parent from the
345+
* src_td base pointer. The parents field is not filled in
346+
* when a type descriptor is created with an older compiler.
347+
* Note: This method does not always work if the type descriptor is
348+
* defined in a shared library.
349+
*/
350+
offset = level * sizeof(__POINT_T);
351+
parent = *((TYPE_DESC **)(((char *)src_td) - offset));
352+
}
353+
354+
return parent;
355+
356+
}
313357
static void
314358
process_final_procedures(char *area, F90_Desc *sd)
315359
{
@@ -408,8 +452,9 @@ process_final_procedures(char *area, F90_Desc *sd)
408452

409453
if (((F90_Desc *)src_td)->tag == __POLY && src_td->obj.level > 0) {
410454
/* process parent finals */
411-
__INT_T offset = (src_td->obj.level) * sizeof(__POINT_T);
412-
TYPE_DESC *parent = *((TYPE_DESC **)(((char *)src_td) - offset));
455+
TYPE_DESC *parent = get_parent_pointer(src_td, src_td->obj.level);
456+
457+
413458

414459
if (rank > 0) {
415460
int i;
@@ -910,14 +955,12 @@ void I8(__fort_dump_type)(TYPE_DESC *d)
910955
fprintf(__io_stderr(), "Size: %d\n", d->obj.size);
911956
fprintf(__io_stderr(), "Type Descriptor:\n\t'%s'\n", d->name);
912957
if (d->obj.level > 0) {
913-
TYPE_DESC *parent;
914958
__INT_T offset, level;
915959
fprintf(__io_stderr(), "(Child Type)\n");
916960
fprintf(__io_stderr(), "Parent Descriptor%s\n",
917961
(d->obj.level == 1) ? ":" : "s:");
918962
for (level = d->obj.level - 1; level >= 0; --level) {
919-
offset = (level + 1) * sizeof(__POINT_T);
920-
TYPE_DESC *parent = *((TYPE_DESC **)(((char *)d) - offset));
963+
TYPE_DESC *parent = get_parent_pointer(d, level+1);
921964
fprintf(__io_stderr(), "\t'%s'\n", parent->name);
922965
}
923966

runtime/flang/type.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2010-2019, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@ struct object_desc {
120120
struct type_desc /* extends(OBJECT_DESC) */ {
121121
OBJECT_DESC obj; /**< parent object_desc */
122122
VTABLE(func_table); /**< pointer to virtual function table */
123-
VTABLE(constructor); /**< reserved */
123+
POINT(TYPE_DESC, parents); /**< pointer to parent type descriptor list */
124124
FINAL_TABLE(finals); /**< pointer to final procedures table */
125125
POINT(LAYOUT_DESC, layout); /**< pointer to layout descriptor */
126126
char name[MAX_TYPE_NAME + 1];/**< null terminated user defined name of type */

tools/flang2/flang2exe/llassem.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2561,7 +2561,17 @@ write_typedescs(void)
25612561
put_ll_table_addr(sname, "$vft", false, vft,
25622562
ll_feature_explicit_gep_load_type(&cpu_llvm_module->ir));
25632563
fprintf(ASMFIL, ",\n");
2564-
fprintf(ASMFIL, " i8* null,\n"); /* 0 */
2564+
2565+
/* Pointer to parent list */
2566+
if (level > 0) {
2567+
fprintf(ASMFIL,
2568+
" i8* bitcast(i8* getelementptr(i8, i8* "
2569+
"bitcast(%%struct%s$parents* @%s$parents to i8*), i32 0) to i8*)"
2570+
",\n", name, name);
2571+
} else {
2572+
fprintf(ASMFIL, " i8* null,\n"); /* 0 */
2573+
}
2574+
25652575

25662576
/* Pointer to finalizer table (always same size) */
25672577
fprintf(ASMFIL, " ");

0 commit comments

Comments
 (0)