diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -176,10 +176,11 @@ fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type, llvm::StringRef name, mlir::StringAttr linkage = {}, - mlir::Attribute value = {}, bool isConst = false); + mlir::Attribute value = {}, bool isConst = false, + bool isTarget = false); fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type, - llvm::StringRef name, bool isConst, + llvm::StringRef name, bool isConst, bool isTarget, std::function bodyBuilder, mlir::StringAttr linkage = {}); @@ -188,7 +189,8 @@ llvm::StringRef name, mlir::StringAttr linkage = {}, mlir::Attribute value = {}) { - return createGlobal(loc, type, name, linkage, value, /*isConst=*/true); + return createGlobal(loc, type, name, linkage, value, /*isConst=*/true, + /*isTarget=*/false); } fir::GlobalOp @@ -196,8 +198,8 @@ llvm::StringRef name, std::function bodyBuilder, mlir::StringAttr linkage = {}) { - return createGlobal(loc, type, name, /*isConst=*/true, bodyBuilder, - linkage); + return createGlobal(loc, type, name, /*isConst=*/true, /*isTarget=*/false, + bodyBuilder, linkage); } /// Convert a StringRef string into a fir::StringLitOp. diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2654,6 +2654,7 @@ TypeAttr:$type, OptionalAttr:$initVal, OptionalAttr:$constant, + OptionalAttr:$target, OptionalAttr:$linkName ); @@ -2666,19 +2667,20 @@ OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type, CArg<"llvm::ArrayRef", "{}">:$attrs)>, OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant, - "mlir::Type":$type, + "bool":$isTarget, "mlir::Type":$type, CArg<"llvm::ArrayRef", "{}">:$attrs)>, OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type, CArg<"mlir::StringAttr", "{}">:$linkage, CArg<"llvm::ArrayRef", "{}">:$attrs)>, OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant, + "bool":$isTarget, "mlir::Type":$type, CArg<"mlir::StringAttr", "{}">:$linkage, CArg<"llvm::ArrayRef", "{}">:$attrs)>, OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type, "mlir::Attribute":$initVal, CArg<"mlir::StringAttr", "{}">:$linkage, CArg<"llvm::ArrayRef", "{}">:$attrs)>, OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant, - "mlir::Type":$type, "mlir::Attribute":$initVal, + "bool":$isTarget, "mlir::Type":$type, "mlir::Attribute":$initVal, CArg<"mlir::StringAttr", "{}">:$linkage, CArg<"llvm::ArrayRef", "{}">:$attrs)>, ]; @@ -2691,6 +2693,9 @@ static constexpr llvm::StringRef getLinkageAttrNameStr() { return "linkName"; } + static constexpr llvm::StringRef getTargetAttrNameStr() { + return "target"; + } /// The semantic type of the global mlir::Type resultType(); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -134,7 +134,8 @@ mlir::emitError(loc, "processing global declaration: symbol '") << toStringRef(sym.name()) << "' has unexpected details\n"; return builder.createGlobal(loc, converter.genType(var), globalName, linkage, - mlir::Attribute{}, isConstant(ultimate)); + mlir::Attribute{}, isConstant(ultimate), + var.isTarget()); } /// Temporary helper to catch todos in initial data target lowering. @@ -442,7 +443,7 @@ } if (!global) global = builder.createGlobal(loc, symTy, globalName, linkage, - mlir::Attribute{}, isConst); + mlir::Attribute{}, isConst, var.isTarget()); if (Fortran::semantics::IsAllocatableOrPointer(sym)) { const auto *details = sym.detailsIf(); diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -401,9 +401,9 @@ if (groupIsLocal) { groupFunc(builder); } else { - fir::GlobalOp group = - builder.createGlobal(loc, groupTy, groupMangleName, - /*isConst=*/true, groupFunc, linkOnce); + fir::GlobalOp group = builder.createGlobal( + loc, groupTy, groupMangleName, + /*isConst=*/true, /*isTarget=*/false, groupFunc, linkOnce); groupAddr = builder.create(loc, group.resultType(), group.getSymbol()); } diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -234,30 +234,34 @@ /// Create a global variable in the (read-only) data section. A global variable /// must have a unique name to identify and reference it. -fir::GlobalOp -fir::FirOpBuilder::createGlobal(mlir::Location loc, mlir::Type type, - llvm::StringRef name, mlir::StringAttr linkage, - mlir::Attribute value, bool isConst) { +fir::GlobalOp fir::FirOpBuilder::createGlobal(mlir::Location loc, + mlir::Type type, + llvm::StringRef name, + mlir::StringAttr linkage, + mlir::Attribute value, + bool isConst, bool isTarget) { auto module = getModule(); auto insertPt = saveInsertionPoint(); if (auto glob = module.lookupSymbol(name)) return glob; setInsertionPoint(module.getBody(), module.getBody()->end()); - auto glob = create(loc, name, isConst, type, value, linkage); + auto glob = + create(loc, name, isConst, isTarget, type, value, linkage); restoreInsertionPoint(insertPt); return glob; } fir::GlobalOp fir::FirOpBuilder::createGlobal( mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst, - std::function bodyBuilder, mlir::StringAttr linkage) { + bool isTarget, std::function bodyBuilder, + mlir::StringAttr linkage) { auto module = getModule(); auto insertPt = saveInsertionPoint(); if (auto glob = module.lookupSymbol(name)) return glob; setInsertionPoint(module.getBody(), module.getBody()->end()); - auto glob = create(loc, name, isConst, type, mlir::Attribute{}, - linkage); + auto glob = create(loc, name, isConst, isTarget, type, + mlir::Attribute{}, linkage); auto ®ion = glob.getRegion(); region.push_back(new mlir::Block); auto &block = glob.getRegion().back(); diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -1251,6 +1251,9 @@ result.addAttribute("constant", builder.getUnitAttr()); } + if (succeeded(parser.parseOptionalKeyword("target"))) + result.addAttribute(getTargetAttrNameStr(), builder.getUnitAttr()); + mlir::Type globalType; if (parser.parseColonType(globalType)) return mlir::failure(); @@ -1279,6 +1282,8 @@ p << '(' << val << ')'; if (getOperation()->getAttr(fir::GlobalOp::getConstantAttrNameStr())) p << " constant"; + if (getOperation()->getAttr(getTargetAttrName())) + p << " target"; p << " : "; p.printType(getType()); if (hasInitializationBody()) { @@ -1295,7 +1300,7 @@ void fir::GlobalOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, llvm::StringRef name, - bool isConstant, mlir::Type type, + bool isConstant, bool isTarget, mlir::Type type, mlir::Attribute initialVal, mlir::StringAttr linkage, llvm::ArrayRef attrs) { result.addRegion(); @@ -1307,6 +1312,8 @@ if (isConstant) result.addAttribute(getConstantAttrName(result.name), builder.getUnitAttr()); + if (isTarget) + result.addAttribute(getTargetAttrName(result.name), builder.getUnitAttr()); if (initialVal) result.addAttribute(getInitValAttrName(result.name), initialVal); if (linkage) @@ -1319,36 +1326,40 @@ mlir::Type type, mlir::Attribute initialVal, mlir::StringAttr linkage, llvm::ArrayRef attrs) { - build(builder, result, name, /*isConstant=*/false, type, {}, linkage, attrs); + build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type, + {}, linkage, attrs); } void fir::GlobalOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, llvm::StringRef name, - bool isConstant, mlir::Type type, + bool isConstant, bool isTarget, mlir::Type type, mlir::StringAttr linkage, llvm::ArrayRef attrs) { - build(builder, result, name, isConstant, type, {}, linkage, attrs); + build(builder, result, name, isConstant, isTarget, type, {}, linkage, attrs); } void fir::GlobalOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, llvm::StringRef name, mlir::Type type, mlir::StringAttr linkage, llvm::ArrayRef attrs) { - build(builder, result, name, /*isConstant=*/false, type, {}, linkage, attrs); + build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type, + {}, linkage, attrs); } void fir::GlobalOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, llvm::StringRef name, - bool isConstant, mlir::Type type, + bool isConstant, bool isTarget, mlir::Type type, llvm::ArrayRef attrs) { - build(builder, result, name, isConstant, type, mlir::StringAttr{}, attrs); + build(builder, result, name, isConstant, isTarget, type, mlir::StringAttr{}, + attrs); } void fir::GlobalOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, llvm::StringRef name, mlir::Type type, llvm::ArrayRef attrs) { - build(builder, result, name, /*isConstant=*/false, type, attrs); + build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type, + attrs); } mlir::ParseResult fir::GlobalOp::verifyValidLinkage(llvm::StringRef linkage) { diff --git a/flang/test/Lower/derived-type-descriptor.f90 b/flang/test/Lower/derived-type-descriptor.f90 --- a/flang/test/Lower/derived-type-descriptor.f90 +++ b/flang/test/Lower/derived-type-descriptor.f90 @@ -11,22 +11,22 @@ type(sometype), allocatable, save :: x(:) end subroutine -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.num constant : !fir.char<1,3> { +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.num constant target : !fir.char<1,3> { ! CHECK: %[[res:.*]] = fir.string_lit "num"(3) : !fir.char<1,3> ! CHECK: fir.has_value %[[res]] : !fir.char<1,3> -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.di.sometype.num constant : i32 -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.values constant : !fir.char<1,6> { +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.di.sometype.num constant target : i32 +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.values constant target : !fir.char<1,6> { ! CHECK: %[[res:.*]] = fir.string_lit "values"(6) : !fir.char<1,6> ! CHECK: fir.has_value %[[res]] : !fir.char<1,6> -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.sometype constant : !fir.char<1,8> { +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.n.sometype constant target : !fir.char<1,8> { ! CHECK: %[[res:.*]] = fir.string_lit "sometype"(8) : !fir.char<1,8> ! CHECK: fir.has_value %[[res]] : !fir.char<1,8> -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.di.sometype.values constant : !fir.type<_QFfooT.dp.sometype.values{values:!fir.box>>}> { +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.di.sometype.values constant target : !fir.type<_QFfooT.dp.sometype.values{values:!fir.box>>}> { ! CHECK: fir.address_of(@_QFfooEinit_values) ! CHECK: } -! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.dt.sometype constant {{.*}} { +! CHECK-LABEL: fir.global linkonce_odr @_QFfooE.dt.sometype constant target {{.*}} { !CHECK: fir.address_of(@_QFfooE.n.sometype) !CHECK: fir.address_of(@_QFfooE.c.sometype) ! CHECK:} @@ -46,10 +46,10 @@ type(t) :: a end subroutine -! CHECK-LABEL: fir.global linkonce_odr @_QFchar_comp_initE.di.t.name constant : !fir.char<1,8> { +! CHECK-LABEL: fir.global linkonce_odr @_QFchar_comp_initE.di.t.name constant target : !fir.char<1,8> { ! CHECK: %[[res:.*]] = fir.string_lit "Empty "(8) : !fir.char<1,8> ! CHECK: fir.has_value %[[res]] : !fir.char<1,8> -! CHECK-LABEL: fir.global linkonce_odr @_QFchar_comp_initE.c.t constant : {{.*}} { +! CHECK-LABEL: fir.global linkonce_odr @_QFchar_comp_initE.c.t constant target : {{.*}} { ! CHECK: fir.address_of(@_QFchar_comp_initE.di.t.name) : !fir.ref> ! CHECK: } diff --git a/flang/test/Lower/module-single-point-of-def.f90 b/flang/test/Lower/module-single-point-of-def.f90 --- a/flang/test/Lower/module-single-point-of-def.f90 +++ b/flang/test/Lower/module-single-point-of-def.f90 @@ -23,7 +23,7 @@ end type end module -! CHECK-A-DEF: fir.global linkonce_odr @_QMdefine_aE.dt.atype constant : !fir.type<{{.*}}> { +! CHECK-A-DEF: fir.global linkonce_odr @_QMdefine_aE.dt.atype constant target : !fir.type<{{.*}}> { ! CHECK-A-DEF: fir.has_value ! CHECK-A-DEF: } @@ -45,7 +45,7 @@ ! CHECK-B-DEF: fir.has_value %{{.*}} : i32 ! CHECK-B-DEF: } -! CHECK-B-DEF: fir.global linkonce_odr @_QMdefine_bE.dt.btype constant : !fir.type<{{.*}}> { +! CHECK-B-DEF: fir.global linkonce_odr @_QMdefine_bE.dt.btype constant target : !fir.type<{{.*}}> { ! CHECK-B-DEF: fir.has_value ! CHECK-B-DEF: } diff --git a/flang/test/Lower/target_definition.f90 b/flang/test/Lower/target_definition.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/target_definition.f90 @@ -0,0 +1,11 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! Test TARGET attributes on a definition of a global symbol. +! CHECK: fir.global @_QMtarget_modEx target : f32 { +! CHECK: %[[init:.*]] = fir.undefined f32 +! CHECK: fir.has_value %[[init]] : f32 +! CHECK: } + +module target_mod + real, target :: x +end module target_mod diff --git a/flang/test/Lower/target_use.f90 b/flang/test/Lower/target_use.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/target_use.f90 @@ -0,0 +1,9 @@ +! RUN: bbc -emit-fir %S/target_definition.f90 +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! Test TARGET attributes on a declaration of a global symbol. +! CHECK: fir.global @_QMtarget_modEx target : f32 +real function test() + use target_mod + test = x +end function test