Clang and other frontends generally need the LLVM data layout string in
order to generate LLVM IR modules for LLVM. MLIR clients often need it
as well, since MLIR users often lower to LLVM IR.
Before this change, the LLVM datalayout string was computed in the
LLVM${TGT}CodeGen library in the relevant TargetMachine subclass.
However, none of the logic for computing the data layout string requires
any details of code generation. Clients who want to avoid duplicating
this information were forced to link in LLVMCodeGen and all registered
targets, leading to bloated binaries. This happened in PR #145899,
which measurably increased binary size for some of our users.
By moving this information to the TargetParser library, we
can delete the duplicate datalayout strings in Clang, and retain the
ability to generate IR for unregistered targets.
This is intended to be a very mechanical LLVM-only change, but there is
an immediately obvious follow-up to clang, which will be prepared
separately.
The vast majority of data layouts are computable with two inputs: the
triple and the "ABI name". There is only one exception, NVPTX, which has
a cl::opt to enable short device pointers. I invented a "shortptr" ABI
name to pass this option through the target independent interface.
Everything else fits. Mips is a bit awkward because it uses a special
MipsABIInfo abstraction, which includes members with codegen-like
concepts like ABI physical registers that can't live in TargetParser. I
think the string logic of looking for "n32" "n64" etc is reasonable to
duplicate. We have plenty of other minor duplication to preserve
layering.
---------
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
Co-authored-by: Sergei Barannikov <barannikov88@gmail.com>
143 lines
4.5 KiB
C++
143 lines
4.5 KiB
C++
//===-- AVRTargetMachine.cpp - Define TargetMachine for AVR ---------------===//
|
|
//
|
|
// 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 defines the AVR specific subclass of TargetMachine.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AVRTargetMachine.h"
|
|
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "AVR.h"
|
|
#include "AVRMachineFunctionInfo.h"
|
|
#include "AVRTargetObjectFile.h"
|
|
#include "AVRTargetTransformInfo.h"
|
|
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
|
#include "TargetInfo/AVRTargetInfo.h"
|
|
|
|
#include <optional>
|
|
|
|
namespace llvm {
|
|
|
|
/// Processes a CPU name.
|
|
static StringRef getCPU(StringRef CPU) {
|
|
if (CPU.empty() || CPU == "generic") {
|
|
return "avr2";
|
|
}
|
|
|
|
return CPU;
|
|
}
|
|
|
|
static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
|
|
return RM.value_or(Reloc::Static);
|
|
}
|
|
|
|
AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,
|
|
StringRef CPU, StringRef FS,
|
|
const TargetOptions &Options,
|
|
std::optional<Reloc::Model> RM,
|
|
std::optional<CodeModel::Model> CM,
|
|
CodeGenOptLevel OL, bool JIT)
|
|
: CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, getCPU(CPU), FS,
|
|
Options, getEffectiveRelocModel(RM),
|
|
getEffectiveCodeModel(CM, CodeModel::Small), OL),
|
|
SubTarget(TT, std::string(getCPU(CPU)), std::string(FS), *this) {
|
|
this->TLOF = std::make_unique<AVRTargetObjectFile>();
|
|
initAsmInfo();
|
|
}
|
|
|
|
namespace {
|
|
/// AVR Code Generator Pass Configuration Options.
|
|
class AVRPassConfig : public TargetPassConfig {
|
|
public:
|
|
AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {
|
|
EnableLoopTermFold = true;
|
|
}
|
|
|
|
AVRTargetMachine &getAVRTargetMachine() const {
|
|
return getTM<AVRTargetMachine>();
|
|
}
|
|
|
|
void addIRPasses() override;
|
|
bool addInstSelector() override;
|
|
void addPreSched2() override;
|
|
void addPreEmitPass() override;
|
|
};
|
|
} // namespace
|
|
|
|
TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
return new AVRPassConfig(*this, PM);
|
|
}
|
|
|
|
void AVRPassConfig::addIRPasses() {
|
|
// Expand instructions like
|
|
// %result = shl i32 %n, %amount
|
|
// to a loop so that library calls are avoided.
|
|
addPass(createAVRShiftExpandPass());
|
|
|
|
TargetPassConfig::addIRPasses();
|
|
}
|
|
|
|
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() {
|
|
// Register the target.
|
|
RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
|
|
|
|
auto &PR = *PassRegistry::getPassRegistry();
|
|
initializeAVRAsmPrinterPass(PR);
|
|
initializeAVRExpandPseudoPass(PR);
|
|
initializeAVRShiftExpandPass(PR);
|
|
initializeAVRDAGToDAGISelLegacyPass(PR);
|
|
}
|
|
|
|
const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
|
|
return &SubTarget;
|
|
}
|
|
|
|
const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {
|
|
return &SubTarget;
|
|
}
|
|
|
|
TargetTransformInfo
|
|
AVRTargetMachine::getTargetTransformInfo(const Function &F) const {
|
|
return TargetTransformInfo(std::make_unique<AVRTTIImpl>(this, F));
|
|
}
|
|
|
|
MachineFunctionInfo *AVRTargetMachine::createMachineFunctionInfo(
|
|
BumpPtrAllocator &Allocator, const Function &F,
|
|
const TargetSubtargetInfo *STI) const {
|
|
return AVRMachineFunctionInfo::create<AVRMachineFunctionInfo>(Allocator, F,
|
|
STI);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Pass Pipeline Configuration
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool AVRPassConfig::addInstSelector() {
|
|
// Install an instruction selector.
|
|
addPass(createAVRISelDag(getAVRTargetMachine(), getOptLevel()));
|
|
// Create the frame analyzer pass used by the PEI pass.
|
|
addPass(createAVRFrameAnalyzerPass());
|
|
|
|
return false;
|
|
}
|
|
|
|
void AVRPassConfig::addPreSched2() { addPass(createAVRExpandPseudoPass()); }
|
|
|
|
void AVRPassConfig::addPreEmitPass() {
|
|
// Must run branch selection immediately preceding the asm printer.
|
|
addPass(&BranchRelaxationPassID);
|
|
}
|
|
|
|
} // end of namespace llvm
|