//===-- CallInterface.cpp -- Procedure call interface ---------------------===// // // 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/CallInterface.h" #include "flang/Evaluate/fold.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/Mangler.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/Support/Utils.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/InternalNames.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" //===----------------------------------------------------------------------===// // BIND(C) mangling helpers //===----------------------------------------------------------------------===// // Return the binding label (from BIND(C...)) or the mangled name of a symbol. static std::string getMangledName(const Fortran::semantics::Symbol &symbol) { const std::string *bindName = symbol.GetBindName(); return bindName ? *bindName : Fortran::lower::mangle::mangleName(symbol); } //===----------------------------------------------------------------------===// // Callee side interface implementation //===----------------------------------------------------------------------===// std::string Fortran::lower::CalleeInterface::getMangledName() const { if (funit.isMainProgram()) return fir::NameUniquer::doProgramEntry().str(); return ::getMangledName(funit.getSubprogramSymbol()); } const Fortran::semantics::Symbol * Fortran::lower::CalleeInterface::getProcedureSymbol() const { if (funit.isMainProgram()) return nullptr; return &funit.getSubprogramSymbol(); } mlir::Location Fortran::lower::CalleeInterface::getCalleeLocation() const { // FIXME: do NOT use unknown for the anonymous PROGRAM case. We probably // should just stash the location in the funit regardless. return converter.genLocation(funit.getStartingSourceLoc()); } mlir::FuncOp Fortran::lower::CalleeInterface::addEntryBlockAndMapArguments() { // On the callee side, directly map the mlir::value argument of // the function block to the Fortran symbols. func.addEntryBlock(); return func; } //===----------------------------------------------------------------------===// // CallInterface implementation: this part is common to both callee and caller // sides. //===----------------------------------------------------------------------===// static void addSymbolAttribute(mlir::FuncOp func, const Fortran::semantics::Symbol &sym, mlir::MLIRContext &mlirContext) { // Only add this on bind(C) functions for which the symbol is not reflected in // the current context. if (!Fortran::semantics::IsBindCProcedure(sym)) return; std::string name = Fortran::lower::mangle::mangleName(sym, /*keepExternalInScope=*/true); func->setAttr(fir::getSymbolAttrName(), mlir::StringAttr::get(&mlirContext, name)); } /// Declare drives the different actions to be performed while analyzing the /// signature and building/finding the mlir::FuncOp. template void Fortran::lower::CallInterface::declare() { // Create / get funcOp for direct calls. For indirect calls (only meaningful // on the caller side), no funcOp has to be created here. The mlir::Value // holding the indirection is used when creating the fir::CallOp. if (!side().isIndirectCall()) { std::string name = side().getMangledName(); mlir::ModuleOp module = converter.getModuleOp(); func = fir::FirOpBuilder::getNamedFunction(module, name); if (!func) { mlir::Location loc = side().getCalleeLocation(); mlir::FunctionType ty = genFunctionType(); func = fir::FirOpBuilder::createFunction(loc, module, name, ty); if (const Fortran::semantics::Symbol *sym = side().getProcedureSymbol()) addSymbolAttribute(func, *sym, converter.getMLIRContext()); } } } template mlir::FunctionType Fortran::lower::CallInterface::genFunctionType() { return mlir::FunctionType::get(&converter.getMLIRContext(), {}, {}); } template class Fortran::lower::CallInterface;