1//===-- EnvironmentDefaults.cpp -------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
10#include "flang/Lower/EnvironmentDefault.h"
11#include "flang/Optimizer/Builder/BoxValue.h"
12#include "flang/Optimizer/Builder/FIRBuilder.h"
13#include "flang/Optimizer/Support/InternalNames.h"
14#include "llvm/ADT/ArrayRef.h"
15
16void fir::runtime::genEnvironmentDefaults(
17 fir::FirOpBuilder &builder, mlir::Location loc,
18 const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults) {
19 std::string envDefaultListPtrName =
20 fir::NameUniquer::doGenerated("EnvironmentDefaults");
21
22 mlir::MLIRContext *context = builder.getContext();
23 mlir::StringAttr linkOnce = builder.createLinkOnceLinkage();
24 mlir::IntegerType intTy = builder.getIntegerType(8 * sizeof(int));
25 fir::ReferenceType charRefTy =
26 fir::ReferenceType::get(builder.getIntegerType(8));
27 fir::SequenceType itemListTy = fir::SequenceType::get(
28 envDefaults.size(),
29 mlir::TupleType::get(context, {charRefTy, charRefTy}));
30 mlir::TupleType envDefaultListTy = mlir::TupleType::get(
31 context, {intTy, fir::ReferenceType::get(itemListTy)});
32 fir::ReferenceType envDefaultListRefTy =
33 fir::ReferenceType::get(envDefaultListTy);
34
35 // If no defaults were specified, initialize with a null pointer.
36 if (envDefaults.empty()) {
37 builder.createGlobalConstant(
38 loc, envDefaultListRefTy, envDefaultListPtrName,
39 [&](fir::FirOpBuilder &builder) {
40 mlir::Value nullVal =
41 builder.createNullConstant(loc, envDefaultListRefTy);
42 builder.create<fir::HasValueOp>(loc, nullVal);
43 });
44 return;
45 }
46
47 // Create the Item list.
48 mlir::IndexType idxTy = builder.getIndexType();
49 mlir::IntegerAttr zero = builder.getIntegerAttr(idxTy, 0);
50 mlir::IntegerAttr one = builder.getIntegerAttr(idxTy, 1);
51 std::string itemListName = envDefaultListPtrName + ".items";
52 auto listBuilder = [&](fir::FirOpBuilder &builder) {
53 mlir::Value list = builder.create<fir::UndefOp>(loc, itemListTy);
54 llvm::SmallVector<mlir::Attribute, 2> idx = {mlir::Attribute{},
55 mlir::Attribute{}};
56 auto insertStringField = [&](const std::string &s,
57 llvm::ArrayRef<mlir::Attribute> idx) {
58 mlir::Value stringAddress = fir::getBase(
59 fir::factory::createStringLiteral(builder, loc, s + '\0'));
60 mlir::Value addr = builder.createConvert(loc, charRefTy, stringAddress);
61 return builder.create<fir::InsertValueOp>(loc, itemListTy, list, addr,
62 builder.getArrayAttr(idx));
63 };
64
65 size_t n = 0;
66 for (const Fortran::lower::EnvironmentDefault &def : envDefaults) {
67 idx[0] = builder.getIntegerAttr(idxTy, n);
68 idx[1] = zero;
69 list = insertStringField(def.varName, idx);
70 idx[1] = one;
71 list = insertStringField(def.defaultValue, idx);
72 ++n;
73 }
74 builder.create<fir::HasValueOp>(loc, list);
75 };
76 builder.createGlobalConstant(loc, itemListTy, itemListName, listBuilder,
77 linkOnce);
78
79 // Define the EnviornmentDefaultList object.
80 auto envDefaultListBuilder = [&](fir::FirOpBuilder &builder) {
81 mlir::Value envDefaultList =
82 builder.create<fir::UndefOp>(loc, envDefaultListTy);
83 mlir::Value numItems =
84 builder.createIntegerConstant(loc, intTy, envDefaults.size());
85 envDefaultList = builder.create<fir::InsertValueOp>(
86 loc, envDefaultListTy, envDefaultList, numItems,
87 builder.getArrayAttr(zero));
88 fir::GlobalOp itemList = builder.getNamedGlobal(itemListName);
89 assert(itemList && "missing environment default list");
90 mlir::Value listAddr = builder.create<fir::AddrOfOp>(
91 loc, itemList.resultType(), itemList.getSymbol());
92 envDefaultList = builder.create<fir::InsertValueOp>(
93 loc, envDefaultListTy, envDefaultList, listAddr,
94 builder.getArrayAttr(one));
95 builder.create<fir::HasValueOp>(loc, envDefaultList);
96 };
97 fir::GlobalOp envDefaultList = builder.createGlobalConstant(
98 loc, envDefaultListTy, envDefaultListPtrName + ".list",
99 envDefaultListBuilder, linkOnce);
100
101 // Define the pointer to the list used by the runtime.
102 builder.createGlobalConstant(
103 loc, envDefaultListRefTy, envDefaultListPtrName,
104 [&](fir::FirOpBuilder &builder) {
105 mlir::Value addr = builder.create<fir::AddrOfOp>(
106 loc, envDefaultList.resultType(), envDefaultList.getSymbol());
107 builder.create<fir::HasValueOp>(loc, addr);
108 });
109}
110

source code of flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp