From a7c041d1477bdfd753f7155b2cb1fb739eaddb0f Mon Sep 17 00:00:00 2001 From: Nirav Dave Date: Tue, 31 Jan 2017 17:00:27 +0000 Subject: [PATCH] [X86] Implement -mfentry Summary: Insert calls to __fentry__ at function entry. Reviewers: hfinkel, craig.topper Subscribers: mgorny, llvm-commits Differential Revision: https://reviews.llvm.org/D28000 llvm-svn: 293648 --- llvm/include/llvm/CodeGen/Passes.h | 3 ++ llvm/include/llvm/InitializePasses.h | 1 + llvm/include/llvm/Target/Target.td | 9 ++++ llvm/include/llvm/Target/TargetOpcodes.def | 3 ++ llvm/lib/CodeGen/CMakeLists.txt | 1 + llvm/lib/CodeGen/CodeGen.cpp | 1 + llvm/lib/CodeGen/FEntryInserter.cpp | 55 ++++++++++++++++++++++ llvm/lib/CodeGen/TargetPassConfig.cpp | 3 ++ llvm/lib/Target/X86/X86AsmPrinter.h | 2 + llvm/lib/Target/X86/X86MCInstLower.cpp | 16 +++++++ llvm/test/CodeGen/X86/fentry-insertion.ll | 16 +++++++ 11 files changed, 110 insertions(+) create mode 100644 llvm/lib/CodeGen/FEntryInserter.cpp create mode 100644 llvm/test/CodeGen/X86/fentry-insertion.ll diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 2fff94c03f88..ed4bd7fdd665 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -286,6 +286,9 @@ namespace llvm { /// the target platform. extern char &XRayInstrumentationID; + /// This pass inserts FEntry calls + extern char &FEntryInserterID; + /// \brief This pass implements the "patchable-function" attribute. extern char &PatchableFunctionID; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index dd355012cb92..2f31d75787b1 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -131,6 +131,7 @@ void initializeGVNHoistLegacyPassPass(PassRegistry &); void initializeExpandISelPseudosPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeExternalAAWrapperPassPass(PassRegistry&); +void initializeFEntryInserterPass(PassRegistry &); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeFloat2IntLegacyPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index e50969d7001d..bf0bdaedc4f2 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -998,6 +998,15 @@ def PATCHABLE_TAIL_CALL : Instruction { let hasSideEffects = 1; let isReturn = 1; } +def FENTRY_CALL : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = "# FEntry call"; + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} // Generic opcodes used in GlobalISel. include "llvm/Target/GenericOpcodes.td" diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def index cd62a19fdf16..76ed060e8ceb 100644 --- a/llvm/include/llvm/Target/TargetOpcodes.def +++ b/llvm/include/llvm/Target/TargetOpcodes.def @@ -107,6 +107,9 @@ HANDLE_TARGET_OPCODE(LIFETIME_END) /// that must lie within the function and not contain another stackmap. HANDLE_TARGET_OPCODE(STACKMAP) +/// FEntry all - This is a marker instruction which gets translated into a raw fentry call. +HANDLE_TARGET_OPCODE(FENTRY_CALL) + /// Patchable call instruction - this instruction represents a call to a /// constant address, followed by a series of NOPs. It is intended to /// support optimizations for dynamic languages (such as javascript) that diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 43bca0ef5f01..a1e5fd46610e 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -23,6 +23,7 @@ add_llvm_library(LLVMCodeGen ExpandISelPseudos.cpp ExpandPostRAPseudos.cpp FaultMaps.cpp + FEntryInserter.cpp FuncletLayout.cpp GCMetadata.cpp GCMetadataPrinter.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 4cf9b138f10d..9fb796a6d206 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -32,6 +32,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeExpandISelPseudosPass(Registry); initializeExpandPostRAPass(Registry); initializeFinalizeMachineBundlesPass(Registry); + initializeFEntryInserterPass(Registry); initializeFuncletLayoutPass(Registry); initializeGCMachineCodeAnalysisPass(Registry); initializeGCModuleInfoPass(Registry); diff --git a/llvm/lib/CodeGen/FEntryInserter.cpp b/llvm/lib/CodeGen/FEntryInserter.cpp new file mode 100644 index 000000000000..0759bf6713e0 --- /dev/null +++ b/llvm/lib/CodeGen/FEntryInserter.cpp @@ -0,0 +1,55 @@ +//===-- FEntryInsertion.cpp - Patchable prologues for LLVM -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file edits function bodies to insert fentry calls. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +using namespace llvm; + +namespace { +struct FEntryInserter : public MachineFunctionPass { + static char ID; // Pass identification, replacement for typeid + FEntryInserter() : MachineFunctionPass(ID) { + initializeFEntryInserterPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &F) override; +}; +} + +bool FEntryInserter::runOnMachineFunction(MachineFunction &MF) { + const std::string FEntryName = + MF.getFunction()->getFnAttribute("fentry-call").getValueAsString(); + if (FEntryName != "true") + return false; + + auto &FirstMBB = *MF.begin(); + auto &FirstMI = *FirstMBB.begin(); + + auto *TII = MF.getSubtarget().getInstrInfo(); + BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(), + TII->get(TargetOpcode::FENTRY_CALL)); + return true; +} + +char FEntryInserter::ID = 0; +char &llvm::FEntryInserterID = FEntryInserter::ID; +INITIALIZE_PASS(FEntryInserter, "fentry-insert", "Insert fentry calls", false, + false) diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index e7ea2b4563f9..2788287ddc18 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -668,6 +668,9 @@ void TargetPassConfig::addMachinePasses() { addPass(&StackMapLivenessID, false); addPass(&LiveDebugValuesID, false); + // Insert before XRay Instrumentation. + addPass(&FEntryInserterID, false); + addPass(&XRayInstrumentationID, false); addPass(&PatchableFunctionID, false); diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h index 6798253d0f6a..bb15fd7ae8ee 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -92,6 +92,8 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL); void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); + void LowerFENTRY_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); + // Helper function that emits the XRay sleds we've collected for a particular // function. void EmitXRayTable(); diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 8fa431412259..c7cc1a08237c 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -919,6 +919,19 @@ void X86AsmPrinter::LowerFAULTING_LOAD_OP(const MachineInstr &MI, OutStreamer->EmitInstruction(LoadMI, getSubtargetInfo()); } +void X86AsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, + X86MCInstLower &MCIL) { + bool Is64Bits = Subtarget->is64Bit(); + MCContext &Ctx = OutStreamer->getContext(); + MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); + const MCSymbolRefExpr *Op = + MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_None, Ctx); + + EmitAndCountInstruction( + MCInstBuilder(Is64Bits ? X86::CALL64pcrel32 : X86::CALLpcrel32) + .addExpr(Op)); +} + void X86AsmPrinter::LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL) { // PATCHABLE_OP minsize, opcode, operands @@ -1377,6 +1390,9 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { case TargetOpcode::FAULTING_LOAD_OP: return LowerFAULTING_LOAD_OP(*MI, MCInstLowering); + case TargetOpcode::FENTRY_CALL: + return LowerFENTRY_CALL(*MI, MCInstLowering); + case TargetOpcode::PATCHABLE_OP: return LowerPATCHABLE_OP(*MI, MCInstLowering); diff --git a/llvm/test/CodeGen/X86/fentry-insertion.ll b/llvm/test/CodeGen/X86/fentry-insertion.ll new file mode 100644 index 000000000000..a585d96b209c --- /dev/null +++ b/llvm/test/CodeGen/X86/fentry-insertion.ll @@ -0,0 +1,16 @@ +; RUN: llc %s -o - | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @test1() #0 { +entry: + ret void + +; CHECK-LABEL: @test1 +; CHECK: callq __fentry__ +; CHECK-NOT: mcount +; CHECK: retq +} + +attributes #0 = { "fentry-call"="true" } +