blob: 4061d3b2e58c7628cd7aab7eccab61f83c42e7e0 [file]
//===--- LowerModule.cpp - Lower CIR Module to a Target -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file partially mimics clang/lib/CodeGen/CodeGenModule.cpp. The queries
// are adapted to operate on the CIR dialect, however.
//
//===----------------------------------------------------------------------===//
#include "LowerModule.h"
#include "CIRCXXABI.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
namespace cir {
static std::unique_ptr<CIRCXXABI> createCXXABI(LowerModule &lm) {
switch (lm.getCXXABIKind()) {
case clang::TargetCXXABI::AppleARM64:
case clang::TargetCXXABI::Fuchsia:
case clang::TargetCXXABI::GenericAArch64:
case clang::TargetCXXABI::GenericARM:
case clang::TargetCXXABI::iOS:
case clang::TargetCXXABI::WatchOS:
case clang::TargetCXXABI::GenericMIPS:
case clang::TargetCXXABI::GenericItanium:
case clang::TargetCXXABI::WebAssembly:
case clang::TargetCXXABI::XL:
return createItaniumCXXABI(lm);
case clang::TargetCXXABI::Microsoft:
llvm_unreachable("Windows ABI NYI");
}
llvm_unreachable("invalid C++ ABI kind");
}
static std::unique_ptr<TargetLoweringInfo>
createTargetLoweringInfo(LowerModule &lm) {
const llvm::Triple &triple = lm.getTarget().getTriple();
switch (triple.getArch()) {
case llvm::Triple::amdgpu:
return createAMDGPUTargetLoweringInfo();
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
return createNVPTXTargetLoweringInfo();
case llvm::Triple::spirv:
case llvm::Triple::spirv32:
case llvm::Triple::spirv64:
return createSPIRVTargetLoweringInfo();
default:
assert(!cir::MissingFeatures::targetLoweringInfo());
return std::make_unique<TargetLoweringInfo>();
}
}
LowerModule::LowerModule(clang::LangOptions langOpts,
clang::CodeGenOptions codeGenOpts,
mlir::ModuleOp &module,
std::unique_ptr<clang::TargetInfo> target)
: module(module), target(std::move(target)), abi(createCXXABI(*this)) {}
const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
if (!targetLoweringInfo)
targetLoweringInfo = createTargetLoweringInfo(*this);
return *targetLoweringInfo;
}
// TODO: not to create it every time
std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
return nullptr;
// Fetch target information.
llvm::Triple triple(mlir::cast<mlir::StringAttr>(
module->getAttr(cir::CIRDialect::getTripleAttrName()))
.getValue());
clang::TargetOptions targetOptions;
targetOptions.Triple = triple.str();
auto targetInfo = clang::targets::AllocateTarget(triple, targetOptions);
// FIXME(cir): This just uses the default language options. We need to account
// for custom options.
// Create context.
assert(!cir::MissingFeatures::lowerModuleLangOpts());
clang::LangOptions langOpts;
// FIXME(cir): This just uses the default code generation options. We need to
// account for custom options.
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
codeGenOpts.OptimizationLevel = optInfo.getLevel();
codeGenOpts.OptimizeSize = optInfo.getSize();
}
return std::make_unique<LowerModule>(std::move(langOpts),
std::move(codeGenOpts), module,
std::move(targetInfo));
}
} // namespace cir