Skip to content

[flang] Zero initialize uninitialized components in saved default init #67777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions flang/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ end
* `$` and `@` as legal characters in names
* Initialization in type declaration statements using `/values/`
* Saved variables without explicit or default initializers are zero initialized.
* In a saved entity of a type with a default initializer, components without default
values are zero initialized.
* Kind specification with `*`, e.g. `REAL*4`
* `DOUBLE COMPLEX` as a synonym for `COMPLEX(KIND(0.D0))` --
but not when spelled `TYPE(DOUBLECOMPLEX)`.
Expand Down
11 changes: 6 additions & 5 deletions flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,16 +352,17 @@ static mlir::Value genDefaultInitializerValue(
componentValue = genDefaultInitializerValue(converter, loc, component,
componentTy, stmtCtx);
} else {
// Component has no initial value.
componentValue = builder.create<fir::UndefOp>(loc, componentTy);
// Component has no initial value. Set its bits to zero by extension
// to match what is expected because other compilers are doing it.
componentValue = builder.create<fir::ZeroOp>(loc, componentTy);
}
} else if (const auto *proc{
component
.detailsIf<Fortran::semantics::ProcEntityDetails>()}) {
if (proc->init().has_value())
TODO(loc, "procedure pointer component default initialization");
else
componentValue = builder.create<fir::UndefOp>(loc, componentTy);
componentValue = builder.create<fir::ZeroOp>(loc, componentTy);
}
assert(componentValue && "must have been computed");
componentValue = builder.createConvert(loc, componentTy, componentValue);
Expand Down Expand Up @@ -890,7 +891,7 @@ static fir::GlobalOp defineGlobalAggregateStore(
Fortran::lower::createGlobalInitialization(
builder, global, [&](fir::FirOpBuilder &builder) {
Fortran::lower::StatementContext stmtCtx;
mlir::Value initVal = builder.create<fir::UndefOp>(loc, aggTy);
mlir::Value initVal = builder.create<fir::ZeroOp>(loc, aggTy);
builder.create<fir::HasValueOp>(loc, initVal);
});
return global;
Expand Down Expand Up @@ -1171,7 +1172,7 @@ static void finalizeCommonBlockDefinition(
mlir::TupleType commonTy = global.getType().cast<mlir::TupleType>();
auto initFunc = [&](fir::FirOpBuilder &builder) {
mlir::IndexType idxTy = builder.getIndexType();
mlir::Value cb = builder.create<fir::UndefOp>(loc, commonTy);
mlir::Value cb = builder.create<fir::ZeroOp>(loc, commonTy);
unsigned tupIdx = 0;
std::size_t offset = 0;
LLVM_DEBUG(llvm::dbgs() << "block {\n");
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/array.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32
! CHECK-DAG: %[[VAL_2:.*]] = arith.constant 2.400000e+00 : f32
! CHECK-DAG: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32
! CHECK: %[[VAL_4:.*]] = fir.undefined tuple<!fir.array<5x5xf32>>
! CHECK: %[[VAL_4:.*]] = fir.zero_bits tuple<!fir.array<5x5xf32>>
! CHECK: %[[VAL_5:.*]] = fir.undefined !fir.array<5x5xf32>
! CHECK: %[[VAL_6:.*]] = fir.insert_on_range %[[VAL_5]], %[[VAL_1]] from (0, 0) to (1, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32>
! CHECK: %[[VAL_7:.*]] = fir.insert_on_range %[[VAL_6]], %[[VAL_3]] from (2, 0) to (4, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32>
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/common-block-2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
! - A common block that is initialized outside of a BLOCK DATA.

! CHECK-LABEL: fir.global @__BLNK__ : tuple<i32, !fir.array<8xi8>> {
! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>

! CHECK-LABEL: fir.global @a_ : tuple<i32, !fir.array<8xi8>> {
! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/common-block.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
! CHECK: @with_empty_equiv_ = common global [8 x i8] zeroinitializer
! CHECK: @x_ = global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} }
! CHECK: @y_ = common global [12 x i8] zeroinitializer
! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] undef, float 3.000000e+00 }
! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] zeroinitializer, float 3.000000e+00 }

! CHECK-LABEL: _QPs0
subroutine s0
Expand Down
8 changes: 4 additions & 4 deletions flang/test/Lower/default-initialization-globals.f90
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ module tinit
! CHECK-DAG: %[[VAL_15:.*]] = arith.constant 66 : i32
! CHECK: %[[VAL_16:.*]] = fir.undefined !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_11]], ["i", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_18:.*]] = fir.undefined i32
! CHECK: %[[VAL_18:.*]] = fir.zero_bits i32
! CHECK: %[[VAL_19:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_18]], ["j", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_20:.*]] = fir.address_of(@_QMtinitEziel) : !fir.ref<!fir.array<100xf32>>
! CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
Expand All @@ -111,12 +111,12 @@ module tinit
! CHECK: %[[VAL_28:.*]] = fir.insert_value %[[VAL_27]], %[[VAL_26]], ["z", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_29:.*]] = fir.string_lit "hello "(10) : !fir.char<1,10>
! CHECK: %[[VAL_30:.*]] = fir.insert_value %[[VAL_28]], %[[VAL_29]], ["c1", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_31:.*]] = fir.undefined !fir.char<1,10>
! CHECK: %[[VAL_31:.*]] = fir.zero_bits !fir.char<1,10>
! CHECK: %[[VAL_32:.*]] = fir.insert_value %[[VAL_30]], %[[VAL_31]], ["c2", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_33:.*]] = fir.undefined !fir.type<_QMtinitTt0{k:i32}>
! CHECK: %[[VAL_34:.*]] = fir.insert_value %[[VAL_33]], %[[VAL_15]], ["k", !fir.type<_QMtinitTt0{k:i32}>] : (!fir.type<_QMtinitTt0{k:i32}>, i32) -> !fir.type<_QMtinitTt0{k:i32}>
! CHECK: %[[VAL_35:.*]] = fir.insert_value %[[VAL_32]], %[[VAL_34]], ["somet0", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTt0{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_36:.*]] = fir.undefined !fir.type<_QMtinitTtno_init{k:i32}>
! CHECK: %[[VAL_36:.*]] = fir.zero_bits !fir.type<_QMtinitTtno_init{k:i32}>
! CHECK: %[[VAL_37:.*]] = fir.insert_value %[[VAL_35]], %[[VAL_36]], ["sometno_init", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTtno_init{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}>
! CHECK: %[[VAL_38:.*]] = fir.insert_value %[[VAL_33]], %[[VAL_14]], ["k", !fir.type<_QMtinitTt0{k:i32}>] : (!fir.type<_QMtinitTt0{k:i32}>, i32) -> !fir.type<_QMtinitTt0{k:i32}>
! CHECK: %[[VAL_39:.*]] = fir.insert_value %[[VAL_37]], %[[VAL_38]], ["somet0_2", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTt0{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}>
Expand All @@ -129,7 +129,7 @@ module tinit
! CHECK: %[[VAL_42:.*]] = arith.constant 66 : i32
! CHECK: %[[VAL_43:.*]] = fir.undefined !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
! CHECK: %[[VAL_44:.*]] = fir.insert_value %[[VAL_43]], %[[VAL_42]], ["k", !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>] : (!fir.type<_QMtinitTtextendst0{k:i32,l:i32}>, i32) -> !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
! CHECK: %[[VAL_45:.*]] = fir.undefined i32
! CHECK: %[[VAL_45:.*]] = fir.zero_bits i32
! CHECK: %[[VAL_46:.*]] = fir.insert_value %[[VAL_44]], %[[VAL_45]], ["l", !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>] : (!fir.type<_QMtinitTtextendst0{k:i32,l:i32}>, i32) -> !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
! CHECK: fir.has_value %[[VAL_46]] : !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/equivalence-static-init.f90
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module module_without_init
equivalence(i(1), x)
end module
! CHECK-LABEL: fir.global @_QMmodule_without_initEi : !fir.array<8xi8> {
! CHECK: %0 = fir.undefined !fir.array<8xi8>
! CHECK: %0 = fir.zero_bits !fir.array<8xi8>
! CHECK: fir.has_value %0 : !fir.array<8xi8>
! CHECK}

Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/pointer-default-init.f90
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module test
type(t) :: test_module_var
! CHECK-LABEL: fir.global @_QMtestEtest_module_var : !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
! CHECK: %[[VAL_1:.*]] = fir.undefined i32
! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32
! CHECK: %[[VAL_2:.*]] = fir.field_index i
! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]]
! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
Expand Down Expand Up @@ -97,7 +97,7 @@ subroutine test_saved_pointer()

