From 3e0a302bce48a010f71cd8199bd678e2df21c345 Mon Sep 17 00:00:00 2001 From: HuQingYuan Date: Wed, 25 Oct 2023 13:53:55 +0800 Subject: [PATCH] Add patch for add align pragma for scalar variables --- ...dd-align-pragma-for-scalar-variables.patch | 833 ++++++++++++++++++ flang.spec | 6 +- 2 files changed, 838 insertions(+), 1 deletion(-) create mode 100644 25-add-align-pragma-for-scalar-variables.patch diff --git a/25-add-align-pragma-for-scalar-variables.patch b/25-add-align-pragma-for-scalar-variables.patch new file mode 100644 index 0000000..a90821b --- /dev/null +++ b/25-add-align-pragma-for-scalar-variables.patch @@ -0,0 +1,833 @@ +From 05c275912c20ff744b7434e5cabed43ff042a3eb Mon Sep 17 00:00:00 2001 +From: HuQingYuan +Date: Wed, 25 Oct 2023 13:33:21 +0800 +Subject: [PATCH] add align pragma for scalar variables + +--- + test/directives/align_pragma_function_var.f90 | 46 ++++++++++++ + .../align_pragma_local_var_init.f90 | 14 ++++ + .../align_pragma_local_var_no_init.f90 | 12 +++ + .../align_pragma_module_var_init.f90 | 51 +++++++++++++ + .../align_pragma_module_var_no_init.f90 | 42 +++++++++++ + .../align_pragma_subroutine_var.f90 | 36 +++++++++ + tools/flang1/flang1exe/exterf.c | 4 + + tools/flang1/flang1exe/global.h | 10 +++ + tools/flang1/flang1exe/lowersym.c | 6 ++ + tools/flang1/flang1exe/main.c | 2 + + tools/flang1/flang1exe/parser.c | 9 ++- + tools/flang1/flang1exe/scan.c | 15 ++++ + tools/flang1/flang1exe/symtab.c | 75 +++++++++++++++++++ + tools/flang1/utils/symtab/symtab.in.h | 5 ++ + tools/flang1/utils/symtab/symtab.n | 4 + + tools/flang2/flang2exe/llassem.cpp | 56 +++++++++++--- + tools/flang2/flang2exe/upper.cpp | 51 ++++++++++++- + tools/flang2/utils/symtab/symtab.n | 4 + + tools/shared/pragma.c | 8 +- + 19 files changed, 437 insertions(+), 13 deletions(-) + create mode 100644 test/directives/align_pragma_function_var.f90 + create mode 100644 test/directives/align_pragma_local_var_init.f90 + create mode 100644 test/directives/align_pragma_local_var_no_init.f90 + create mode 100644 test/directives/align_pragma_module_var_init.f90 + create mode 100644 test/directives/align_pragma_module_var_no_init.f90 + create mode 100644 test/directives/align_pragma_subroutine_var.f90 + +diff --git a/test/directives/align_pragma_function_var.f90 b/test/directives/align_pragma_function_var.f90 +new file mode 100644 +index 0000000..76daea2 +--- /dev/null ++++ b/test/directives/align_pragma_function_var.f90 +@@ -0,0 +1,46 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++ ++! CHECK: %struct.[[BLOCK1:STATICS[0-9]+]] = type <{ [132 x i8] }> ++! CHECK: @.[[BLOCK1]] = internal global %struct.[[BLOCK1]] <{ [132 x i8] {{[^,]+}} }>, align 128 ++integer(kind=4) function function_init() ++ !dir$ align 128 ++ integer(kind=4) :: a128 = 10 ++ !dir$ align 128 ++ integer(kind=4) :: b128 = 20 ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 128 ++ a128 = a128 + 1 ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 128 ++ b128 = b128 + 2 ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 128 ++ function_init = a128 + b128 ++end function function_init ++ ++ ++integer(kind=4) function function_no_init() ++! CHECK: {{[^=]+}} = alloca i32, align 128 ++ !dir$ align 128 ++ integer(kind=4) :: a128 ++! CHECK: {{[^=]+}} = alloca i32, align 128 ++ !dir$ align 128 ++ integer(kind=4) :: b128 ++ ++ a128 = 1 ++ b128 = 2 ++ ++ function_no_init = a128 + b128 ++end function function_no_init ++ ++ ++program MainProgram ++ implicit none ++ ++ ++ integer(kind=4) :: res ++ integer(kind=4) :: function_init ++ integer(kind=4) :: function_no_init ++ ++ res = function_init() ++ res = function_no_init() ++ ++end program MainProgram ++ +diff --git a/test/directives/align_pragma_local_var_init.f90 b/test/directives/align_pragma_local_var_init.f90 +new file mode 100644 +index 0000000..a1ae402 +--- /dev/null ++++ b/test/directives/align_pragma_local_var_init.f90 +@@ -0,0 +1,14 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++! CHECK: %struct.[[BLOCK1:STATICS[0-9]+]] = type <{ [1028 x i8] }> ++! CHECK: @.[[BLOCK1]] = internal global %struct.[[BLOCK1]] <{ [1028 x i8] {{[^,]+}} }>, align 1024 ++program MainProgram ++ implicit none ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 1024 ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 1024 ++ !dir$ align 1024 ++ integer(kind=4) :: a1024 =30 ++ !dir$ align 1024 ++ integer(kind=4) :: b1024 =40 ++ a1024 = a1024 + b1024 ++ ++end program MainProgram +diff --git a/test/directives/align_pragma_local_var_no_init.f90 b/test/directives/align_pragma_local_var_no_init.f90 +new file mode 100644 +index 0000000..fe163fd +--- /dev/null ++++ b/test/directives/align_pragma_local_var_no_init.f90 +@@ -0,0 +1,12 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++program main ++ implicit none ++! CHECK: {{[^=]+}} = alloca i64, align 256 ++! CHECK: {{[^=]+}} = alloca i64, align 256 ++ ++ !dir$ align 256 ++ integer(kind=8) :: d,e ++ ++ d=e ++ ++end program main +diff --git a/test/directives/align_pragma_module_var_init.f90 b/test/directives/align_pragma_module_var_init.f90 +new file mode 100644 +index 0000000..02fc0a3 +--- /dev/null ++++ b/test/directives/align_pragma_module_var_init.f90 +@@ -0,0 +1,51 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++ ++! CHECK: %struct.[[BLOCK1:STATICS[0-9]+]] = type <{ [260 x i8] }> ++! CHECK: %struct[[STRUCT1:[^=]+]] = type <{ [516 x i8] }> ++ ++! CHECK: @.[[BLOCK1]] = internal global %struct.[[BLOCK1]] <{ [260 x i8] {{[^,]+}} }>, align 256 ++! CHECK: @[[STRUCT1]] = global %struct[[STRUCT1]] <{ [516 x i8] {{[^,]+}} }>, align 512 ++ ++module module_align ++ implicit none ++ ++ !dir$ align 128 ++ integer :: a128 = 123 ++ ++ !dir$ align 512 ++ integer :: b512 = 234 ++ ++ interface ++ module subroutine module_interface_subroutine() ++ end subroutine module_interface_subroutine ++ end interface ++ ++end module module_align ++ ++submodule (module_align) submodule_align ++ ++contains ++ module subroutine module_interface_subroutine() ++ ++ ++ !dir$ align 256 ++ integer :: a256 = 12 ++ ++ !dir$ align 128 ++ integer :: b128 = 14 ++ ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 256 ++! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 512 ++ a128 = 12 + a256 ++ b512 = 23 + b128 ++ ++ ++ end subroutine module_interface_subroutine ++end submodule submodule_align ++ ++program MainProgram ++ ++ use module_align ++ call module_interface_subroutine() ++ ++end program MainProgram +diff --git a/test/directives/align_pragma_module_var_no_init.f90 b/test/directives/align_pragma_module_var_no_init.f90 +new file mode 100644 +index 0000000..3bff99e +--- /dev/null ++++ b/test/directives/align_pragma_module_var_no_init.f90 +@@ -0,0 +1,42 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++! CHECK: %struct[[STRUCT1:[^=]+]] = type <{ [1028 x i8] }> ++! CHECK: @[[STRUCT1]] = common global %struct[[STRUCT1]] zeroinitializer, align 1024 ++module MyModule ++ !dir$ align 512 ++ integer(kind=4) :: a512 ++ !dir$ align 512 ++ integer(kind=4) :: b512 ++ ++ integer, dimension (5,5) :: c ++ ++ !dir$ align 128 ++ integer(kind=4) :: d128 ++ ++ integer(kind=4) :: e4 ++ ++ !dir$ align 1024 ++ integer(kind=4) :: f1024 ++ ++contains ++ ++ subroutine InitializeModuleVariables() ++ ! 在子程序中初始化模块变量 ++ a512 = 11 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 512 ++ b512 = 12 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 572 ++ c(3, 3) = 13 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 640 ++ d128 = 14 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 644 ++ e4 = 15 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 1024 ++ f1024 = 16 ++ end subroutine InitializeModuleVariables ++ ++end module MyModule ++ ++program MainProgram ++ use MyModule ++ call InitializeModuleVariables() ++end program MainProgram +diff --git a/test/directives/align_pragma_subroutine_var.f90 b/test/directives/align_pragma_subroutine_var.f90 +new file mode 100644 +index 0000000..7834014 +--- /dev/null ++++ b/test/directives/align_pragma_subroutine_var.f90 +@@ -0,0 +1,36 @@ ++! RUN: %flang -O0 -S -emit-llvm %s -o - | FileCheck %s ++ ++program MainProgram ++ implicit none ++ ++ call subroutine_init() ++ call subroutine_no_init() ++ ++end program MainProgram ++ ++ ++! CHECK: %struct.[[BLOCK1:STATICS[0-9]+]] = type <{ [2052 x i8] }> ++! CHECK: @.[[BLOCK1]] = internal global %struct.[[BLOCK1]] <{ [2052 x i8] {{[^,]+}} }>, align 2048 ++subroutine subroutine_init() ++ !dir$ align 2048 ++ integer(kind=4) :: a2048 = 10 ++ !dir$ align 2048 ++ integer(kind=4) :: b2048 = 20 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 2048 ++ ! CHECK: {{[^g]+}}getelementptr {{[^,]+}}, {{[^,]+}}, i64 2048 ++ a2048 = a2048 + 1 ++ b2048 = b2048 + 2 ++ ++end subroutine subroutine_init ++ ++subroutine subroutine_no_init() ++ ! CHECK: {{[^=]+}} = alloca i32, align 1024 ++ !dir$ align 1024 ++ integer(kind=4) :: a1024 ++ ! CHECK: {{[^=]+}} = alloca i32, align 1024 ++ !dir$ align 1024 ++ integer(kind=4) :: b1024 ++ a1024 = 1 ++ b1024 = 2 ++ ++end subroutine subroutine_no_init +diff --git a/tools/flang1/flang1exe/exterf.c b/tools/flang1/flang1exe/exterf.c +index 21e8444..cae79c9 100644 +--- a/tools/flang1/flang1exe/exterf.c ++++ b/tools/flang1/flang1exe/exterf.c +@@ -2259,6 +2259,10 @@ export_symbol(int sptr) + + scope = SCOPEG(sptr); + stype = STYPEG(sptr); ++ if (stype == ST_VAR) { ++ /* Match the variable with the corresponding align pragma before writing out symbol info */ ++ match_align_pragma(sptr); ++ } + if (!exportmode && stype == ST_UNKNOWN && sptr == gbl.sym_nproc) { + return; + } +diff --git a/tools/flang1/flang1exe/global.h b/tools/flang1/flang1exe/global.h +index 947cc0d..a528627 100644 +--- a/tools/flang1/flang1exe/global.h ++++ b/tools/flang1/flang1exe/global.h +@@ -35,6 +35,13 @@ typedef enum { + RU_BDATA, + } RU_TYPE; + ++/* record an align pragma's alignment value, scope and lineno. */ ++typedef struct ALIGN_PRAGMA { ++ int lineno; ++ int scope; ++ int alignment; ++} ALIGN_PRAGMA; ++ + typedef struct { + int maxsev; /* maximum error severity for this compile */ + int lineno; /* current source line number */ +@@ -134,6 +141,9 @@ typedef struct { + LOGICAL denorm; /* enforce denorm for the current subprogram */ + LOGICAL inomptarget; /* set if it is OpenMP's target region*/ + LOGICAL empty_contains; /* if TRUE, CONTAINS clause has an empty body */ ++ ++ ALIGN_PRAGMA *align_pragma_table; /* store all align pragmas in this unit */ ++ unsigned align_pragma_size; /* Current number of align pragmas */ + } GBL; + + #undef MAXCPUS +diff --git a/tools/flang1/flang1exe/lowersym.c b/tools/flang1/flang1exe/lowersym.c +index 0285d1a..cdc2db9 100644 +--- a/tools/flang1/flang1exe/lowersym.c ++++ b/tools/flang1/flang1exe/lowersym.c +@@ -3814,6 +3814,11 @@ lower_symbol(int sptr) + putbit("f90pointer", 0); /* F90POINTER will denote the POINTER attribute */ + /* but first need to remove FE legacy use */ + putbit("procdescr", IS_PROC_DESCRG(sptr)); ++ if (stype == ST_VAR) { ++ /* print the align pragma value of var */ ++ putval("align-pragma", ALIGN_PRAGMAG(sptr)); ++ } ++ + strip = 1; + break; + +@@ -3868,6 +3873,7 @@ lower_symbol(int sptr) + putbit("copyin", 0); + putbit("resident", 0); + putbit("link", 0); ++ putval("align-pragma", ALIGN_PRAGMAG(sptr)); /* print the align pragma value of cmblk */ + if (BLANKCG(sptr)) { + namelen = 6; + name = "_BLNK_"; +diff --git a/tools/flang1/flang1exe/main.c b/tools/flang1/flang1exe/main.c +index 70290d7..bfa5443 100644 +--- a/tools/flang1/flang1exe/main.c ++++ b/tools/flang1/flang1exe/main.c +@@ -205,7 +205,9 @@ main(int argc, char *argv[]) + break; + } else { + TR(DNAME " PARSER begins\n") ++ reinit_align_pragma(); /* need to reinit align pragma table before parsing a unit*/ + parser(); /* parse and do semantic analysis */ ++ reinit_align_pragma(); /* need to reinit align pragma table after parsing a unit*/ + set_tag(); + } + gbl.func_count++; +diff --git a/tools/flang1/flang1exe/parser.c b/tools/flang1/flang1exe/parser.c +index 21b1ec0..e2fce4d 100644 +--- a/tools/flang1/flang1exe/parser.c ++++ b/tools/flang1/flang1exe/parser.c +@@ -95,7 +95,7 @@ parser(void) + */ + if (maxsev >= 3) + summary(FALSE, FALSE); +- if (gbl.rutype == RU_BDATA) ++ if (gbl.rutype == RU_BDATA) { + /* + * A module specification part was parsed. Either: + * 1. a CONTAINS within the module terminated the first +@@ -104,7 +104,11 @@ parser(void) + * Now, just produce the module-created blockdata - the second + * parse isn't performed. + */ ++ /* match all align pragmas with their corresponding variables ++ * before exiting parser */ ++ match_align_pragma(0); + return; ++ } + /* + * At this point, either: + * 1. a module specification part with errors was parsed, or +@@ -169,6 +173,9 @@ parser(void) + sem.mod_sym = 0; + sem.submod_sym = 0; + } ++ /* match all align pragmas with their corresponding variables ++ * before exiting parser */ ++ match_align_pragma(0); + } + + static void +diff --git a/tools/flang1/flang1exe/scan.c b/tools/flang1/flang1exe/scan.c +index 6c24adb..deb379e 100644 +--- a/tools/flang1/flang1exe/scan.c ++++ b/tools/flang1/flang1exe/scan.c +@@ -994,6 +994,21 @@ again: + *p = '\0'; + } + put_astfil(FR_PRAGMA, currc, TRUE); ++ /* parse and store a new align pragma in first parse */ ++ if (strncmp(currc, "cray", 4) == 0) { ++ char *next_tok = currc + 4; ++ while (*next_tok == ' ' || *next_tok == '\t') { ++ next_tok++; ++ } ++ if (strncmp(next_tok, "align", 5) == 0) { ++ unsigned old_align_pragma_size = gbl.align_pragma_size; ++ p_pragma(currc, gbl.lineno); ++ if (old_align_pragma_size != gbl.align_pragma_size) { ++ ALIGN_PRAGMA *new_align_pragma_ptr = gbl.align_pragma_table + gbl.align_pragma_size - 1; ++ new_align_pragma_ptr->lineno = curr_line; /* set align pragma's lineno to the next line */ ++ } ++ } ++ } + if (XBIT(49, 0x1040000) && strncmp(currc, "cray", 4) == 0) { + int len; + /* T3D/T3E or C90 Cray targets */ +diff --git a/tools/flang1/flang1exe/symtab.c b/tools/flang1/flang1exe/symtab.c +index 5975bd6..7986560 100644 +--- a/tools/flang1/flang1exe/symtab.c ++++ b/tools/flang1/flang1exe/symtab.c +@@ -60,6 +60,7 @@ static void cng_inttyp(int, int); + static void cng_specific(int, int); + static void generate_type_mismatch_errors(SPTR s1, SPTR s2); + static void update_arrdsc(SPTR s, DEC_DEF_MAP *smap, int num_dummies); ++static void adjust_cmblk_align(int var_sptr); /* adjust cmblk's cmblk_align by var's align_pragma */ + /* entry hack? */ + static ENTRY onlyentry; + +@@ -1294,6 +1295,11 @@ symdentry(FILE *file, int sptr) + *p = '\0'; + fprintf(dfil, "declared bounds %s\n", line); + } ++ ++ /* print variable's align pragma value */ ++ if (stype == ST_VAR) { ++ fprintf(dfil, "align_pragma:%d\n", ALIGN_PRAGMAG(sptr)); ++ } + break; + + case ST_STAG: +@@ -3242,6 +3248,9 @@ void rw_sym_state(RW_ROUTINE, RW_FILE) + RW_SCALAR(stb.firstusym); + RW_SCALAR(stb.stg_avail); + RW_SCALAR(stb.stg_cleared); ++ ++ /* match variables and align pragmas before reading or writing symbols */ ++ match_align_pragma(0); + RW_FD(stb.stg_base, SYM, stb.stg_avail); + + RW_SCALAR(stb.namavl); +@@ -3517,3 +3526,69 @@ generate_type_mismatch_errors(SPTR s1, SPTR s2) { + error(1058, ERR_Severe, gbl.lineno, SYMNAME(s1), NULL); + } + ++void ++reinit_align_pragma(void) { ++ FREE(gbl.align_pragma_table); ++ gbl.align_pragma_size = 0; ++} ++ ++/** \brief ++ * When sym_sptr is non-zero, match the variable indexed by sym_sptr and its align pragma. ++ * when sym_sptr is zero, match all align pragmas and their corresponding variables. ++ */ ++void ++match_align_pragma(int sym_sptr) { ++ if (stb.firstusym == SPTR_NULL || stb.firstusym == NME_NULL) { ++ return; ++ } ++ for (int i = 0; i < gbl.align_pragma_size; i++) { ++ ALIGN_PRAGMA *align_pragma_ptr = gbl.align_pragma_table + i; ++ ++ if (sym_sptr != 0) { ++ /* match the variable indexed by sym_sptr and its corresponding align pragma */ ++ if (sym_sptr >= stb.firstusym && sym_sptr <= SPTR_MAX && sym_sptr < stb.stg_avail) { ++ int sym_scope = SCOPEG(sym_sptr); ++ int sym_type = STYPEG(sym_sptr); ++ int sym_lineno = LINENOG(sym_sptr); ++ if (align_pragma_ptr->scope == sym_scope && sym_type == ST_VAR ++ && align_pragma_ptr->lineno == sym_lineno) { ++ // set variable's ALIGN_PRAGMA field ++ ALIGN_PRAGMAP(sym_sptr, align_pragma_ptr->alignment); ++ if (SCG(sym_sptr) == SC_CMBLK) { ++ adjust_cmblk_align(sym_sptr); ++ } ++ } ++ } ++ } else { ++ /* match all align pragmas and their corresponding variables */ ++ for (unsigned int sptr = stb.firstusym; sptr < stb.stg_avail; sptr++) { ++ int sym_scope = SCOPEG(sptr); ++ int sym_type = STYPEG(sptr); ++ int sym_lineno = LINENOG(sptr); ++ if (align_pragma_ptr->scope == sym_scope && sym_type == ST_VAR ++ && align_pragma_ptr->lineno == sym_lineno) { ++ // set variable's ALIGN_PRAGMA field ++ ALIGN_PRAGMAP(sptr, align_pragma_ptr->alignment); ++ if (SCG(sptr) == SC_CMBLK) { ++ adjust_cmblk_align(sptr); ++ } ++ } ++ } ++ } ++ } ++} ++ ++void ++adjust_cmblk_align(int var_sptr) { ++ int cmblk_sptr = CMBLKG(var_sptr); ++ if (cmblk_sptr < stb.firstusym || cmblk_sptr >= stb.stg_avail) { ++ return; ++ } ++ /* Set the cmblk's align pragma value to ++ * the maximum of its variables' align pragma values. ++ * */ ++ unsigned align_pragma_bytes = ALIGN_PRAGMAG(var_sptr); ++ if (CMBLK_ALIGNG(cmblk_sptr) < align_pragma_bytes) { ++ CMBLK_ALIGNP(cmblk_sptr, align_pragma_bytes); ++ } ++} +\ No newline at end of file +diff --git a/tools/flang1/utils/symtab/symtab.in.h b/tools/flang1/utils/symtab/symtab.in.h +index f8c820a..144d3f6 100644 +--- a/tools/flang1/utils/symtab/symtab.in.h ++++ b/tools/flang1/utils/symtab/symtab.in.h +@@ -480,4 +480,9 @@ bool compatible_characteristics(int psptr, int psptr2, + bool cmp_interfaces_strict(SPTR sym1, SPTR sym2, cmp_interface_flags flag); + bool is_used_by_submod(SPTR sym1, SPTR sym2); + ++ ++void match_align_pragma(int sym_sptr); /* match align_pragma and symbol */ ++ ++void reinit_align_pragma(void); /* reinit align pragma table */ ++ + #endif // SYMTAB_H_ +diff --git a/tools/flang1/utils/symtab/symtab.n b/tools/flang1/utils/symtab/symtab.n +index 37251e7..dfd80d6 100644 +--- a/tools/flang1/utils/symtab/symtab.n ++++ b/tools/flang1/utils/symtab/symtab.n +@@ -1252,6 +1252,8 @@ This field is only used for certain cases of allocatable arrays (e.g., + .cw DYNAMIC + arrays + and their descriptors). ++.SE ALIGN_PRAGMA w20 ++Store the variable's alignment value specified by align pragma in the form of '!dir$ align n'. + .SE NMCNST w30 SPTR + If the variable represents the compiler-created temporary for + a named array or structure constant, this field is the sptr +@@ -1351,6 +1353,8 @@ the ARRAY field points to the original array symbol (which is now the only + element in the new common block). + .SE RESERVED_w18 w18 + reserved ++.SE CMBLK_ALIGN w20 ++Store the block's alignment value if it has variable with align pragma. + .SE ALTNAME + Set if the common block has DVF's + also set for common blocks, module variables, subroutines , functions +diff --git a/tools/flang2/flang2exe/llassem.cpp b/tools/flang2/flang2exe/llassem.cpp +index 4ec7802..2f209c0 100644 +--- a/tools/flang2/flang2exe/llassem.cpp ++++ b/tools/flang2/flang2exe/llassem.cpp +@@ -118,6 +118,7 @@ static char * get_struct_from_dsrt(SPTR sptr, DSRT *dsrtp, ISZ_T size, + bool stop_at_sect, ISZ_T addr); + #if DEBUG + static void dump_all_dinits(void); ++static void adjust_statics_align(void); /* set the align value of static's ag */ + + static hashset_t CommonBlockInits; + #endif +@@ -1169,9 +1170,8 @@ assemble_end(void) + fprintf(ASMFIL, "@%s = %s global %%struct%s ", name, + AG_ISMOD(gblsym) ? "external" : "common", name); + +- /* handle the flang1 pragma !dir$ align +- * Here we refer common block's alignment from +- * its belonging ag's alignment ++ /* ++ * refer common block's alignment from its belonging ag's alignment + */ + align_value = AG_ALIGN(tdefsym) > align_value ? + AG_ALIGN(tdefsym) : align_value; +@@ -1524,9 +1524,8 @@ write_bss(void) + int align; + SPTR ag; + +- /* handle the flang1 pragma !dir$ align +- * Here we refer bss's alignment from +- * its belonging ag's alignment ++ /* ++ * refer bss's alignment from its belonging ag's alignment + */ + sprintf(gname, "struct%s", bss_nm); + ag = find_ag(gname); +@@ -1594,6 +1593,8 @@ write_statics(void) + int count = 0; + char *static_nm = static_name; + ++ /* set static's align value before printing */ ++ adjust_statics_align(); + if (lcl_inits) { + if (DBGBIT(5, 32)) { + fprintf(gbl.dbgfil, "write_statics:%s\n", static_nm); +@@ -1610,7 +1611,9 @@ write_statics(void) + fprintf(ASMFIL, "%%struct%s = type <{ %s }>\n", static_nm, type_only); + fprintf(ASMFIL, "@%s = %s %%struct%s <{ ", static_nm, type_str, static_nm); + process_dsrt(lcl_inits, gbl.saddr, typed, false, 0); +- fprintf(ASMFIL, " }>, align 16"); ++ /* refer static's alignment from its belonging ag's alignment */ ++ unsigned align_bytes = AG_ALIGN(gblsym) > 16 ? AG_ALIGN(gblsym) : 16; ++ fprintf(ASMFIL, " }>, align %d", align_bytes); + ll_write_object_dbg_references(ASMFIL, cpu_llvm_module, static_dbg_list); + static_dbg_list = NULL; + fputc('\n', ASMFIL); +@@ -1745,7 +1748,8 @@ write_comm(void) + fprintf(ASMFIL, " } > "); + + DSRTP(sptr, NULL); +- ++ /* refer cmblk's alignment from its belonging ag's alignment */ ++ align_value = AG_ALIGN(cmsym) > align_value ? AG_ALIGN(cmsym) : align_value; + fprintf(ASMFIL, ", align %d", align_value); + + for (cmem = CMEMFG(sptr); cmem > NOSYM; cmem = SYMLKG(cmem)) { +@@ -3206,6 +3210,10 @@ get_ag(SPTR sptr) + if (!XBIT(57, 0x10000000) && CCSYMG(sptr) && PDALNG(sptr) == 4) { + AG_ALIGN(gblsym) = max_cm_align + 1; + } ++ // write cmblk symbol's CMBLK_ALIGN to global symbol's AG_ALIGN ++ if (CMBLK_ALIGNG(sptr) > 0) { ++ AG_ALIGN(gblsym) = CMBLK_ALIGNG(sptr); ++ } + } else if ((stype == ST_ARRAY) & !CFUNCG(sptr)) { + AG_SYMLK(gblsym) = ag_other; + ag_other = gblsym; +@@ -4223,6 +4231,19 @@ unsigned + align_of_var(SPTR sptr) + { + DTYPE dtype = DTYPEG(sptr); ++ if (STYPEG(sptr) == ST_VAR) { ++ /* ++ * return var's align pragma value if align pragma value > dtype's align value ++ */ ++ int align_pragma_bytes = ALIGN_PRAGMAG(sptr); ++ if (align_pragma_bytes > 0) { ++ int standard_align_bytes = align_of(dtype); ++ if (standard_align_bytes > align_pragma_bytes) { ++ return standard_align_bytes; ++ } ++ return align_pragma_bytes; ++ } ++ } + if (!PDALN_IS_DEFAULT(sptr)) + return 1u << PDALNG(sptr); + if (QALNG(sptr)) +@@ -4303,7 +4324,10 @@ assn_static_off(SPTR sptr, DTYPE dtype, ISZ_T size) + } else { + a = align_unconstrained(dtype); + } +- ++ // in static, adjust variable's offset by its ALIGN PRAGMA ++ if (STYPEG(sptr) == ST_VAR && SCG(sptr) == SC_STATIC && ALIGN_PRAGMAG(sptr) > a) { ++ a = ALIGN_PRAGMAG(sptr) - 1; ++ } + if (DTA(dtype) > a) + a = DTA(dtype); + +@@ -6010,3 +6034,17 @@ assem_dinit(void) + /* intentionally empty */ + } + ++void ++adjust_statics_align(void) { ++ for (int sptr = stb.firstusym; sptr < stb.stg_avail; sptr++) { ++ if (STYPEG(sptr) == ST_VAR && SCG(sptr) == SC_STATIC && ALIGN_PRAGMAG(sptr) > 0) { ++ /* get static's ag by its sptr */ ++ char gname[MXIDLN + 50]; ++ sprintf(gname, "struct%s", get_llvm_name((SPTR) sptr)); ++ SPTR ag = find_ag(gname); ++ /* set the align value of static's ag */ ++ if (ALIGN_PRAGMAG(sptr) >= AG_ALIGN(ag)) ++ AG_ALIGN(ag) = ALIGN_PRAGMAG(sptr); ++ } ++ } ++} +diff --git a/tools/flang2/flang2exe/upper.cpp b/tools/flang2/flang2exe/upper.cpp +index 7ddeeac..72b05bc 100644 +--- a/tools/flang2/flang2exe/upper.cpp ++++ b/tools/flang2/flang2exe/upper.cpp +@@ -100,6 +100,7 @@ static void read_global(void); + static int read_CCFF(void); + #include "fdirect.h" + static void read_contained(void); ++static void adjust_cmblk_size(); // adjust cmblk's align and size + + typedef struct CGR_LIST { + struct CGR_LIST *next; +@@ -569,6 +570,8 @@ upper(int stb_processing) + } + fix_symbol(); + fix_datatype(); ++ /* adjust cmblk's size and variables' start addresses by ALIGN_PRAGMA of variables */ ++ adjust_cmblk_size(); + + #if DEBUG + if (DBGBIT(47, 0x200)) { +@@ -2044,6 +2047,7 @@ read_symbol(void) + SPTR sptr = getSptrVal("symbol"); + bool has_alias = false; + char *alias_name; ++ int align_pragma; + #if DEBUG + if (sptr > symbolcount) { + fprintf(stderr, "Symbol count was %d, but new symbol number is %d\n", +@@ -2189,6 +2193,10 @@ read_symbol(void) + f90pointer = getbit("f90pointer"); /* will denote the POINTER attribute */ + /* but need to remove FE legacy use */ + procdesc = getbit("procdescr"); ++ if (stype == ST_VAR) { ++ /* read variable's ALIGN_PRAGMA from stb */ ++ align_pragma = getval("align-pragma"); ++ } + newsptr = get_or_create_symbol(sptr); + if (Class) { + CLASSP(newsptr, Class); +@@ -2211,6 +2219,8 @@ read_symbol(void) + STYPEP(newsptr, ST_STRUCT); + } else { + STYPEP(newsptr, stype); ++ /* set variable's ALIGN_PRAGMA */ ++ ALIGN_PRAGMAP(newsptr, align_pragma); + } + if (Class && stype == ST_ARRAY && isdesc) { + /* put the type that this type descriptor is associated with +@@ -2397,7 +2407,8 @@ read_symbol(void) + resident = getbit("resident"); + acclink = getbit("link"); + } +- ++ /* read cmblk's ALIGN_PRAGMA from stb */ ++ align_pragma = getval("align-pragma"); + newsptr = get_or_create_symbol(sptr); + + STYPEP(newsptr, stype); +@@ -2439,7 +2450,8 @@ read_symbol(void) + ACCRESIDENTP(newsptr, resident); + ACCLINKP(newsptr, acclink); + } +- ++ /* set cmblk's CMBLK_ALIGN */ ++ CMBLK_ALIGNP(newsptr, align_pragma); + SYMLKP(newsptr, gbl.cmblks); + gbl.cmblks = newsptr; + if (modcmn && !fromMod) { +@@ -6540,3 +6552,38 @@ free_modvar_alias_list() + } + } + ++/** ++ * \brief adjust cmblk's size and variables' start addresses by ALIGN_PRAGMA of variables in cmblk ++ * The start address of a variable in the cmblk should be an integer multiple of the variable's ALIGN_PRAGMA. ++ */ ++void adjust_cmblk_size() { ++ if (stb.firstusym == SPTR_NULL || stb.firstusym == NME_NULL) { ++ return; ++ } ++ for (int sptr = stb.firstusym; sptr < stb.stg_avail; sptr++) { ++ if (STYPEG(sptr) != ST_CMBLK) { ++ continue; ++ } ++ int cmblk_sptr = sptr; ++ for (int var_sptr = CMEMFG(cmblk_sptr); ++ var_sptr >= stb.firstusym && cmblk_sptr < stb.stg_avail; var_sptr = SYMLKG(var_sptr)) { ++ if (STYPEG(var_sptr) != ST_VAR) { ++ continue; ++ } ++ unsigned align_pragma_bytes = ALIGN_PRAGMAG(var_sptr); ++ if (align_pragma_bytes <= size_of(DTYPEG(var_sptr))) { ++ continue; ++ } ++ unsigned old_var_address = ADDRESSG(var_sptr); ++ if (old_var_address % align_pragma_bytes == 0) { ++ continue; ++ } ++ unsigned new_var_address = ALIGN(old_var_address, align_pragma_bytes - 1); ++ unsigned add_offset = new_var_address - old_var_address; ++ for (int it_var = var_sptr; it_var > NOSYM; it_var = SYMLKG(it_var)) { ++ ADDRESSP(it_var, ADDRESSG(it_var) + add_offset); ++ } ++ SIZEP(cmblk_sptr, SIZEG(cmblk_sptr) + add_offset); ++ } ++ } ++} +\ No newline at end of file +diff --git a/tools/flang2/utils/symtab/symtab.n b/tools/flang2/utils/symtab/symtab.n +index ea851fa..6a36c55 100644 +--- a/tools/flang2/utils/symtab/symtab.n ++++ b/tools/flang2/utils/symtab/symtab.n +@@ -878,6 +878,8 @@ If this array is a type descriptor, then this is used to link this type + descriptor with the other type descriptors. + .SE ETLS w28 + Extended TLS levels ++.SE ALIGN_PRAGMA w30 ++Store the variable's alignment value specified by align pragma in the form of '!dir$ align n'. + .SE ASSOC_PTR w31 + When set, this is the sptr of a pointer that is initialized with this symbol. + .SE ORIGDUMMY w32 +@@ -1110,6 +1112,8 @@ A value of zero indicates that the common block has not yet been defined. + Pointer to last element of linked list of common block members. + .SE ALTNAME w18 + Set if the common block has DVF's ++.SE CMBLK_ALIGN w20 ++Store the block's alignment value if it has variable with align pragma. + .SE ETLS w28 + Extended TLS levels + .SE THPRVTOPT w30 +diff --git a/tools/shared/pragma.c b/tools/shared/pragma.c +index 4105b3b..e87ccf0 100644 +--- a/tools/shared/pragma.c ++++ b/tools/shared/pragma.c +@@ -1013,7 +1013,13 @@ do_sw(void) + gbl.nowarn = backup_nowarn; + return true; + } +- ++#ifdef PGHPF ++ NEED(gbl.align_pragma_size + 1, gbl.align_pragma_table, ALIGN_PRAGMA, gbl.align_pragma_size, gbl.align_pragma_size + 1); ++ ALIGN_PRAGMA * new_align_pragma_ptr = gbl.align_pragma_table + gbl.align_pragma_size - 1; ++ new_align_pragma_ptr->lineno = lineno; ++ new_align_pragma_ptr->alignment = itok; ++ new_align_pragma_ptr->scope = stb.curr_scope; ++#endif + TR1("SW_ALIGN alignment[%d]\n", itok); + flg.x[251] = itok; + return true; +-- +2.34.1 + diff --git a/flang.spec b/flang.spec index ba5ebfe..00ea7be 100644 --- a/flang.spec +++ b/flang.spec @@ -2,7 +2,7 @@ Name: flang Version: flang_20210324 -Release: 28 +Release: 29 Summary: Fortran language compiler targeting LLVM License: Apache-2.0 @@ -35,6 +35,7 @@ Patch20: 21-add-align-prgma-for-fix-shape-array-character-type.patch Patch21: 22-fix-import-use.patch Patch22: 23-fix-bug-about-sizeof-for-data-with-Bind-C.patch Patch23: 24-fix-retun-dynamic-multidimensional-array-bug.patch +Patch24: 25-add-align-pragma-for-scalar-variables.patch %description Flang depends on a fork of the LLVM project (https://github.com/flang-compiler/classic-flang-llvm-project). The fork made some changes to the upstream LLVM project to support Flang toolchain. Flang cannot build independently for now. @@ -56,6 +57,9 @@ TODO: support build Flang. %changelog +* Wed Oct 25 2023 HuQingYuan - flang_20210324-29 +- Add patch for add align pragma for scalar variables + * Mon Sep 11 2023 xieyihui - flang_20210324-28 - Add patch for fix retun dynamic multidimensional array bug -- Gitee