[flang] Updating drivers to create data layout before semantics (#73301)
Preliminary patch to change lowering/code generation to use llvm::DataLayout information instead of generating "sizeof" GEP (see https://github.com/llvm/llvm-project/issues/71507). Fortran Semantic analysis needs to know about the target type size and alignment to deal with common blocks, and intrinsics like C_SIZEOF/TRANSFER. This information should be obtained from the llvm::DataLayout so that it is consistent during the whole compilation flow. This change is changing flang-new and bbc drivers to: 1. Create the llvm::TargetMachine so that the data layout of the target can be obtained before semantics. 2. Sharing bbc/flang-new set-up of the SemanticConstext.targetCharateristics from the llvm::TargetMachine. For now, the actual part that set-up the Fortran type size and alignment from the llvm::DataLayout is left TODO so that this change is mostly an NFC impacting the drivers. 3. Let the lowering bridge set-up the mlir::Module datalayout attributes since it is doing it for the target attribute, and that allows the llvm data layout information to be available during lowering. For flang-new, the changes are code shuffling: the `llvm::TargetMachine` instance is moved to `CompilerInvocation` class so that it can be used to set-up the semantic contexts. `setMLIRDataLayout` is moved to `flang/Optimizer/Support/DataLayout.h` (it will need to be used from codegen pass for fir-opt target independent testing.)), and the code setting-up semantics targetCharacteristics is moved to `Tools/TargetSetup.h` so that it can be shared with bbc. As a consequence, LLVM targets must be registered when running semantics, and it is not possible to run semantics for a target that is not registered with the -triple option (hence the power pc specific modules can only be built if the PowerPC target is available.
This commit is contained in:
parent
d77067d08a
commit
e59e848805
@ -21,6 +21,7 @@
|
|||||||
#include "flang/Semantics/runtime-type-info.h"
|
#include "flang/Semantics/runtime-type-info.h"
|
||||||
#include "flang/Semantics/semantics.h"
|
#include "flang/Semantics/semantics.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
namespace Fortran::frontend {
|
namespace Fortran::frontend {
|
||||||
|
|
||||||
@ -57,6 +58,8 @@ class CompilerInstance {
|
|||||||
|
|
||||||
std::unique_ptr<Fortran::semantics::SemanticsContext> semaContext;
|
std::unique_ptr<Fortran::semantics::SemanticsContext> semaContext;
|
||||||
|
|
||||||
|
std::unique_ptr<llvm::TargetMachine> targetMachine;
|
||||||
|
|
||||||
/// The stream for diagnostics from Semantics
|
/// The stream for diagnostics from Semantics
|
||||||
llvm::raw_ostream *semaOutputStream = &llvm::errs();
|
llvm::raw_ostream *semaOutputStream = &llvm::errs();
|
||||||
|
|
||||||
@ -231,6 +234,26 @@ public:
|
|||||||
createDefaultOutputFile(bool binary = true, llvm::StringRef baseInput = "",
|
createDefaultOutputFile(bool binary = true, llvm::StringRef baseInput = "",
|
||||||
llvm::StringRef extension = "");
|
llvm::StringRef extension = "");
|
||||||
|
|
||||||
|
/// {
|
||||||
|
/// @name Target Machine
|
||||||
|
/// {
|
||||||
|
|
||||||
|
/// Get the target machine.
|
||||||
|
const llvm::TargetMachine &getTargetMachine() const {
|
||||||
|
assert(targetMachine && "target machine was not set");
|
||||||
|
return *targetMachine;
|
||||||
|
}
|
||||||
|
llvm::TargetMachine &getTargetMachine() {
|
||||||
|
assert(targetMachine && "target machine was not set");
|
||||||
|
return *targetMachine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up LLVM's TargetMachine.
|
||||||
|
bool setUpTargetMachine();
|
||||||
|
|
||||||
|
/// Produces the string which represents target feature
|
||||||
|
std::string getTargetFeatures();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Create a new output file
|
/// Create a new output file
|
||||||
///
|
///
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#include "llvm/Option/ArgList.h"
|
#include "llvm/Option/ArgList.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class TargetMachine;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Fortran::frontend {
|
namespace Fortran::frontend {
|
||||||
|
|
||||||
/// Fill out Opts based on the options given in Args.
|
/// Fill out Opts based on the options given in Args.
|
||||||
@ -161,7 +165,8 @@ public:
|
|||||||
|
|
||||||
/// Creates and configures semantics context based on the compilation flags.
|
/// Creates and configures semantics context based on the compilation flags.
|
||||||
std::unique_ptr<Fortran::semantics::SemanticsContext>
|
std::unique_ptr<Fortran::semantics::SemanticsContext>
|
||||||
getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources);
|
getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
|
||||||
|
const llvm::TargetMachine &);
|
||||||
|
|
||||||
std::string &getModuleDir() { return moduleDir; }
|
std::string &getModuleDir() { return moduleDir; }
|
||||||
const std::string &getModuleDir() const { return moduleDir; }
|
const std::string &getModuleDir() const { return moduleDir; }
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "mlir/IR/BuiltinOps.h"
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Fortran::frontend {
|
namespace Fortran::frontend {
|
||||||
@ -204,8 +203,6 @@ class CodeGenAction : public FrontendAction {
|
|||||||
void executeAction() override;
|
void executeAction() override;
|
||||||
/// Runs prescan, parsing, sema and lowers to MLIR.
|
/// Runs prescan, parsing, sema and lowers to MLIR.
|
||||||
bool beginSourceFileAction() override;
|
bool beginSourceFileAction() override;
|
||||||
/// Sets up LLVM's TargetMachine.
|
|
||||||
bool setUpTargetMachine();
|
|
||||||
/// Runs the optimization (aka middle-end) pipeline on the LLVM module
|
/// Runs the optimization (aka middle-end) pipeline on the LLVM module
|
||||||
/// associated with this action.
|
/// associated with this action.
|
||||||
void runOptimizationPipeline(llvm::raw_pwrite_stream &os);
|
void runOptimizationPipeline(llvm::raw_pwrite_stream &os);
|
||||||
@ -234,7 +231,6 @@ protected:
|
|||||||
|
|
||||||
BackendActionTy action;
|
BackendActionTy action;
|
||||||
|
|
||||||
std::unique_ptr<llvm::TargetMachine> tm;
|
|
||||||
/// }
|
/// }
|
||||||
public:
|
public:
|
||||||
~CodeGenAction() override;
|
~CodeGenAction() override;
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
||||||
#include "mlir/IR/BuiltinOps.h"
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class DataLayout;
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
namespace Fortran {
|
namespace Fortran {
|
||||||
namespace common {
|
namespace common {
|
||||||
class IntrinsicTypeDefaultKinds;
|
class IntrinsicTypeDefaultKinds;
|
||||||
@ -59,10 +63,12 @@ public:
|
|||||||
llvm::StringRef triple, fir::KindMapping &kindMap,
|
llvm::StringRef triple, fir::KindMapping &kindMap,
|
||||||
const Fortran::lower::LoweringOptions &loweringOptions,
|
const Fortran::lower::LoweringOptions &loweringOptions,
|
||||||
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
||||||
const Fortran::common::LanguageFeatureControl &languageFeatures) {
|
const Fortran::common::LanguageFeatureControl &languageFeatures,
|
||||||
|
const llvm::DataLayout *dataLayout = nullptr) {
|
||||||
return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics,
|
return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics,
|
||||||
targetCharacteristics, allCooked, triple, kindMap,
|
targetCharacteristics, allCooked, triple, kindMap,
|
||||||
loweringOptions, envDefaults, languageFeatures);
|
loweringOptions, envDefaults, languageFeatures,
|
||||||
|
dataLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -140,7 +146,8 @@ private:
|
|||||||
fir::KindMapping &kindMap,
|
fir::KindMapping &kindMap,
|
||||||
const Fortran::lower::LoweringOptions &loweringOptions,
|
const Fortran::lower::LoweringOptions &loweringOptions,
|
||||||
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
||||||
const Fortran::common::LanguageFeatureControl &languageFeatures);
|
const Fortran::common::LanguageFeatureControl &languageFeatures,
|
||||||
|
const llvm::DataLayout *dataLayout);
|
||||||
LoweringBridge() = delete;
|
LoweringBridge() = delete;
|
||||||
LoweringBridge(const LoweringBridge &) = delete;
|
LoweringBridge(const LoweringBridge &) = delete;
|
||||||
|
|
||||||
|
39
flang/include/flang/Optimizer/Support/DataLayout.h
Normal file
39
flang/include/flang/Optimizer/Support/DataLayout.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//===-- Optimizer/Support/DataLayout.h --------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef FORTRAN_OPTIMIZER_SUPPORT_DATALAYOUT_H
|
||||||
|
#define FORTRAN_OPTIMIZER_SUPPORT_DATALAYOUT_H
|
||||||
|
|
||||||
|
namespace mlir {
|
||||||
|
class ModuleOp;
|
||||||
|
}
|
||||||
|
namespace llvm {
|
||||||
|
class DataLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace fir::support {
|
||||||
|
/// Create an mlir::DataLayoutSpecInterface attribute from an llvm::DataLayout
|
||||||
|
/// and set it on the provided mlir::ModuleOp.
|
||||||
|
/// Also set the llvm.data_layout attribute with the string representation of
|
||||||
|
/// the llvm::DataLayout on the module.
|
||||||
|
/// These attributes are replaced if they were already set.
|
||||||
|
void setMLIRDataLayout(mlir::ModuleOp mlirModule, const llvm::DataLayout &dl);
|
||||||
|
|
||||||
|
/// Create an mlir::DataLayoutSpecInterface from the llvm.data_layout attribute
|
||||||
|
/// if one is provided. If such attribute is not available, create a default
|
||||||
|
/// target independent layout when allowDefaultLayout is true. Otherwise do
|
||||||
|
/// nothing.
|
||||||
|
void setMLIRDataLayoutFromAttributes(mlir::ModuleOp mlirModule,
|
||||||
|
bool allowDefaultLayout);
|
||||||
|
} // namespace fir::support
|
||||||
|
|
||||||
|
#endif // FORTRAN_OPTIMIZER_SUPPORT_DATALAYOUT_H
|
40
flang/include/flang/Tools/TargetSetup.h
Normal file
40
flang/include/flang/Tools/TargetSetup.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//===-- Tools/TargetSetup.h ------------------------------------- *-C++-*-===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef FORTRAN_TOOLS_TARGET_SETUP_H
|
||||||
|
#define FORTRAN_TOOLS_TARGET_SETUP_H
|
||||||
|
|
||||||
|
#include "flang/Evaluate/target.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
|
namespace Fortran::tools {
|
||||||
|
|
||||||
|
[[maybe_unused]] inline static void setUpTargetCharacteristics(
|
||||||
|
Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
|
||||||
|
const llvm::TargetMachine &targetMachine,
|
||||||
|
const std::string &compilerVersion, const std::string &compilerOptions) {
|
||||||
|
|
||||||
|
const llvm::Triple &targetTriple{targetMachine.getTargetTriple()};
|
||||||
|
// FIXME: Handle real(3) ?
|
||||||
|
if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64)
|
||||||
|
targetCharacteristics.DisableType(
|
||||||
|
Fortran::common::TypeCategory::Real, /*kind=*/10);
|
||||||
|
|
||||||
|
targetCharacteristics.set_compilerOptionsString(compilerOptions)
|
||||||
|
.set_compilerVersionString(compilerVersion);
|
||||||
|
|
||||||
|
if (targetTriple.isPPC())
|
||||||
|
targetCharacteristics.set_isPPC(true);
|
||||||
|
|
||||||
|
// TODO: use target machine data layout to set-up the target characteristics
|
||||||
|
// type size and alignment info.
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Fortran::tools
|
||||||
|
|
||||||
|
#endif // FORTRAN_TOOLS_TARGET_SETUP_H
|
@ -17,11 +17,15 @@
|
|||||||
#include "flang/Parser/parsing.h"
|
#include "flang/Parser/parsing.h"
|
||||||
#include "flang/Parser/provenance.h"
|
#include "flang/Parser/provenance.h"
|
||||||
#include "flang/Semantics/semantics.h"
|
#include "flang/Semantics/semantics.h"
|
||||||
|
#include "clang/Basic/DiagnosticFrontend.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/MC/TargetRegistry.h"
|
||||||
#include "llvm/Support/Errc.h"
|
#include "llvm/Support/Errc.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/TargetParser/TargetParser.h"
|
||||||
#include "llvm/TargetParser/Triple.h"
|
#include "llvm/TargetParser/Triple.h"
|
||||||
|
|
||||||
using namespace Fortran::frontend;
|
using namespace Fortran::frontend;
|
||||||
@ -156,8 +160,10 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
|
|||||||
invoc.setFortranOpts();
|
invoc.setFortranOpts();
|
||||||
// Set the encoding to read all input files in based on user input.
|
// Set the encoding to read all input files in based on user input.
|
||||||
allSources->set_encoding(invoc.getFortranOpts().encoding);
|
allSources->set_encoding(invoc.getFortranOpts().encoding);
|
||||||
|
if (!setUpTargetMachine())
|
||||||
|
return false;
|
||||||
// Create the semantics context
|
// Create the semantics context
|
||||||
semaContext = invoc.getSemanticsCtx(*allCookedSources);
|
semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine());
|
||||||
// Set options controlling lowering to FIR.
|
// Set options controlling lowering to FIR.
|
||||||
invoc.setLoweringOptions();
|
invoc.setLoweringOptions();
|
||||||
|
|
||||||
@ -197,3 +203,129 @@ CompilerInstance::createDiagnostics(clang::DiagnosticOptions *opts,
|
|||||||
}
|
}
|
||||||
return diags;
|
return diags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get feature string which represents combined explicit target features
|
||||||
|
// for AMD GPU and the target features specified by the user
|
||||||
|
static std::string
|
||||||
|
getExplicitAndImplicitAMDGPUTargetFeatures(clang::DiagnosticsEngine &diags,
|
||||||
|
const TargetOptions &targetOpts,
|
||||||
|
const llvm::Triple triple) {
|
||||||
|
llvm::StringRef cpu = targetOpts.cpu;
|
||||||
|
llvm::StringMap<bool> implicitFeaturesMap;
|
||||||
|
std::string errorMsg;
|
||||||
|
// Get the set of implicit target features
|
||||||
|
llvm::AMDGPU::fillAMDGPUFeatureMap(cpu, triple, implicitFeaturesMap);
|
||||||
|
|
||||||
|
// Add target features specified by the user
|
||||||
|
for (auto &userFeature : targetOpts.featuresAsWritten) {
|
||||||
|
std::string userKeyString = userFeature.substr(1);
|
||||||
|
implicitFeaturesMap[userKeyString] = (userFeature[0] == '+');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!llvm::AMDGPU::insertWaveSizeFeature(cpu, triple, implicitFeaturesMap,
|
||||||
|
errorMsg)) {
|
||||||
|
unsigned diagID = diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
|
||||||
|
"Unsupported feature ID: %0");
|
||||||
|
diags.Report(diagID) << errorMsg.data();
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::SmallVector<std::string> featuresVec;
|
||||||
|
for (auto &implicitFeatureItem : implicitFeaturesMap) {
|
||||||
|
featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
|
||||||
|
implicitFeatureItem.first().str())
|
||||||
|
.str());
|
||||||
|
}
|
||||||
|
llvm::sort(featuresVec);
|
||||||
|
return llvm::join(featuresVec, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get feature string which represents combined explicit target features
|
||||||
|
// for NVPTX and the target features specified by the user/
|
||||||
|
// TODO: Have a more robust target conf like `clang/lib/Basic/Targets/NVPTX.cpp`
|
||||||
|
static std::string
|
||||||
|
getExplicitAndImplicitNVPTXTargetFeatures(clang::DiagnosticsEngine &diags,
|
||||||
|
const TargetOptions &targetOpts,
|
||||||
|
const llvm::Triple triple) {
|
||||||
|
llvm::StringRef cpu = targetOpts.cpu;
|
||||||
|
llvm::StringMap<bool> implicitFeaturesMap;
|
||||||
|
std::string errorMsg;
|
||||||
|
bool ptxVer = false;
|
||||||
|
|
||||||
|
// Add target features specified by the user
|
||||||
|
for (auto &userFeature : targetOpts.featuresAsWritten) {
|
||||||
|
llvm::StringRef userKeyString(llvm::StringRef(userFeature).drop_front(1));
|
||||||
|
implicitFeaturesMap[userKeyString.str()] = (userFeature[0] == '+');
|
||||||
|
// Check if the user provided a PTX version
|
||||||
|
if (userKeyString.startswith("ptx"))
|
||||||
|
ptxVer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default PTX version to `ptx61` if none was provided.
|
||||||
|
// TODO: set the default PTX version based on the chip.
|
||||||
|
if (!ptxVer)
|
||||||
|
implicitFeaturesMap["ptx61"] = true;
|
||||||
|
|
||||||
|
// Set the compute capability.
|
||||||
|
implicitFeaturesMap[cpu.str()] = true;
|
||||||
|
|
||||||
|
llvm::SmallVector<std::string> featuresVec;
|
||||||
|
for (auto &implicitFeatureItem : implicitFeaturesMap) {
|
||||||
|
featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
|
||||||
|
implicitFeatureItem.first().str())
|
||||||
|
.str());
|
||||||
|
}
|
||||||
|
llvm::sort(featuresVec);
|
||||||
|
return llvm::join(featuresVec, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CompilerInstance::getTargetFeatures() {
|
||||||
|
const TargetOptions &targetOpts = getInvocation().getTargetOpts();
|
||||||
|
const llvm::Triple triple(targetOpts.triple);
|
||||||
|
|
||||||
|
// Clang does not append all target features to the clang -cc1 invocation.
|
||||||
|
// Some target features are parsed implicitly by clang::TargetInfo child
|
||||||
|
// class. Clang::TargetInfo classes are the basic clang classes and
|
||||||
|
// they cannot be reused by Flang.
|
||||||
|
// That's why we need to extract implicit target features and add
|
||||||
|
// them to the target features specified by the user
|
||||||
|
if (triple.isAMDGPU()) {
|
||||||
|
return getExplicitAndImplicitAMDGPUTargetFeatures(getDiagnostics(),
|
||||||
|
targetOpts, triple);
|
||||||
|
} else if (triple.isNVPTX()) {
|
||||||
|
return getExplicitAndImplicitNVPTXTargetFeatures(getDiagnostics(),
|
||||||
|
targetOpts, triple);
|
||||||
|
}
|
||||||
|
return llvm::join(targetOpts.featuresAsWritten.begin(),
|
||||||
|
targetOpts.featuresAsWritten.end(), ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompilerInstance::setUpTargetMachine() {
|
||||||
|
const TargetOptions &targetOpts = getInvocation().getTargetOpts();
|
||||||
|
const std::string &theTriple = targetOpts.triple;
|
||||||
|
|
||||||
|
// Create `Target`
|
||||||
|
std::string error;
|
||||||
|
const llvm::Target *theTarget =
|
||||||
|
llvm::TargetRegistry::lookupTarget(theTriple, error);
|
||||||
|
if (!theTarget) {
|
||||||
|
getDiagnostics().Report(clang::diag::err_fe_unable_to_create_target)
|
||||||
|
<< error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create `TargetMachine`
|
||||||
|
const auto &CGOpts = getInvocation().getCodeGenOpts();
|
||||||
|
std::optional<llvm::CodeGenOptLevel> OptLevelOrNone =
|
||||||
|
llvm::CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
|
||||||
|
assert(OptLevelOrNone && "Invalid optimization level!");
|
||||||
|
llvm::CodeGenOptLevel OptLevel = *OptLevelOrNone;
|
||||||
|
std::string featuresStr = getTargetFeatures();
|
||||||
|
targetMachine.reset(theTarget->createTargetMachine(
|
||||||
|
theTriple, /*CPU=*/targetOpts.cpu,
|
||||||
|
/*Features=*/featuresStr, llvm::TargetOptions(),
|
||||||
|
/*Reloc::Model=*/CGOpts.getRelocationModel(),
|
||||||
|
/*CodeModel::Model=*/std::nullopt, OptLevel));
|
||||||
|
assert(targetMachine && "Failed to create TargetMachine");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "flang/Frontend/PreprocessorOptions.h"
|
#include "flang/Frontend/PreprocessorOptions.h"
|
||||||
#include "flang/Frontend/TargetOptions.h"
|
#include "flang/Frontend/TargetOptions.h"
|
||||||
#include "flang/Semantics/semantics.h"
|
#include "flang/Semantics/semantics.h"
|
||||||
|
#include "flang/Tools/TargetSetup.h"
|
||||||
#include "flang/Version.inc"
|
#include "flang/Version.inc"
|
||||||
#include "clang/Basic/AllDiagnostics.h"
|
#include "clang/Basic/AllDiagnostics.h"
|
||||||
#include "clang/Basic/DiagnosticDriver.h"
|
#include "clang/Basic/DiagnosticDriver.h"
|
||||||
@ -1347,7 +1348,8 @@ void CompilerInvocation::setFortranOpts() {
|
|||||||
|
|
||||||
std::unique_ptr<Fortran::semantics::SemanticsContext>
|
std::unique_ptr<Fortran::semantics::SemanticsContext>
|
||||||
CompilerInvocation::getSemanticsCtx(
|
CompilerInvocation::getSemanticsCtx(
|
||||||
Fortran::parser::AllCookedSources &allCookedSources) {
|
Fortran::parser::AllCookedSources &allCookedSources,
|
||||||
|
const llvm::TargetMachine &targetMachine) {
|
||||||
auto &fortranOptions = getFortranOpts();
|
auto &fortranOptions = getFortranOpts();
|
||||||
|
|
||||||
auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
|
auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
|
||||||
@ -1360,21 +1362,10 @@ CompilerInvocation::getSemanticsCtx(
|
|||||||
.set_moduleFileSuffix(getModuleFileSuffix())
|
.set_moduleFileSuffix(getModuleFileSuffix())
|
||||||
.set_underscoring(getCodeGenOpts().Underscoring);
|
.set_underscoring(getCodeGenOpts().Underscoring);
|
||||||
|
|
||||||
llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
|
std::string compilerVersion = Fortran::common::getFlangFullVersion();
|
||||||
// FIXME: Handle real(3) ?
|
Fortran::tools::setUpTargetCharacteristics(
|
||||||
if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
|
semanticsContext->targetCharacteristics(), targetMachine, compilerVersion,
|
||||||
semanticsContext->targetCharacteristics().DisableType(
|
allCompilerInvocOpts);
|
||||||
Fortran::common::TypeCategory::Real, /*kind=*/10);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string version = Fortran::common::getFlangFullVersion();
|
|
||||||
semanticsContext->targetCharacteristics()
|
|
||||||
.set_compilerOptionsString(allCompilerInvocOpts)
|
|
||||||
.set_compilerVersionString(version);
|
|
||||||
|
|
||||||
if (targetTriple.isPPC())
|
|
||||||
semanticsContext->targetCharacteristics().set_isPPC(true);
|
|
||||||
|
|
||||||
return semanticsContext;
|
return semanticsContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "flang/Lower/Support/Verifier.h"
|
#include "flang/Lower/Support/Verifier.h"
|
||||||
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
||||||
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
||||||
|
#include "flang/Optimizer/Support/DataLayout.h"
|
||||||
#include "flang/Optimizer/Support/InitFIR.h"
|
#include "flang/Optimizer/Support/InitFIR.h"
|
||||||
#include "flang/Optimizer/Support/Utils.h"
|
#include "flang/Optimizer/Support/Utils.h"
|
||||||
#include "flang/Optimizer/Transforms/Passes.h"
|
#include "flang/Optimizer/Transforms/Passes.h"
|
||||||
@ -53,7 +54,6 @@
|
|||||||
#include "llvm/IR/LegacyPassManager.h"
|
#include "llvm/IR/LegacyPassManager.h"
|
||||||
#include "llvm/IR/Verifier.h"
|
#include "llvm/IR/Verifier.h"
|
||||||
#include "llvm/IRReader/IRReader.h"
|
#include "llvm/IRReader/IRReader.h"
|
||||||
#include "llvm/MC/TargetRegistry.h"
|
|
||||||
#include "llvm/Object/OffloadBinary.h"
|
#include "llvm/Object/OffloadBinary.h"
|
||||||
#include "llvm/Passes/PassBuilder.h"
|
#include "llvm/Passes/PassBuilder.h"
|
||||||
#include "llvm/Passes/PassPlugin.h"
|
#include "llvm/Passes/PassPlugin.h"
|
||||||
@ -65,7 +65,6 @@
|
|||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/ToolOutputFile.h"
|
#include "llvm/Support/ToolOutputFile.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/TargetParser/TargetParser.h"
|
|
||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
@ -139,111 +138,6 @@ bool PrescanAndSemaDebugAction::beginSourceFileAction() {
|
|||||||
(generateRtTypeTables() || true);
|
(generateRtTypeTables() || true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get feature string which represents combined explicit target features
|
|
||||||
// for AMD GPU and the target features specified by the user
|
|
||||||
static std::string
|
|
||||||
getExplicitAndImplicitAMDGPUTargetFeatures(CompilerInstance &ci,
|
|
||||||
const TargetOptions &targetOpts,
|
|
||||||
const llvm::Triple triple) {
|
|
||||||
llvm::StringRef cpu = targetOpts.cpu;
|
|
||||||
llvm::StringMap<bool> implicitFeaturesMap;
|
|
||||||
std::string errorMsg;
|
|
||||||
// Get the set of implicit target features
|
|
||||||
llvm::AMDGPU::fillAMDGPUFeatureMap(cpu, triple, implicitFeaturesMap);
|
|
||||||
|
|
||||||
// Add target features specified by the user
|
|
||||||
for (auto &userFeature : targetOpts.featuresAsWritten) {
|
|
||||||
std::string userKeyString = userFeature.substr(1);
|
|
||||||
implicitFeaturesMap[userKeyString] = (userFeature[0] == '+');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!llvm::AMDGPU::insertWaveSizeFeature(cpu, triple, implicitFeaturesMap,
|
|
||||||
errorMsg)) {
|
|
||||||
unsigned diagID = ci.getDiagnostics().getCustomDiagID(
|
|
||||||
clang::DiagnosticsEngine::Error, "Unsupported feature ID: %0");
|
|
||||||
ci.getDiagnostics().Report(diagID) << errorMsg.data();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::SmallVector<std::string> featuresVec;
|
|
||||||
for (auto &implicitFeatureItem : implicitFeaturesMap) {
|
|
||||||
featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
|
|
||||||
implicitFeatureItem.first().str())
|
|
||||||
.str());
|
|
||||||
}
|
|
||||||
llvm::sort(featuresVec);
|
|
||||||
return llvm::join(featuresVec, ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get feature string which represents combined explicit target features
|
|
||||||
// for NVPTX and the target features specified by the user/
|
|
||||||
// TODO: Have a more robust target conf like `clang/lib/Basic/Targets/NVPTX.cpp`
|
|
||||||
static std::string
|
|
||||||
getExplicitAndImplicitNVPTXTargetFeatures(CompilerInstance &ci,
|
|
||||||
const TargetOptions &targetOpts,
|
|
||||||
const llvm::Triple triple) {
|
|
||||||
llvm::StringRef cpu = targetOpts.cpu;
|
|
||||||
llvm::StringMap<bool> implicitFeaturesMap;
|
|
||||||
std::string errorMsg;
|
|
||||||
bool ptxVer = false;
|
|
||||||
|
|
||||||
// Add target features specified by the user
|
|
||||||
for (auto &userFeature : targetOpts.featuresAsWritten) {
|
|
||||||
llvm::StringRef userKeyString(llvm::StringRef(userFeature).drop_front(1));
|
|
||||||
implicitFeaturesMap[userKeyString.str()] = (userFeature[0] == '+');
|
|
||||||
// Check if the user provided a PTX version
|
|
||||||
if (userKeyString.startswith("ptx"))
|
|
||||||
ptxVer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the default PTX version to `ptx61` if none was provided.
|
|
||||||
// TODO: set the default PTX version based on the chip.
|
|
||||||
if (!ptxVer)
|
|
||||||
implicitFeaturesMap["ptx61"] = true;
|
|
||||||
|
|
||||||
// Set the compute capability.
|
|
||||||
implicitFeaturesMap[cpu.str()] = true;
|
|
||||||
|
|
||||||
llvm::SmallVector<std::string> featuresVec;
|
|
||||||
for (auto &implicitFeatureItem : implicitFeaturesMap) {
|
|
||||||
featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
|
|
||||||
implicitFeatureItem.first().str())
|
|
||||||
.str());
|
|
||||||
}
|
|
||||||
llvm::sort(featuresVec);
|
|
||||||
return llvm::join(featuresVec, ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Produces the string which represents target feature
|
|
||||||
static std::string getTargetFeatures(CompilerInstance &ci) {
|
|
||||||
const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
|
|
||||||
const llvm::Triple triple(targetOpts.triple);
|
|
||||||
|
|
||||||
// Clang does not append all target features to the clang -cc1 invocation.
|
|
||||||
// Some target features are parsed implicitly by clang::TargetInfo child
|
|
||||||
// class. Clang::TargetInfo classes are the basic clang classes and
|
|
||||||
// they cannot be reused by Flang.
|
|
||||||
// That's why we need to extract implicit target features and add
|
|
||||||
// them to the target features specified by the user
|
|
||||||
if (triple.isAMDGPU()) {
|
|
||||||
return getExplicitAndImplicitAMDGPUTargetFeatures(ci, targetOpts, triple);
|
|
||||||
} else if (triple.isNVPTX()) {
|
|
||||||
return getExplicitAndImplicitNVPTXTargetFeatures(ci, targetOpts, triple);
|
|
||||||
}
|
|
||||||
return llvm::join(targetOpts.featuresAsWritten.begin(),
|
|
||||||
targetOpts.featuresAsWritten.end(), ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setMLIRDataLayout(mlir::ModuleOp &mlirModule,
|
|
||||||
const llvm::DataLayout &dl) {
|
|
||||||
mlir::MLIRContext *context = mlirModule.getContext();
|
|
||||||
mlirModule->setAttr(
|
|
||||||
mlir::LLVM::LLVMDialect::getDataLayoutAttrName(),
|
|
||||||
mlir::StringAttr::get(context, dl.getStringRepresentation()));
|
|
||||||
mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, context);
|
|
||||||
mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) {
|
static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) {
|
||||||
const std::vector<std::string> &libs =
|
const std::vector<std::string> &libs =
|
||||||
ci.getInvocation().getCodeGenOpts().DependentLibs;
|
ci.getInvocation().getCodeGenOpts().DependentLibs;
|
||||||
@ -352,6 +246,8 @@ bool CodeGenAction::beginSourceFileAction() {
|
|||||||
fir::support::loadDialects(*mlirCtx);
|
fir::support::loadDialects(*mlirCtx);
|
||||||
fir::support::registerLLVMTranslation(*mlirCtx);
|
fir::support::registerLLVMTranslation(*mlirCtx);
|
||||||
|
|
||||||
|
const llvm::TargetMachine &targetMachine = ci.getTargetMachine();
|
||||||
|
|
||||||
// If the input is an MLIR file, just parse it and return.
|
// If the input is an MLIR file, just parse it and return.
|
||||||
if (this->getCurrentInput().getKind().getLanguage() == Language::MLIR) {
|
if (this->getCurrentInput().getKind().getLanguage() == Language::MLIR) {
|
||||||
llvm::SourceMgr sourceMgr;
|
llvm::SourceMgr sourceMgr;
|
||||||
@ -369,10 +265,8 @@ bool CodeGenAction::beginSourceFileAction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mlirModule = std::make_unique<mlir::ModuleOp>(module.release());
|
mlirModule = std::make_unique<mlir::ModuleOp>(module.release());
|
||||||
if (!setUpTargetMachine())
|
const llvm::DataLayout &dl = targetMachine.createDataLayout();
|
||||||
return false;
|
fir::support::setMLIRDataLayout(*mlirModule, dl);
|
||||||
const llvm::DataLayout &dl = tm->createDataLayout();
|
|
||||||
setMLIRDataLayout(*mlirModule, dl);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +288,8 @@ bool CodeGenAction::beginSourceFileAction() {
|
|||||||
ci.getSemanticsContext().defaultKinds();
|
ci.getSemanticsContext().defaultKinds();
|
||||||
fir::KindMapping kindMap(mlirCtx.get(), llvm::ArrayRef<fir::KindTy>{
|
fir::KindMapping kindMap(mlirCtx.get(), llvm::ArrayRef<fir::KindTy>{
|
||||||
fir::fromDefaultKinds(defKinds)});
|
fir::fromDefaultKinds(defKinds)});
|
||||||
|
const llvm::DataLayout &dl = targetMachine.createDataLayout();
|
||||||
|
|
||||||
lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
|
lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
|
||||||
*mlirCtx, ci.getSemanticsContext(), defKinds,
|
*mlirCtx, ci.getSemanticsContext(), defKinds,
|
||||||
ci.getSemanticsContext().intrinsics(),
|
ci.getSemanticsContext().intrinsics(),
|
||||||
@ -401,27 +297,22 @@ bool CodeGenAction::beginSourceFileAction() {
|
|||||||
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
|
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
|
||||||
kindMap, ci.getInvocation().getLoweringOpts(),
|
kindMap, ci.getInvocation().getLoweringOpts(),
|
||||||
ci.getInvocation().getFrontendOpts().envDefaults,
|
ci.getInvocation().getFrontendOpts().envDefaults,
|
||||||
ci.getInvocation().getFrontendOpts().features);
|
ci.getInvocation().getFrontendOpts().features, &dl);
|
||||||
|
|
||||||
// Fetch module from lb, so we can set
|
// Fetch module from lb, so we can set
|
||||||
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
|
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
|
||||||
|
|
||||||
if (!setUpTargetMachine())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
|
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
|
||||||
Fortran::common::LanguageFeature::OpenMP)) {
|
Fortran::common::LanguageFeature::OpenMP)) {
|
||||||
setOffloadModuleInterfaceAttributes(*mlirModule,
|
setOffloadModuleInterfaceAttributes(*mlirModule,
|
||||||
ci.getInvocation().getLangOpts());
|
ci.getInvocation().getLangOpts());
|
||||||
setOffloadModuleInterfaceTargetAttribute(*mlirModule, tm->getTargetCPU(),
|
setOffloadModuleInterfaceTargetAttribute(
|
||||||
tm->getTargetFeatureString());
|
*mlirModule, targetMachine.getTargetCPU(),
|
||||||
|
targetMachine.getTargetFeatureString());
|
||||||
setOpenMPVersionAttribute(*mlirModule,
|
setOpenMPVersionAttribute(*mlirModule,
|
||||||
ci.getInvocation().getLangOpts().OpenMPVersion);
|
ci.getInvocation().getLangOpts().OpenMPVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm::DataLayout &dl = tm->createDataLayout();
|
|
||||||
setMLIRDataLayout(*mlirModule, dl);
|
|
||||||
|
|
||||||
// Create a parse tree and lower it to FIR
|
// Create a parse tree and lower it to FIR
|
||||||
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
|
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
|
||||||
lb.lower(parseTree, ci.getSemanticsContext());
|
lb.lower(parseTree, ci.getSemanticsContext());
|
||||||
@ -830,7 +721,7 @@ getVScaleRange(CompilerInstance &ci,
|
|||||||
return std::pair<unsigned, unsigned>(
|
return std::pair<unsigned, unsigned>(
|
||||||
langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
|
langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
|
||||||
|
|
||||||
std::string featuresStr = getTargetFeatures(ci);
|
std::string featuresStr = ci.getTargetFeatures();
|
||||||
if (featuresStr.find("+sve") != std::string::npos)
|
if (featuresStr.find("+sve") != std::string::npos)
|
||||||
return std::pair<unsigned, unsigned>(1, 16);
|
return std::pair<unsigned, unsigned>(1, 16);
|
||||||
|
|
||||||
@ -911,38 +802,6 @@ void CodeGenAction::generateLLVMIR() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGenAction::setUpTargetMachine() {
|
|
||||||
CompilerInstance &ci = this->getInstance();
|
|
||||||
|
|
||||||
const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
|
|
||||||
const std::string &theTriple = targetOpts.triple;
|
|
||||||
|
|
||||||
// Create `Target`
|
|
||||||
std::string error;
|
|
||||||
const llvm::Target *theTarget =
|
|
||||||
llvm::TargetRegistry::lookupTarget(theTriple, error);
|
|
||||||
if (!theTarget) {
|
|
||||||
ci.getDiagnostics().Report(clang::diag::err_fe_unable_to_create_target)
|
|
||||||
<< error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create `TargetMachine`
|
|
||||||
const auto &CGOpts = ci.getInvocation().getCodeGenOpts();
|
|
||||||
std::optional<llvm::CodeGenOptLevel> OptLevelOrNone =
|
|
||||||
llvm::CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
|
|
||||||
assert(OptLevelOrNone && "Invalid optimization level!");
|
|
||||||
llvm::CodeGenOptLevel OptLevel = *OptLevelOrNone;
|
|
||||||
std::string featuresStr = getTargetFeatures(ci);
|
|
||||||
tm.reset(theTarget->createTargetMachine(
|
|
||||||
theTriple, /*CPU=*/targetOpts.cpu,
|
|
||||||
/*Features=*/featuresStr, llvm::TargetOptions(),
|
|
||||||
/*Reloc::Model=*/CGOpts.getRelocationModel(),
|
|
||||||
/*CodeModel::Model=*/std::nullopt, OptLevel));
|
|
||||||
assert(tm && "Failed to create TargetMachine");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<llvm::raw_pwrite_stream>
|
static std::unique_ptr<llvm::raw_pwrite_stream>
|
||||||
getOutputStream(CompilerInstance &ci, llvm::StringRef inFile,
|
getOutputStream(CompilerInstance &ci, llvm::StringRef inFile,
|
||||||
BackendActionTy action) {
|
BackendActionTy action) {
|
||||||
@ -1020,6 +879,7 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
|
|||||||
auto &diags = getInstance().getDiagnostics();
|
auto &diags = getInstance().getDiagnostics();
|
||||||
llvm::OptimizationLevel level = mapToLevel(opts);
|
llvm::OptimizationLevel level = mapToLevel(opts);
|
||||||
|
|
||||||
|
llvm::TargetMachine *targetMachine = &getInstance().getTargetMachine();
|
||||||
// Create the analysis managers.
|
// Create the analysis managers.
|
||||||
llvm::LoopAnalysisManager lam;
|
llvm::LoopAnalysisManager lam;
|
||||||
llvm::FunctionAnalysisManager fam;
|
llvm::FunctionAnalysisManager fam;
|
||||||
@ -1033,7 +893,7 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
|
|||||||
llvm::StandardInstrumentations si(llvmModule->getContext(),
|
llvm::StandardInstrumentations si(llvmModule->getContext(),
|
||||||
opts.DebugPassManager);
|
opts.DebugPassManager);
|
||||||
si.registerCallbacks(pic, &mam);
|
si.registerCallbacks(pic, &mam);
|
||||||
llvm::PassBuilder pb(tm.get(), pto, pgoOpt, &pic);
|
llvm::PassBuilder pb(targetMachine, pto, pgoOpt, &pic);
|
||||||
|
|
||||||
// Attempt to load pass plugins and register their callbacks with PB.
|
// Attempt to load pass plugins and register their callbacks with PB.
|
||||||
for (auto &pluginFile : opts.LLVMPassPlugins) {
|
for (auto &pluginFile : opts.LLVMPassPlugins) {
|
||||||
@ -1299,9 +1159,8 @@ void CodeGenAction::executeAction() {
|
|||||||
// Set the triple based on the targetmachine (this comes compiler invocation
|
// Set the triple based on the targetmachine (this comes compiler invocation
|
||||||
// and the command-line target option if specified, or the default if not
|
// and the command-line target option if specified, or the default if not
|
||||||
// given on the command-line).
|
// given on the command-line).
|
||||||
if (!setUpTargetMachine())
|
llvm::TargetMachine &targetMachine = ci.getTargetMachine();
|
||||||
return;
|
const std::string &theTriple = targetMachine.getTargetTriple().str();
|
||||||
const std::string &theTriple = tm->getTargetTriple().str();
|
|
||||||
|
|
||||||
if (llvmModule->getTargetTriple() != theTriple) {
|
if (llvmModule->getTargetTriple() != theTriple) {
|
||||||
diags.Report(clang::diag::warn_fe_override_module) << theTriple;
|
diags.Report(clang::diag::warn_fe_override_module) << theTriple;
|
||||||
@ -1311,7 +1170,7 @@ void CodeGenAction::executeAction() {
|
|||||||
// Note that this overwrites any datalayout stored in the LLVM-IR. This avoids
|
// Note that this overwrites any datalayout stored in the LLVM-IR. This avoids
|
||||||
// an assert for incompatible data layout when the code-generation happens.
|
// an assert for incompatible data layout when the code-generation happens.
|
||||||
llvmModule->setTargetTriple(theTriple);
|
llvmModule->setTargetTriple(theTriple);
|
||||||
llvmModule->setDataLayout(tm->createDataLayout());
|
llvmModule->setDataLayout(targetMachine.createDataLayout());
|
||||||
|
|
||||||
// Embed offload objects specified with -fembed-offload-object
|
// Embed offload objects specified with -fembed-offload-object
|
||||||
if (!codeGenOpts.OffloadObjects.empty())
|
if (!codeGenOpts.OffloadObjects.empty())
|
||||||
@ -1361,7 +1220,7 @@ void CodeGenAction::executeAction() {
|
|||||||
if (action == BackendActionTy::Backend_EmitAssembly ||
|
if (action == BackendActionTy::Backend_EmitAssembly ||
|
||||||
action == BackendActionTy::Backend_EmitObj) {
|
action == BackendActionTy::Backend_EmitObj) {
|
||||||
generateMachineCodeOrAssemblyImpl(
|
generateMachineCodeOrAssemblyImpl(
|
||||||
diags, *tm, action, *llvmModule, codeGenOpts,
|
diags, targetMachine, action, *llvmModule, codeGenOpts,
|
||||||
ci.isOutputStreamNull() ? *os : ci.getOutputStream());
|
ci.isOutputStreamNull() ? *os : ci.getOutputStream());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "flang/Optimizer/Dialect/FIROps.h"
|
#include "flang/Optimizer/Dialect/FIROps.h"
|
||||||
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
||||||
#include "flang/Optimizer/HLFIR/HLFIROps.h"
|
#include "flang/Optimizer/HLFIR/HLFIROps.h"
|
||||||
|
#include "flang/Optimizer/Support/DataLayout.h"
|
||||||
#include "flang/Optimizer/Support/FatalError.h"
|
#include "flang/Optimizer/Support/FatalError.h"
|
||||||
#include "flang/Optimizer/Support/InternalNames.h"
|
#include "flang/Optimizer/Support/InternalNames.h"
|
||||||
#include "flang/Optimizer/Transforms/Passes.h"
|
#include "flang/Optimizer/Transforms/Passes.h"
|
||||||
@ -5089,7 +5090,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
|
|||||||
fir::KindMapping &kindMap,
|
fir::KindMapping &kindMap,
|
||||||
const Fortran::lower::LoweringOptions &loweringOptions,
|
const Fortran::lower::LoweringOptions &loweringOptions,
|
||||||
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
|
||||||
const Fortran::common::LanguageFeatureControl &languageFeatures)
|
const Fortran::common::LanguageFeatureControl &languageFeatures,
|
||||||
|
const llvm::DataLayout *dataLayout)
|
||||||
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
|
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
|
||||||
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
|
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
|
||||||
cooked{&cooked}, context{context}, kindMap{kindMap},
|
cooked{&cooked}, context{context}, kindMap{kindMap},
|
||||||
@ -5145,4 +5147,6 @@ Fortran::lower::LoweringBridge::LoweringBridge(
|
|||||||
assert(module.get() && "module was not created");
|
assert(module.get() && "module was not created");
|
||||||
fir::setTargetTriple(*module.get(), triple);
|
fir::setTargetTriple(*module.get(), triple);
|
||||||
fir::setKindMapping(*module.get(), kindMap);
|
fir::setKindMapping(*module.get(), kindMap);
|
||||||
|
if (dataLayout)
|
||||||
|
fir::support::setMLIRDataLayout(*module.get(), *dataLayout);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
|
|||||||
get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
|
get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
|
||||||
|
|
||||||
add_flang_library(FIRSupport
|
add_flang_library(FIRSupport
|
||||||
|
DataLayout.cpp
|
||||||
InitFIR.cpp
|
InitFIR.cpp
|
||||||
InternalNames.cpp
|
InternalNames.cpp
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ add_flang_library(FIRSupport
|
|||||||
MLIROpenMPToLLVMIRTranslation
|
MLIROpenMPToLLVMIRTranslation
|
||||||
MLIRLLVMToLLVMIRTranslation
|
MLIRLLVMToLLVMIRTranslation
|
||||||
MLIRTargetLLVMIRExport
|
MLIRTargetLLVMIRExport
|
||||||
|
MLIRTargetLLVMIRImport
|
||||||
|
|
||||||
LINK_COMPONENTS
|
LINK_COMPONENTS
|
||||||
TargetParser
|
TargetParser
|
||||||
|
47
flang/lib/Optimizer/Support/DataLayout.cpp
Normal file
47
flang/lib/Optimizer/Support/DataLayout.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//===-- Optimizer/Support/DataLayout.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/Optimizer/Support/DataLayout.h"
|
||||||
|
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
||||||
|
#include "flang/Optimizer/Support/FatalError.h"
|
||||||
|
#include "mlir/Dialect/DLTI/DLTI.h"
|
||||||
|
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||||
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
|
#include "mlir/Interfaces/DataLayoutInterfaces.h"
|
||||||
|
#include "mlir/Support/LLVM.h"
|
||||||
|
#include "mlir/Target/LLVMIR/Import.h"
|
||||||
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
#include "llvm/MC/TargetRegistry.h"
|
||||||
|
#include "llvm/Support/TargetSelect.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
|
void fir::support::setMLIRDataLayout(mlir::ModuleOp mlirModule,
|
||||||
|
const llvm::DataLayout &dl) {
|
||||||
|
mlir::MLIRContext *context = mlirModule.getContext();
|
||||||
|
mlirModule->setAttr(
|
||||||
|
mlir::LLVM::LLVMDialect::getDataLayoutAttrName(),
|
||||||
|
mlir::StringAttr::get(context, dl.getStringRepresentation()));
|
||||||
|
mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, context);
|
||||||
|
mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fir::support::setMLIRDataLayoutFromAttributes(mlir::ModuleOp mlirModule,
|
||||||
|
bool allowDefaultLayout) {
|
||||||
|
if (mlirModule.getDataLayoutSpec())
|
||||||
|
return; // Already set.
|
||||||
|
if (auto dataLayoutString = mlirModule->getAttrOfType<mlir::StringAttr>(
|
||||||
|
mlir::LLVM::LLVMDialect::getDataLayoutAttrName())) {
|
||||||
|
llvm::DataLayout llvmDataLayout(dataLayoutString);
|
||||||
|
fir::support::setMLIRDataLayout(mlirModule, llvmDataLayout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!allowDefaultLayout)
|
||||||
|
return;
|
||||||
|
llvm::DataLayout llvmDataLayout("");
|
||||||
|
fir::support::setMLIRDataLayout(mlirModule, llvmDataLayout);
|
||||||
|
}
|
12
flang/test/Fir/tco-default-datalayout.fir
Normal file
12
flang/test/Fir/tco-default-datalayout.fir
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Test that tco tool sets a target independent data layout when none is
|
||||||
|
// provided. LLVM default data layout aligns i64 with 32 bits.
|
||||||
|
// RUN: tco -emit-fir %s | FileCheck %s
|
||||||
|
|
||||||
|
module {
|
||||||
|
}
|
||||||
|
// CHECK: module attributes {
|
||||||
|
// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<
|
||||||
|
// ...
|
||||||
|
// CHECK-SAME: #dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi64>>,
|
||||||
|
// ...
|
||||||
|
// CHECK-SAME: llvm.data_layout = ""
|
13
flang/test/Fir/tco-explicit-datalayout.fir
Normal file
13
flang/test/Fir/tco-explicit-datalayout.fir
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Test that tco tool preserves incoming llvm.data_layout and creates a
|
||||||
|
// related dlti.dl_spec attribute. This tests a weird datalayout where
|
||||||
|
// i64 would be 128 bit aligned.
|
||||||
|
// RUN: tco -emit-fir %s | FileCheck %s
|
||||||
|
|
||||||
|
module attributes {llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:128-i128:128-f80:128-n8:16:32:64-S128"} {
|
||||||
|
}
|
||||||
|
// CHECK: module attributes {
|
||||||
|
// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<
|
||||||
|
// ...
|
||||||
|
// CHECK-SAME: #dlti.dl_entry<i64, dense<128> : vector<2xi64>>,
|
||||||
|
// ...
|
||||||
|
// CHECK-SAME: llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:128-i128:128-f80:128-n8:16:32:64-S128"
|
9
flang/test/Lower/bbc-host-datalayout.f90
Normal file
9
flang/test/Lower/bbc-host-datalayout.f90
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
! Test bbc set-up of the target data layout from the host.
|
||||||
|
! RUN: bbc %s -o - | FileCheck %s
|
||||||
|
subroutine test
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
! CHECK: module attributes {
|
||||||
|
! CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<
|
||||||
|
! CHECK-SAME: llvm.data_layout = "{{[^"]}}
|
||||||
|
! CHECK-SAME: llvm.target_triple = "{{[^"]}}
|
10
flang/test/Lower/bbc-target-datalayout.f90
Normal file
10
flang/test/Lower/bbc-target-datalayout.f90
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
! Test bbc target override.
|
||||||
|
! REQUIRES: x86-registered-target
|
||||||
|
! RUN: bbc %s -target x86_64-unknown-linux-gnu -o - | FileCheck %s
|
||||||
|
subroutine test
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
! CHECK: module attributes {
|
||||||
|
! CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<
|
||||||
|
! CHECK-SAME: llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||||
|
! CHECK-SAME: llvm.target_triple = "x86_64-unknown-linux-gnu"
|
@ -1,3 +1,4 @@
|
|||||||
|
! REQUIRES: aarch64-registered-target
|
||||||
! RUN: %python %S/test_modfile.py %s %flang_fc1 -triple aarch64-unknown-linux-gnu
|
! RUN: %python %S/test_modfile.py %s %flang_fc1 -triple aarch64-unknown-linux-gnu
|
||||||
|
|
||||||
module m1
|
module m1
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
set(LLVM_LINK_COMPONENTS
|
set(LLVM_LINK_COMPONENTS
|
||||||
Passes
|
Passes
|
||||||
|
AllTargetsCodeGens
|
||||||
|
AllTargetsDescs
|
||||||
|
AllTargetsInfos
|
||||||
TargetParser
|
TargetParser
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "flang/Common/Fortran-features.h"
|
#include "flang/Common/Fortran-features.h"
|
||||||
#include "flang/Common/OpenMP-features.h"
|
#include "flang/Common/OpenMP-features.h"
|
||||||
|
#include "flang/Common/Version.h"
|
||||||
#include "flang/Common/default-kinds.h"
|
#include "flang/Common/default-kinds.h"
|
||||||
#include "flang/Lower/Bridge.h"
|
#include "flang/Lower/Bridge.h"
|
||||||
#include "flang/Lower/PFTBuilder.h"
|
#include "flang/Lower/PFTBuilder.h"
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#include "flang/Semantics/semantics.h"
|
#include "flang/Semantics/semantics.h"
|
||||||
#include "flang/Semantics/unparse-with-symbols.h"
|
#include "flang/Semantics/unparse-with-symbols.h"
|
||||||
#include "flang/Tools/CrossToolHelpers.h"
|
#include "flang/Tools/CrossToolHelpers.h"
|
||||||
|
#include "flang/Tools/TargetSetup.h"
|
||||||
#include "flang/Version.inc"
|
#include "flang/Version.inc"
|
||||||
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
||||||
#include "mlir/IR/AsmState.h"
|
#include "mlir/IR/AsmState.h"
|
||||||
@ -50,6 +52,7 @@
|
|||||||
#include "mlir/Pass/PassRegistry.h"
|
#include "mlir/Pass/PassRegistry.h"
|
||||||
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
||||||
#include "mlir/Transforms/Passes.h"
|
#include "mlir/Transforms/Passes.h"
|
||||||
|
#include "llvm/MC/TargetRegistry.h"
|
||||||
#include "llvm/Passes/OptimizationLevel.h"
|
#include "llvm/Passes/OptimizationLevel.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ErrorOr.h"
|
#include "llvm/Support/ErrorOr.h"
|
||||||
@ -63,6 +66,7 @@
|
|||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/TargetParser/Host.h"
|
#include "llvm/TargetParser/Host.h"
|
||||||
#include "llvm/TargetParser/Triple.h"
|
#include "llvm/TargetParser/Triple.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Some basic command-line options
|
// Some basic command-line options
|
||||||
@ -202,6 +206,10 @@ static llvm::cl::opt<bool> enableCUDA("fcuda",
|
|||||||
static llvm::cl::opt<bool> fixedForm("ffixed-form",
|
static llvm::cl::opt<bool> fixedForm("ffixed-form",
|
||||||
llvm::cl::desc("enable fixed form"),
|
llvm::cl::desc("enable fixed form"),
|
||||||
llvm::cl::init(false));
|
llvm::cl::init(false));
|
||||||
|
static llvm::cl::opt<std::string>
|
||||||
|
targetTripleOverride("target",
|
||||||
|
llvm::cl::desc("Override host target triple"),
|
||||||
|
llvm::cl::init(""));
|
||||||
|
|
||||||
#define FLANG_EXCLUDE_CODEGEN
|
#define FLANG_EXCLUDE_CODEGEN
|
||||||
#include "flang/Tools/CLOptions.inc"
|
#include "flang/Tools/CLOptions.inc"
|
||||||
@ -221,6 +229,27 @@ static void registerAllPasses() {
|
|||||||
fir::registerOptTransformPasses();
|
fir::registerOptTransformPasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a target machine that is at least sufficient to get data-layout
|
||||||
|
/// information required by flang semantics and lowering. Note that it may not
|
||||||
|
/// contain all the CPU feature information to get optimized assembly generation
|
||||||
|
/// from LLVM IR. Drivers that needs to generate assembly from LLVM IR should
|
||||||
|
/// create a target machine according to their specific options.
|
||||||
|
static std::unique_ptr<llvm::TargetMachine>
|
||||||
|
createTargetMachine(llvm::StringRef targetTriple, std::string &error) {
|
||||||
|
std::string triple{targetTriple};
|
||||||
|
if (triple.empty())
|
||||||
|
triple = llvm::sys::getDefaultTargetTriple();
|
||||||
|
|
||||||
|
const llvm::Target *theTarget =
|
||||||
|
llvm::TargetRegistry::lookupTarget(triple, error);
|
||||||
|
if (!theTarget)
|
||||||
|
return nullptr;
|
||||||
|
return std::unique_ptr<llvm::TargetMachine>{
|
||||||
|
theTarget->createTargetMachine(triple, /*CPU=*/"",
|
||||||
|
/*Features=*/"", llvm::TargetOptions(),
|
||||||
|
/*Reloc::Model=*/std::nullopt)};
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Translate Fortran input to FIR, a dialect of MLIR.
|
// Translate Fortran input to FIR, a dialect of MLIR.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -229,7 +258,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
|
|||||||
std::string path, Fortran::parser::Options options,
|
std::string path, Fortran::parser::Options options,
|
||||||
const ProgramName &programPrefix,
|
const ProgramName &programPrefix,
|
||||||
Fortran::semantics::SemanticsContext &semanticsContext,
|
Fortran::semantics::SemanticsContext &semanticsContext,
|
||||||
const mlir::PassPipelineCLParser &passPipeline) {
|
const mlir::PassPipelineCLParser &passPipeline,
|
||||||
|
const llvm::TargetMachine &targetMachine) {
|
||||||
|
|
||||||
// prep for prescan and parse
|
// prep for prescan and parse
|
||||||
Fortran::parser::Parsing parsing{semanticsContext.allCookedSources()};
|
Fortran::parser::Parsing parsing{semanticsContext.allCookedSources()};
|
||||||
@ -295,6 +325,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
|
|||||||
auto &defKinds = semanticsContext.defaultKinds();
|
auto &defKinds = semanticsContext.defaultKinds();
|
||||||
fir::KindMapping kindMap(
|
fir::KindMapping kindMap(
|
||||||
&ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});
|
&ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});
|
||||||
|
const llvm::DataLayout &dataLayout = targetMachine.createDataLayout();
|
||||||
|
std::string targetTriple = targetMachine.getTargetTriple().normalize();
|
||||||
// Use default lowering options for bbc.
|
// Use default lowering options for bbc.
|
||||||
Fortran::lower::LoweringOptions loweringOptions{};
|
Fortran::lower::LoweringOptions loweringOptions{};
|
||||||
loweringOptions.setPolymorphicTypeImpl(enablePolymorphic);
|
loweringOptions.setPolymorphicTypeImpl(enablePolymorphic);
|
||||||
@ -302,8 +334,9 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
|
|||||||
loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);
|
loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);
|
||||||
auto burnside = Fortran::lower::LoweringBridge::create(
|
auto burnside = Fortran::lower::LoweringBridge::create(
|
||||||
ctx, semanticsContext, defKinds, semanticsContext.intrinsics(),
|
ctx, semanticsContext, defKinds, semanticsContext.intrinsics(),
|
||||||
semanticsContext.targetCharacteristics(), parsing.allCooked(), "",
|
semanticsContext.targetCharacteristics(), parsing.allCooked(),
|
||||||
kindMap, loweringOptions, {}, semanticsContext.languageFeatures());
|
targetTriple, kindMap, loweringOptions, {},
|
||||||
|
semanticsContext.languageFeatures(), &dataLayout);
|
||||||
burnside.lower(parseTree, semanticsContext);
|
burnside.lower(parseTree, semanticsContext);
|
||||||
mlir::ModuleOp mlirModule = burnside.getModule();
|
mlir::ModuleOp mlirModule = burnside.getModule();
|
||||||
if (enableOpenMP) {
|
if (enableOpenMP) {
|
||||||
@ -388,6 +421,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
[[maybe_unused]] llvm::InitLLVM y(argc, argv);
|
[[maybe_unused]] llvm::InitLLVM y(argc, argv);
|
||||||
|
llvm::InitializeAllTargets();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
registerAllPasses();
|
registerAllPasses();
|
||||||
|
|
||||||
mlir::registerMLIRContextCLOptions();
|
mlir::registerMLIRContextCLOptions();
|
||||||
@ -453,17 +488,21 @@ int main(int argc, char **argv) {
|
|||||||
.set_warnOnNonstandardUsage(warnStdViolation)
|
.set_warnOnNonstandardUsage(warnStdViolation)
|
||||||
.set_warningsAreErrors(warnIsError);
|
.set_warningsAreErrors(warnIsError);
|
||||||
|
|
||||||
llvm::Triple targetTriple{llvm::Triple(
|
std::string error;
|
||||||
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))};
|
// Create host target machine.
|
||||||
// FIXME: Handle real(3) ?
|
std::unique_ptr<llvm::TargetMachine> targetMachine =
|
||||||
if (targetTriple.getArch() != llvm::Triple::ArchType::x86 &&
|
createTargetMachine(targetTripleOverride, error);
|
||||||
targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
|
if (!targetMachine) {
|
||||||
semanticsContext.targetCharacteristics().DisableType(
|
llvm::errs() << "failed to create target machine: " << error << "\n";
|
||||||
Fortran::common::TypeCategory::Real, /*kind=*/10);
|
return mlir::failed(mlir::failure());
|
||||||
}
|
}
|
||||||
if (targetTriple.isPPC())
|
std::string compilerVersion = Fortran::common::getFlangToolFullVersion("bbc");
|
||||||
semanticsContext.targetCharacteristics().set_isPPC(true);
|
std::string compilerOptions = "";
|
||||||
|
Fortran::tools::setUpTargetCharacteristics(
|
||||||
|
semanticsContext.targetCharacteristics(), *targetMachine, compilerVersion,
|
||||||
|
compilerOptions);
|
||||||
|
|
||||||
return mlir::failed(convertFortranSourceToMLIR(
|
return mlir::failed(
|
||||||
inputFilename, options, programPrefix, semanticsContext, passPipe));
|
convertFortranSourceToMLIR(inputFilename, options, programPrefix,
|
||||||
|
semanticsContext, passPipe, *targetMachine));
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,14 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
|
|
||||||
# The module contains PPC vector types that needs the PPC target.
|
# The module contains PPC vector types that needs the PPC target.
|
||||||
set(opts "")
|
set(opts "")
|
||||||
if(${filename} STREQUAL "__ppc_intrinsics" OR
|
if(${filename} STREQUAL "__ppc_intrinsics" OR
|
||||||
${filename} STREQUAL "mma")
|
${filename} STREQUAL "mma")
|
||||||
set(opts "--target=ppc64le")
|
if (PowerPC IN_LIST LLVM_TARGETS_TO_BUILD)
|
||||||
|
set(opts "--target=ppc64le")
|
||||||
|
else()
|
||||||
|
# Do not compile PPC module if the target is not available.
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${base}.mod
|
add_custom_command(OUTPUT ${base}.mod
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "flang/Optimizer/CodeGen/CodeGen.h"
|
#include "flang/Optimizer/CodeGen/CodeGen.h"
|
||||||
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
|
||||||
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
|
||||||
|
#include "flang/Optimizer/Support/DataLayout.h"
|
||||||
#include "flang/Optimizer/Support/InitFIR.h"
|
#include "flang/Optimizer/Support/InitFIR.h"
|
||||||
#include "flang/Optimizer/Support/InternalNames.h"
|
#include "flang/Optimizer/Support/InternalNames.h"
|
||||||
#include "flang/Optimizer/Transforms/Passes.h"
|
#include "flang/Optimizer/Transforms/Passes.h"
|
||||||
@ -61,9 +62,8 @@ static cl::opt<bool> codeGenLLVM(
|
|||||||
|
|
||||||
#include "flang/Tools/CLOptions.inc"
|
#include "flang/Tools/CLOptions.inc"
|
||||||
|
|
||||||
static void printModuleBody(mlir::ModuleOp mod, raw_ostream &output) {
|
static void printModule(mlir::ModuleOp mod, raw_ostream &output) {
|
||||||
for (auto &op : *mod.getBody())
|
output << mod << '\n';
|
||||||
output << op << '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile a .fir file
|
// compile a .fir file
|
||||||
@ -104,6 +104,10 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
|
|||||||
fir::KindMapping kindMap{&context};
|
fir::KindMapping kindMap{&context};
|
||||||
fir::setTargetTriple(*owningRef, targetTriple);
|
fir::setTargetTriple(*owningRef, targetTriple);
|
||||||
fir::setKindMapping(*owningRef, kindMap);
|
fir::setKindMapping(*owningRef, kindMap);
|
||||||
|
// tco is a testing tool, so it will happily use the target independent
|
||||||
|
// data layout if none is on the module.
|
||||||
|
fir::support::setMLIRDataLayoutFromAttributes(*owningRef,
|
||||||
|
/*allowDefaultLayout=*/true);
|
||||||
mlir::PassManager pm((*owningRef)->getName(),
|
mlir::PassManager pm((*owningRef)->getName(),
|
||||||
mlir::OpPassManager::Nesting::Implicit);
|
mlir::OpPassManager::Nesting::Implicit);
|
||||||
pm.enableVerifier(/*verifyPasses=*/true);
|
pm.enableVerifier(/*verifyPasses=*/true);
|
||||||
@ -135,13 +139,13 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
|
|||||||
if (mlir::succeeded(pm.run(*owningRef))) {
|
if (mlir::succeeded(pm.run(*owningRef))) {
|
||||||
// passes ran successfully, so keep the output
|
// passes ran successfully, so keep the output
|
||||||
if ((emitFir || passPipeline.hasAnyOccurrences()) && !codeGenLLVM)
|
if ((emitFir || passPipeline.hasAnyOccurrences()) && !codeGenLLVM)
|
||||||
printModuleBody(*owningRef, out.os());
|
printModule(*owningRef, out.os());
|
||||||
out.keep();
|
out.keep();
|
||||||
return mlir::success();
|
return mlir::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass manager failed
|
// pass manager failed
|
||||||
printModuleBody(*owningRef, errs());
|
printModule(*owningRef, errs());
|
||||||
errs() << "\n\nFAILED: " << inputFilename << '\n';
|
errs() << "\n\nFAILED: " << inputFilename << '\n';
|
||||||
return mlir::failure();
|
return mlir::failure();
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,13 @@ protected:
|
|||||||
compInst.createDiagnostics();
|
compInst.createDiagnostics();
|
||||||
invoc = std::make_shared<CompilerInvocation>();
|
invoc = std::make_shared<CompilerInvocation>();
|
||||||
|
|
||||||
|
// Set-up default target triple and initialize LLVM Targets so that the
|
||||||
|
// target data layout can be passed to the frontend.
|
||||||
|
invoc->getTargetOpts().triple =
|
||||||
|
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
|
||||||
|
llvm::InitializeAllTargets();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
|
||||||
compInst.setInvocation(std::move(invoc));
|
compInst.setInvocation(std::move(invoc));
|
||||||
compInst.getFrontendOpts().inputs.push_back(
|
compInst.getFrontendOpts().inputs.push_back(
|
||||||
FrontendInputFile(inputFilePath, Language::Fortran));
|
FrontendInputFile(inputFilePath, Language::Fortran));
|
||||||
@ -174,13 +181,7 @@ TEST_F(FrontendActionTest, EmitLLVM) {
|
|||||||
// Set-up the action kind.
|
// Set-up the action kind.
|
||||||
compInst.getInvocation().getFrontendOpts().programAction = EmitLLVM;
|
compInst.getInvocation().getFrontendOpts().programAction = EmitLLVM;
|
||||||
|
|
||||||
// Set-up default target triple.
|
|
||||||
compInst.getInvocation().getTargetOpts().triple =
|
|
||||||
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
|
|
||||||
|
|
||||||
// Initialise LLVM backend
|
// Initialise LLVM backend
|
||||||
llvm::InitializeAllTargets();
|
|
||||||
llvm::InitializeAllTargetMCs();
|
|
||||||
llvm::InitializeAllAsmPrinters();
|
llvm::InitializeAllAsmPrinters();
|
||||||
|
|
||||||
// Set-up the output stream. We are using output buffer wrapped as an output
|
// Set-up the output stream. We are using output buffer wrapped as an output
|
||||||
@ -209,13 +210,7 @@ TEST_F(FrontendActionTest, EmitAsm) {
|
|||||||
// Set-up the action kind.
|
// Set-up the action kind.
|
||||||
compInst.getInvocation().getFrontendOpts().programAction = EmitAssembly;
|
compInst.getInvocation().getFrontendOpts().programAction = EmitAssembly;
|
||||||
|
|
||||||
// Set-up default target triple.
|
|
||||||
compInst.getInvocation().getTargetOpts().triple =
|
|
||||||
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
|
|
||||||
|
|
||||||
// Initialise LLVM backend
|
// Initialise LLVM backend
|
||||||
llvm::InitializeAllTargets();
|
|
||||||
llvm::InitializeAllTargetMCs();
|
|
||||||
llvm::InitializeAllAsmPrinters();
|
llvm::InitializeAllAsmPrinters();
|
||||||
|
|
||||||
// Set-up the output stream. We are using output buffer wrapped as an output
|
// Set-up the output stream. We are using output buffer wrapped as an output
|
||||||
|
Loading…
x
Reference in New Issue
Block a user