[flang][debug] Make common blocks data extraction more robust. (#168752)
Our current implementation for extracting information about common block required traversal of FIR which was not ideal but previously there was no other way to obtain that information. The `[hl]fir.declare` was extended in commit https://github.com/llvm/llvm-project/pull/155325 to include storage and storage_offset. This commit adds these operands in `fircg.ext_declare` and then use them in `AddDebugInfoPass` to create debug data for common blocks.
This commit is contained in:
parent
5d0bfd1bf8
commit
0e8222b84b
@ -225,17 +225,25 @@ def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> {
|
||||
let description = [{
|
||||
Prior to lowering to LLVM IR dialect, a DeclareOp will
|
||||
be converted to an extended DeclareOp.
|
||||
|
||||
Most operands are inherited from fir.declare except for the shape and shift
|
||||
operands, which are "expanded" forms of the corresponding shape/shift
|
||||
operands of fir.declare.
|
||||
}];
|
||||
|
||||
let arguments = (ins AnyRefOrBox:$memref, Variadic<AnyIntegerType>:$shape,
|
||||
Variadic<AnyIntegerType>:$shift, Variadic<AnyIntegerType>:$typeparams,
|
||||
Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name,
|
||||
Optional<fir_DummyScopeType>:$dummy_scope,
|
||||
Optional<AnyReferenceLike>:$storage,
|
||||
DefaultValuedAttr<UI64Attr, "0">:$storage_offset,
|
||||
Builtin_StringAttr:$uniq_name,
|
||||
OptionalAttr<UI32Attr>:$dummy_arg_no);
|
||||
let results = (outs AnyRefOrBox);
|
||||
|
||||
let assemblyFormat = [{
|
||||
$memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)?
|
||||
(`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
|
||||
(`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
|
||||
attr-dict `:` functional-type(operands, results)
|
||||
}];
|
||||
|
||||
|
||||
@ -310,6 +310,7 @@ public:
|
||||
auto xDeclOp = fir::cg::XDeclareOp::create(
|
||||
rewriter, loc, declareOp.getType(), declareOp.getMemref(), shapeOpers,
|
||||
shiftOpers, declareOp.getTypeparams(), declareOp.getDummyScope(),
|
||||
declareOp.getStorage(), declareOp.getStorageOffset(),
|
||||
declareOp.getUniqName(), dummyArgNoAttr);
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< "rewriting " << declareOp << " to " << xDeclOp << '\n');
|
||||
|
||||
@ -144,62 +144,80 @@ bool AddDebugInfoPass::createCommonBlockGlobal(
|
||||
fir::DebugTypeGenerator &typeGen, mlir::SymbolTable *symbolTable) {
|
||||
mlir::MLIRContext *context = &getContext();
|
||||
mlir::OpBuilder builder(context);
|
||||
std::optional<std::int64_t> optint;
|
||||
mlir::Operation *op = declOp.getMemref().getDefiningOp();
|
||||
|
||||
if (auto conOp = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
|
||||
op = conOp.getValue().getDefiningOp();
|
||||
std::optional<std::int64_t> offset;
|
||||
mlir::Value storage = declOp.getStorage();
|
||||
if (!storage)
|
||||
return false;
|
||||
|
||||
if (auto cordOp = mlir::dyn_cast_if_present<fir::CoordinateOp>(op)) {
|
||||
auto coors = cordOp.getCoor();
|
||||
if (coors.size() != 1)
|
||||
return false;
|
||||
optint = fir::getIntIfConstant(coors[0]);
|
||||
if (!optint)
|
||||
return false;
|
||||
op = cordOp.getRef().getDefiningOp();
|
||||
if (auto conOp2 = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
|
||||
op = conOp2.getValue().getDefiningOp();
|
||||
// Extract offset from storage_offset attribute
|
||||
uint64_t storageOffset = declOp.getStorageOffset();
|
||||
if (storageOffset != 0)
|
||||
offset = static_cast<std::int64_t>(storageOffset);
|
||||
|
||||
if (auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(op)) {
|
||||
mlir::SymbolRefAttr sym = addrOfOp.getSymbol();
|
||||
if (auto global =
|
||||
symbolTable->lookup<fir::GlobalOp>(sym.getRootReference())) {
|
||||
// Get the GlobalOp from the storage value.
|
||||
// The storage may be wrapped in ConvertOp, so unwrap it first.
|
||||
mlir::Operation *storageOp = storage.getDefiningOp();
|
||||
if (auto convertOp = mlir::dyn_cast_if_present<fir::ConvertOp>(storageOp))
|
||||
storageOp = convertOp.getValue().getDefiningOp();
|
||||
|
||||
unsigned line = getLineFromLoc(global.getLoc());
|
||||
llvm::StringRef commonName(sym.getRootReference());
|
||||
// FIXME: We are trying to extract the name of the common block from the
|
||||
// name of the global. As part of mangling, GetCommonBlockObjectName can
|
||||
// add a trailing _ in the name of that global. The demangle function
|
||||
// does not seem to handle such cases. So the following hack is used to
|
||||
// remove the trailing '_'.
|
||||
if (commonName != Fortran::common::blankCommonObjectName &&
|
||||
commonName.back() == '_')
|
||||
commonName = commonName.drop_back();
|
||||
mlir::LLVM::DICommonBlockAttr commonBlock =
|
||||
getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line);
|
||||
mlir::LLVM::DITypeAttr diType = typeGen.convertType(
|
||||
fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp);
|
||||
line = getLineFromLoc(declOp.getLoc());
|
||||
auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
|
||||
context, commonBlock, mlir::StringAttr::get(context, name),
|
||||
declOp.getUniqName(), fileAttr, line, diType,
|
||||
/*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0);
|
||||
mlir::LLVM::DIExpressionAttr expr;
|
||||
if (*optint != 0) {
|
||||
llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
|
||||
ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(
|
||||
context, llvm::dwarf::DW_OP_plus_uconst, *optint));
|
||||
expr = mlir::LLVM::DIExpressionAttr::get(context, ops);
|
||||
}
|
||||
auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
|
||||
global.getContext(), gvAttr, expr);
|
||||
globalToGlobalExprsMap[global].push_back(dbgExpr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(storageOp);
|
||||
if (!addrOfOp)
|
||||
return false;
|
||||
|
||||
mlir::SymbolRefAttr sym = addrOfOp.getSymbol();
|
||||
fir::GlobalOp global =
|
||||
symbolTable->lookup<fir::GlobalOp>(sym.getRootReference());
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
// Check if the global is actually a common block by demangling its name.
|
||||
// Module EQUIVALENCE variables also use storage operands but are mangled
|
||||
// as VARIABLE type, so we reject them to avoid treating them as common
|
||||
// blocks.
|
||||
llvm::StringRef globalSymbol = sym.getRootReference();
|
||||
auto globalResult = fir::NameUniquer::deconstruct(globalSymbol);
|
||||
if (globalResult.first == fir::NameUniquer::NameKind::VARIABLE)
|
||||
return false;
|
||||
|
||||
// FIXME: We are trying to extract the name of the common block from the
|
||||
// name of the global. As part of mangling, GetCommonBlockObjectName can
|
||||
// add a trailing _ in the name of that global. The demangle function
|
||||
// does not seem to handle such cases. So the following hack is used to
|
||||
// remove the trailing '_'.
|
||||
llvm::StringRef commonName = globalSymbol;
|
||||
if (commonName != Fortran::common::blankCommonObjectName &&
|
||||
!commonName.empty() && commonName.back() == '_')
|
||||
commonName = commonName.drop_back();
|
||||
|
||||
// Create the debug attributes.
|
||||
unsigned line = getLineFromLoc(global.getLoc());
|
||||
mlir::LLVM::DICommonBlockAttr commonBlock =
|
||||
getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line);
|
||||
|
||||
mlir::LLVM::DITypeAttr diType = typeGen.convertType(
|
||||
fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp);
|
||||
|
||||
line = getLineFromLoc(declOp.getLoc());
|
||||
auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
|
||||
context, commonBlock, mlir::StringAttr::get(context, name),
|
||||
declOp.getUniqName(), fileAttr, line, diType,
|
||||
/*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0);
|
||||
|
||||
// Create DIExpression for offset if needed
|
||||
mlir::LLVM::DIExpressionAttr expr;
|
||||
if (offset && *offset != 0) {
|
||||
llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
|
||||
ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(
|
||||
context, llvm::dwarf::DW_OP_plus_uconst, *offset));
|
||||
expr = mlir::LLVM::DIExpressionAttr::get(context, ops);
|
||||
}
|
||||
return false;
|
||||
|
||||
auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
|
||||
global.getContext(), gvAttr, expr);
|
||||
globalToGlobalExprsMap[global].push_back(dbgExpr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
|
||||
|
||||
@ -52,3 +52,23 @@ func.func @unreachable_code(%arg0: !fir.ref<!fir.char<1,10>>) {
|
||||
// NODECL-NOT: uniq_name = "live_code"
|
||||
// DECL-LABEL: func.func @unreachable_code(
|
||||
// DECL: uniq_name = "live_code"
|
||||
|
||||
// Test that storage and storage_offset operands are preserved during conversion
|
||||
func.func @test_storage_operands() {
|
||||
%c0 = arith.constant 0 : index
|
||||
%c4 = arith.constant 4 : index
|
||||
%0 = fir.address_of(@common_block) : !fir.ref<!fir.array<8xi8>>
|
||||
%1 = fir.coordinate_of %0, %c0 : (!fir.ref<!fir.array<8xi8>>, index) -> !fir.ref<i8>
|
||||
%2 = fir.convert %1 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%3 = fir.declare %2 storage(%0[0]) {uniq_name = "_QFEx"} : (!fir.ref<f32>, !fir.ref<!fir.array<8xi8>>) -> !fir.ref<f32>
|
||||
%4 = fir.coordinate_of %0, %c4 : (!fir.ref<!fir.array<8xi8>>, index) -> !fir.ref<i8>
|
||||
%5 = fir.convert %4 : (!fir.ref<i8>) -> !fir.ref<i32>
|
||||
%6 = fir.declare %5 storage(%0[4]) {uniq_name = "_QFEy"} : (!fir.ref<i32>, !fir.ref<!fir.array<8xi8>>) -> !fir.ref<i32>
|
||||
return
|
||||
}
|
||||
fir.global @common_block : !fir.array<8xi8>
|
||||
|
||||
// DECL-LABEL: func.func @test_storage_operands()
|
||||
// DECL: %[[STORAGE:.*]] = fir.address_of(@common_block) : !fir.ref<!fir.array<8xi8>>
|
||||
// DECL: fircg.ext_declare {{.*}} storage(%[[STORAGE]][0]) {uniq_name = "_QFEx"}
|
||||
// DECL: fircg.ext_declare {{.*}} storage(%[[STORAGE]][4]) {uniq_name = "_QFEy"}
|
||||
|
||||
20
flang/test/Integration/debug-module-equivalence.f90
Normal file
20
flang/test/Integration/debug-module-equivalence.f90
Normal file
@ -0,0 +1,20 @@
|
||||
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s
|
||||
|
||||
! Test that module EQUIVALENCE does not generate DICommonBlock.
|
||||
|
||||
module data_module
|
||||
real :: var1, var2
|
||||
equivalence (var1, var2)
|
||||
end module data_module
|
||||
|
||||
subroutine test_module_equiv
|
||||
use data_module
|
||||
var1 = 1.5
|
||||
var2 = 2.5
|
||||
end subroutine
|
||||
|
||||
program main
|
||||
call test_module_equiv()
|
||||
end program
|
||||
|
||||
! CHECK-NOT: DICommonBlock
|
||||
@ -16,18 +16,18 @@ module {
|
||||
%1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%4 = fircg.ext_declare %3 {uniq_name = "_QFf1Ex"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc4)
|
||||
%4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf1Ex"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc4)
|
||||
%5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>>
|
||||
%6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%9 = fircg.ext_declare %8 {uniq_name = "_QFf1Exa"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc5)
|
||||
%9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf1Exa"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc5)
|
||||
%10 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%11 = fir.convert %10 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%12 = fircg.ext_declare %11 {uniq_name = "_QFf1Ey"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc6)
|
||||
%12 = fircg.ext_declare %11 storage(%0[4]) {uniq_name = "_QFf1Ey"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc6)
|
||||
%13 = fir.coordinate_of %6, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%15 = fircg.ext_declare %14 {uniq_name = "_QFf1Eya"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc7)
|
||||
%15 = fircg.ext_declare %14 storage(%5[4]) {uniq_name = "_QFf1Eya"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc7)
|
||||
return
|
||||
} loc(#loc3)
|
||||
func.func @f2() {
|
||||
@ -40,24 +40,24 @@ module {
|
||||
%1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%4 = fircg.ext_declare %3 {uniq_name = "_QFf2Ex"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc9)
|
||||
%4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf2Ex"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc9)
|
||||
%5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>>
|
||||
%6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%9 = fircg.ext_declare %8 {uniq_name = "_QFf2Exa"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc10)
|
||||
%9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf2Exa"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc10)
|
||||
%10 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%11 = fir.convert %10 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%12 = fircg.ext_declare %11 {uniq_name = "_QFf2Ey"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc11)
|
||||
%12 = fircg.ext_declare %11 storage(%0[4]) {uniq_name = "_QFf2Ey"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc11)
|
||||
%13 = fir.coordinate_of %6, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%15 = fircg.ext_declare %14 {uniq_name = "_QFf2Eya"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc12)
|
||||
%15 = fircg.ext_declare %14 storage(%5[4]) {uniq_name = "_QFf2Eya"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc12)
|
||||
%16 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%17 = fir.convert %16 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%18 = fircg.ext_declare %17 {uniq_name = "_QFf2Ez"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc13)
|
||||
%18 = fircg.ext_declare %17 storage(%0[8]) {uniq_name = "_QFf2Ez"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc13)
|
||||
%19 = fir.coordinate_of %6, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%20 = fir.convert %19 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%21 = fircg.ext_declare %20 {uniq_name = "_QFf2Eza"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc14)
|
||||
%21 = fircg.ext_declare %20 storage(%5[8]) {uniq_name = "_QFf2Eza"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc14)
|
||||
return
|
||||
} loc(#loc8)
|
||||
func.func @f3() {
|
||||
@ -69,12 +69,12 @@ module {
|
||||
%1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<i32>
|
||||
%4 = fircg.ext_declare %3 {uniq_name = "_QFf3Ex"} : (!fir.ref<i32>) -> !fir.ref<i32> loc(#loc16)
|
||||
%4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf3Ex"} : (!fir.ref<i32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<i32> loc(#loc16)
|
||||
%5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>>
|
||||
%6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<i32>
|
||||
%9 = fircg.ext_declare %8 {uniq_name = "_QFf3Exa"} : (!fir.ref<i32>) -> !fir.ref<i32> loc(#loc17)
|
||||
%9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf3Exa"} : (!fir.ref<i32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<i32> loc(#loc17)
|
||||
return
|
||||
} loc(#loc15)
|
||||
func.func @test() {
|
||||
@ -87,24 +87,24 @@ module {
|
||||
%1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%4 = fircg.ext_declare %3 {uniq_name = "_QFEv1"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc19)
|
||||
%4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFEv1"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc19)
|
||||
%5 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%6 = fir.convert %5 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%7 = fircg.ext_declare %6 {uniq_name = "_QFEv2"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc20)
|
||||
%7 = fircg.ext_declare %6 storage(%0[4]) {uniq_name = "_QFEv2"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc20)
|
||||
%8 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%9 = fir.convert %8 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%10 = fircg.ext_declare %9 {uniq_name = "_QFEv3"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc21)
|
||||
%10 = fircg.ext_declare %9 storage(%0[8]) {uniq_name = "_QFEv3"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc21)
|
||||
%11 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>>
|
||||
%12 = fir.convert %11 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>>
|
||||
%13 = fir.coordinate_of %12, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%15 = fircg.ext_declare %14 {uniq_name = "_QFEva1"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc22)
|
||||
%15 = fircg.ext_declare %14 storage(%11[0]) {uniq_name = "_QFEva1"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc22)
|
||||
%16 = fir.coordinate_of %12, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%17 = fir.convert %16 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%18 = fircg.ext_declare %17 {uniq_name = "_QFEva2"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc23)
|
||||
%18 = fircg.ext_declare %17 storage(%11[4]) {uniq_name = "_QFEva2"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc23)
|
||||
%19 = fir.coordinate_of %12, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
|
||||
%20 = fir.convert %19 : (!fir.ref<i8>) -> !fir.ref<f32>
|
||||
%21 = fircg.ext_declare %20 {uniq_name = "_QFEva3"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc24)
|
||||
%21 = fircg.ext_declare %20 storage(%11[8]) {uniq_name = "_QFEva3"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc24)
|
||||
return
|
||||
} loc(#loc18)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user