xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp (revision ecec1311fe0521404a11d6f3b90253259c8c3518)
10ec3ac9bSJonathon Penix //===-- EnvironmentDefaults.cpp -------------------------------------------===//
20ec3ac9bSJonathon Penix //
30ec3ac9bSJonathon Penix // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40ec3ac9bSJonathon Penix // See https://llvm.org/LICENSE.txt for license information.
50ec3ac9bSJonathon Penix // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60ec3ac9bSJonathon Penix //
70ec3ac9bSJonathon Penix //===----------------------------------------------------------------------===//
80ec3ac9bSJonathon Penix 
90ec3ac9bSJonathon Penix #include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
100ec3ac9bSJonathon Penix #include "flang/Lower/EnvironmentDefault.h"
110ec3ac9bSJonathon Penix #include "flang/Optimizer/Builder/BoxValue.h"
120ec3ac9bSJonathon Penix #include "flang/Optimizer/Builder/FIRBuilder.h"
130ec3ac9bSJonathon Penix #include "flang/Optimizer/Support/InternalNames.h"
140ec3ac9bSJonathon Penix #include "llvm/ADT/ArrayRef.h"
150ec3ac9bSJonathon Penix 
genEnvironmentDefaults(fir::FirOpBuilder & builder,mlir::Location loc,const std::vector<Fortran::lower::EnvironmentDefault> & envDefaults)16*ecec1311SDavid Truby mlir::Value fir::runtime::genEnvironmentDefaults(
170ec3ac9bSJonathon Penix     fir::FirOpBuilder &builder, mlir::Location loc,
180ec3ac9bSJonathon Penix     const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults) {
190ec3ac9bSJonathon Penix   std::string envDefaultListPtrName =
200ec3ac9bSJonathon Penix       fir::NameUniquer::doGenerated("EnvironmentDefaults");
210ec3ac9bSJonathon Penix 
220ec3ac9bSJonathon Penix   mlir::MLIRContext *context = builder.getContext();
230ec3ac9bSJonathon Penix   mlir::StringAttr linkOnce = builder.createLinkOnceLinkage();
240ec3ac9bSJonathon Penix   mlir::IntegerType intTy = builder.getIntegerType(8 * sizeof(int));
250ec3ac9bSJonathon Penix   fir::ReferenceType charRefTy =
260ec3ac9bSJonathon Penix       fir::ReferenceType::get(builder.getIntegerType(8));
270ec3ac9bSJonathon Penix   fir::SequenceType itemListTy = fir::SequenceType::get(
280ec3ac9bSJonathon Penix       envDefaults.size(),
290ec3ac9bSJonathon Penix       mlir::TupleType::get(context, {charRefTy, charRefTy}));
300ec3ac9bSJonathon Penix   mlir::TupleType envDefaultListTy = mlir::TupleType::get(
310ec3ac9bSJonathon Penix       context, {intTy, fir::ReferenceType::get(itemListTy)});
320ec3ac9bSJonathon Penix   fir::ReferenceType envDefaultListRefTy =
330ec3ac9bSJonathon Penix       fir::ReferenceType::get(envDefaultListTy);
340ec3ac9bSJonathon Penix 
350ec3ac9bSJonathon Penix   // If no defaults were specified, initialize with a null pointer.
360ec3ac9bSJonathon Penix   if (envDefaults.empty()) {
37*ecec1311SDavid Truby     mlir::Value nullVal = builder.createNullConstant(loc, envDefaultListRefTy);
38*ecec1311SDavid Truby     return nullVal;
390ec3ac9bSJonathon Penix   }
400ec3ac9bSJonathon Penix 
410ec3ac9bSJonathon Penix   // Create the Item list.
420ec3ac9bSJonathon Penix   mlir::IndexType idxTy = builder.getIndexType();
430ec3ac9bSJonathon Penix   mlir::IntegerAttr zero = builder.getIntegerAttr(idxTy, 0);
440ec3ac9bSJonathon Penix   mlir::IntegerAttr one = builder.getIntegerAttr(idxTy, 1);
450ec3ac9bSJonathon Penix   std::string itemListName = envDefaultListPtrName + ".items";
460ec3ac9bSJonathon Penix   auto listBuilder = [&](fir::FirOpBuilder &builder) {
470ec3ac9bSJonathon Penix     mlir::Value list = builder.create<fir::UndefOp>(loc, itemListTy);
480ec3ac9bSJonathon Penix     llvm::SmallVector<mlir::Attribute, 2> idx = {mlir::Attribute{},
490ec3ac9bSJonathon Penix                                                  mlir::Attribute{}};
500ec3ac9bSJonathon Penix     auto insertStringField = [&](const std::string &s,
510ec3ac9bSJonathon Penix                                  llvm::ArrayRef<mlir::Attribute> idx) {
520ec3ac9bSJonathon Penix       mlir::Value stringAddress = fir::getBase(
530ec3ac9bSJonathon Penix           fir::factory::createStringLiteral(builder, loc, s + '\0'));
540ec3ac9bSJonathon Penix       mlir::Value addr = builder.createConvert(loc, charRefTy, stringAddress);
550ec3ac9bSJonathon Penix       return builder.create<fir::InsertValueOp>(loc, itemListTy, list, addr,
560ec3ac9bSJonathon Penix                                                 builder.getArrayAttr(idx));
570ec3ac9bSJonathon Penix     };
580ec3ac9bSJonathon Penix 
590ec3ac9bSJonathon Penix     size_t n = 0;
600ec3ac9bSJonathon Penix     for (const Fortran::lower::EnvironmentDefault &def : envDefaults) {
610ec3ac9bSJonathon Penix       idx[0] = builder.getIntegerAttr(idxTy, n);
620ec3ac9bSJonathon Penix       idx[1] = zero;
630ec3ac9bSJonathon Penix       list = insertStringField(def.varName, idx);
640ec3ac9bSJonathon Penix       idx[1] = one;
650ec3ac9bSJonathon Penix       list = insertStringField(def.defaultValue, idx);
660ec3ac9bSJonathon Penix       ++n;
670ec3ac9bSJonathon Penix     }
680ec3ac9bSJonathon Penix     builder.create<fir::HasValueOp>(loc, list);
690ec3ac9bSJonathon Penix   };
700ec3ac9bSJonathon Penix   builder.createGlobalConstant(loc, itemListTy, itemListName, listBuilder,
710ec3ac9bSJonathon Penix                                linkOnce);
720ec3ac9bSJonathon Penix 
730ec3ac9bSJonathon Penix   // Define the EnviornmentDefaultList object.
740ec3ac9bSJonathon Penix   auto envDefaultListBuilder = [&](fir::FirOpBuilder &builder) {
750ec3ac9bSJonathon Penix     mlir::Value envDefaultList =
760ec3ac9bSJonathon Penix         builder.create<fir::UndefOp>(loc, envDefaultListTy);
770ec3ac9bSJonathon Penix     mlir::Value numItems =
780ec3ac9bSJonathon Penix         builder.createIntegerConstant(loc, intTy, envDefaults.size());
790ec3ac9bSJonathon Penix     envDefaultList = builder.create<fir::InsertValueOp>(
800ec3ac9bSJonathon Penix         loc, envDefaultListTy, envDefaultList, numItems,
810ec3ac9bSJonathon Penix         builder.getArrayAttr(zero));
820ec3ac9bSJonathon Penix     fir::GlobalOp itemList = builder.getNamedGlobal(itemListName);
830ec3ac9bSJonathon Penix     assert(itemList && "missing environment default list");
840ec3ac9bSJonathon Penix     mlir::Value listAddr = builder.create<fir::AddrOfOp>(
850ec3ac9bSJonathon Penix         loc, itemList.resultType(), itemList.getSymbol());
860ec3ac9bSJonathon Penix     envDefaultList = builder.create<fir::InsertValueOp>(
870ec3ac9bSJonathon Penix         loc, envDefaultListTy, envDefaultList, listAddr,
880ec3ac9bSJonathon Penix         builder.getArrayAttr(one));
890ec3ac9bSJonathon Penix     builder.create<fir::HasValueOp>(loc, envDefaultList);
900ec3ac9bSJonathon Penix   };
910ec3ac9bSJonathon Penix   fir::GlobalOp envDefaultList = builder.createGlobalConstant(
920ec3ac9bSJonathon Penix       loc, envDefaultListTy, envDefaultListPtrName + ".list",
930ec3ac9bSJonathon Penix       envDefaultListBuilder, linkOnce);
940ec3ac9bSJonathon Penix 
950ec3ac9bSJonathon Penix   // Define the pointer to the list used by the runtime.
960ec3ac9bSJonathon Penix   mlir::Value addr = builder.create<fir::AddrOfOp>(
970ec3ac9bSJonathon Penix       loc, envDefaultList.resultType(), envDefaultList.getSymbol());
98*ecec1311SDavid Truby   return addr;
990ec3ac9bSJonathon Penix }
100