xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp (revision ecec1311fe0521404a11d6f3b90253259c8c3518)
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 
genEnvironmentDefaults(fir::FirOpBuilder & builder,mlir::Location loc,const std::vector<Fortran::lower::EnvironmentDefault> & envDefaults)16 mlir::Value 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     mlir::Value nullVal = builder.createNullConstant(loc, envDefaultListRefTy);
38     return nullVal;
39   }
40 
41   // Create the Item list.
42   mlir::IndexType idxTy = builder.getIndexType();
43   mlir::IntegerAttr zero = builder.getIntegerAttr(idxTy, 0);
44   mlir::IntegerAttr one = builder.getIntegerAttr(idxTy, 1);
45   std::string itemListName = envDefaultListPtrName + ".items";
46   auto listBuilder = [&](fir::FirOpBuilder &builder) {
47     mlir::Value list = builder.create<fir::UndefOp>(loc, itemListTy);
48     llvm::SmallVector<mlir::Attribute, 2> idx = {mlir::Attribute{},
49                                                  mlir::Attribute{}};
50     auto insertStringField = [&](const std::string &s,
51                                  llvm::ArrayRef<mlir::Attribute> idx) {
52       mlir::Value stringAddress = fir::getBase(
53           fir::factory::createStringLiteral(builder, loc, s + '\0'));
54       mlir::Value addr = builder.createConvert(loc, charRefTy, stringAddress);
55       return builder.create<fir::InsertValueOp>(loc, itemListTy, list, addr,
56                                                 builder.getArrayAttr(idx));
57     };
58 
59     size_t n = 0;
60     for (const Fortran::lower::EnvironmentDefault &def : envDefaults) {
61       idx[0] = builder.getIntegerAttr(idxTy, n);
62       idx[1] = zero;
63       list = insertStringField(def.varName, idx);
64       idx[1] = one;
65       list = insertStringField(def.defaultValue, idx);
66       ++n;
67     }
68     builder.create<fir::HasValueOp>(loc, list);
69   };
70   builder.createGlobalConstant(loc, itemListTy, itemListName, listBuilder,
71                                linkOnce);
72 
73   // Define the EnviornmentDefaultList object.
74   auto envDefaultListBuilder = [&](fir::FirOpBuilder &builder) {
75     mlir::Value envDefaultList =
76         builder.create<fir::UndefOp>(loc, envDefaultListTy);
77     mlir::Value numItems =
78         builder.createIntegerConstant(loc, intTy, envDefaults.size());
79     envDefaultList = builder.create<fir::InsertValueOp>(
80         loc, envDefaultListTy, envDefaultList, numItems,
81         builder.getArrayAttr(zero));
82     fir::GlobalOp itemList = builder.getNamedGlobal(itemListName);
83     assert(itemList && "missing environment default list");
84     mlir::Value listAddr = builder.create<fir::AddrOfOp>(
85         loc, itemList.resultType(), itemList.getSymbol());
86     envDefaultList = builder.create<fir::InsertValueOp>(
87         loc, envDefaultListTy, envDefaultList, listAddr,
88         builder.getArrayAttr(one));
89     builder.create<fir::HasValueOp>(loc, envDefaultList);
90   };
91   fir::GlobalOp envDefaultList = builder.createGlobalConstant(
92       loc, envDefaultListTy, envDefaultListPtrName + ".list",
93       envDefaultListBuilder, linkOnce);
94 
95   // Define the pointer to the list used by the runtime.
96   mlir::Value addr = builder.create<fir::AddrOfOp>(
97       loc, envDefaultList.resultType(), envDefaultList.getSymbol());
98   return addr;
99 }
100