1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
//===-- FIRBuilder.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "flang/Lower/FIRBuilder.h"
#include "SymbolMap.h"
#include "flang/Lower/Bridge.h"
#include "flang/Lower/ComplexExpr.h"
#include "flang/Lower/ConvertType.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Semantics/symbol.h"
#include "llvm/Support/ErrorHandling.h"
mlir::FuncOp Fortran::lower::FirOpBuilder::createFunction(
mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name,
mlir::FunctionType ty) {
return fir::createFuncOp(loc, module, name, ty);
}
mlir::FuncOp
Fortran::lower::FirOpBuilder::getNamedFunction(mlir::ModuleOp modOp,
llvm::StringRef name) {
return modOp.lookupSymbol<mlir::FuncOp>(name);
}
fir::GlobalOp
Fortran::lower::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp,
llvm::StringRef name) {
return modOp.lookupSymbol<fir::GlobalOp>(name);
}
mlir::Type Fortran::lower::FirOpBuilder::getRefType(mlir::Type eleTy) {
assert(!eleTy.isa<fir::ReferenceType>());
return fir::ReferenceType::get(eleTy);
}
mlir::Value
Fortran::lower::FirOpBuilder::createNullConstant(mlir::Location loc) {
auto indexType = getIndexType();
auto zero = createIntegerConstant(loc, indexType, 0);
auto noneRefType = getRefType(getNoneType());
return createConvert(loc, noneRefType, zero);
}
mlir::Value Fortran::lower::FirOpBuilder::createIntegerConstant(
mlir::Location loc, mlir::Type ty, std::int64_t cst) {
return create<mlir::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
}
mlir::Value Fortran::lower::FirOpBuilder::createRealConstant(
mlir::Location loc, mlir::Type realType, const llvm::APFloat &val) {
return create<mlir::ConstantOp>(loc, realType, getFloatAttr(realType, val));
}
mlir::Value
Fortran::lower::FirOpBuilder::createRealZeroConstant(mlir::Location loc,
mlir::Type realType) {
mlir::Attribute attr;
if (auto firType = realType.dyn_cast<fir::RealType>()) {
attr = getFloatAttr(
realType,
llvm::APFloat(kindMap.getFloatSemantics(firType.getFKind()), 0));
} else { // mlir::FloatType.
attr = getZeroAttr(realType);
}
return create<mlir::ConstantOp>(loc, realType, attr);
}
mlir::Value Fortran::lower::FirOpBuilder::allocateLocal(
mlir::Location loc, mlir::Type ty, llvm::StringRef nm,
llvm::ArrayRef<mlir::Value> shape, bool asTarget) {
llvm::SmallVector<mlir::Value, 8> indices;
auto idxTy = getIndexType();
llvm::for_each(shape, [&](mlir::Value sh) {
indices.push_back(createConvert(loc, idxTy, sh));
});
llvm::SmallVector<mlir::NamedAttribute, 2> attrs;
if (asTarget)
attrs.emplace_back(mlir::Identifier::get("target", getContext()),
getUnitAttr());
return create<fir::AllocaOp>(loc, ty, nm, llvm::None, indices, attrs);
}
/// Create a temporary variable on the stack. Anonymous temporaries have no
/// `name` value.
mlir::Value Fortran::lower::FirOpBuilder::createTemporary(
mlir::Location loc, mlir::Type type, llvm::StringRef name,
llvm::ArrayRef<mlir::Value> shape) {
auto insPt = saveInsertionPoint();
if (shape.empty())
setInsertionPointToStart(getEntryBlock());
else
setInsertionPointAfter(shape.back().getDefiningOp());
assert(!type.isa<fir::ReferenceType>() && "cannot be a reference");
auto ae = create<fir::AllocaOp>(loc, type, name, llvm::None, shape);
restoreInsertionPoint(insPt);
return ae;
}
/// 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 Fortran::lower::FirOpBuilder::createGlobal(
mlir::Location loc, mlir::Type type, llvm::StringRef name,
mlir::StringAttr linkage, mlir::Attribute value, bool isConst) {
auto module = getModule();
auto insertPt = saveInsertionPoint();
if (auto glob = module.lookupSymbol<fir::GlobalOp>(name))
return glob;
setInsertionPoint(module.getBody()->getTerminator());
auto glob = create<fir::GlobalOp>(loc, name, isConst, type, value, linkage);
restoreInsertionPoint(insertPt);
return glob;
}
fir::GlobalOp Fortran::lower::FirOpBuilder::createGlobal(
mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst,
std::function<void(FirOpBuilder &)> bodyBuilder, mlir::StringAttr linkage) {
auto module = getModule();
auto insertPt = saveInsertionPoint();
if (auto glob = module.lookupSymbol<fir::GlobalOp>(name))
return glob;
setInsertionPoint(module.getBody()->getTerminator());
auto glob = create<fir::GlobalOp>(loc, name, isConst, type, mlir::Attribute{},
linkage);
auto ®ion = glob.getRegion();
region.push_back(new mlir::Block);
auto &block = glob.getRegion().back();
setInsertionPointToStart(&block);
bodyBuilder(*this);
restoreInsertionPoint(insertPt);
return glob;
}
mlir::Value Fortran::lower::FirOpBuilder::convertWithSemantics(
mlir::Location loc, mlir::Type toTy, mlir::Value val) {
assert(toTy && "store location must be typed");
auto fromTy = val.getType();
if (fromTy == toTy)
return val;
// FIXME: add a fir::is_integer() test
ComplexExprHelper helper{*this, loc};
if ((fir::isa_real(fromTy) || fromTy.isSignlessInteger()) &&
fir::isa_complex(toTy)) {
// imaginary part is zero
auto eleTy = helper.getComplexPartType(toTy);
auto cast = createConvert(loc, eleTy, val);
llvm::APFloat zero{
kindMap.getFloatSemantics(toTy.cast<fir::CplxType>().getFKind()), 0};
auto imag = createRealConstant(loc, eleTy, zero);
return helper.createComplex(toTy, cast, imag);
}
// FIXME: add a fir::is_integer() test
if (fir::isa_complex(fromTy) &&
(toTy.isSignlessInteger() || fir::isa_real(toTy))) {
// drop the imaginary part
auto rp = helper.extractComplexPart(val, /*isImagPart=*/false);
return createConvert(loc, toTy, rp);
}
return createConvert(loc, toTy, val);
}
mlir::Value Fortran::lower::FirOpBuilder::createConvert(mlir::Location loc,
mlir::Type toTy,
mlir::Value val) {
if (val.getType() != toTy)
return create<fir::ConvertOp>(loc, toTy, val);
return val;
}
fir::StringLitOp Fortran::lower::FirOpBuilder::createStringLit(
mlir::Location loc, mlir::Type eleTy, llvm::StringRef data) {
auto strAttr = mlir::StringAttr::get(data, getContext());
auto valTag = mlir::Identifier::get(fir::StringLitOp::value(), getContext());
mlir::NamedAttribute dataAttr(valTag, strAttr);
auto sizeTag = mlir::Identifier::get(fir::StringLitOp::size(), getContext());
mlir::NamedAttribute sizeAttr(sizeTag, getI64IntegerAttr(data.size()));
llvm::SmallVector<mlir::NamedAttribute, 2> attrs{dataAttr, sizeAttr};
auto arrTy =
fir::SequenceType::get(fir::SequenceType::Shape(1, data.size()), eleTy);
return create<fir::StringLitOp>(loc, llvm::ArrayRef<mlir::Type>{arrTy},
llvm::None, attrs);
}
|