! CHECK-LABEL: fir.global internal @_QFtest_savedEx : !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
! CHECK: %[[VAL_1:.*]] = fir.undefined i32
! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32
! CHECK: %[[VAL_2:.*]] = fir.field_index i
! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]]
! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/pointer-initial-target-2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
common /a/ p
data p /b/
! CHECK-LABEL: fir.global @a_ : tuple<!fir.box<!fir.ptr<f32>>>
! CHECK: %[[undef:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<f32>>>
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<f32>>>
! CHECK: %[[b:.*]] = fir.address_of(@_QEb) : !fir.ref<f32>
! CHECK: %[[box:.*]] = fir.embox %[[b]] : (!fir.ref<f32>) -> !fir.box<f32>
! CHECK: %[[rebox:.*]] = fir.rebox %[[box]] : (!fir.box<f32>) -> !fir.box<!fir.ptr<f32>>
Expand Down Expand Up @@ -41,7 +41,7 @@ block data bdsnake
integer, pointer :: p => b
common /snake/ p, b
! CHECK-LABEL: fir.global @snake_ : tuple<!fir.box<!fir.ptr<i32>>, i32>
! CHECK: %[[tuple0:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<i32>>, i32>
! CHECK: %[[tuple0:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<i32>>, i32>
! CHECK: %[[snakeAddr:.*]] = fir.address_of(@snake_) : !fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>
! CHECK: %[[byteView:.*]] = fir.convert %[[snakeAddr:.*]] : (!fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>) -> !fir.ref<!fir.array<?xi8>>
! CHECK: %[[coor:.*]] = fir.coordinate_of %[[byteView]], %c24{{.*}} : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
Expand Down