From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932411AbaBFBLQ (ORCPT ); Wed, 5 Feb 2014 20:11:16 -0500 Received: from mail-pd0-f170.google.com ([209.85.192.170]:45797 "EHLO mail-pd0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932133AbaBFBLG (ORCPT ); Wed, 5 Feb 2014 20:11:06 -0500 From: Alexei Starovoitov To: Ingo Molnar Cc: "David S. Miller" , Steven Rostedt , Peter Zijlstra , "H. Peter Anvin" , Thomas Gleixner , Masami Hiramatsu , Tom Zanussi , Jovi Zhangwei , Eric Dumazet , Linus Torvalds , Andrew Morton , Frederic Weisbecker , Arnaldo Carvalho de Melo , Pekka Enberg , Arjan van de Ven , Christoph Hellwig , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC PATCH v2 tip 6/7] LLVM BPF backend Date: Wed, 5 Feb 2014 17:10:45 -0800 Message-Id: <1391649046-4383-7-git-send-email-ast@plumgrid.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1391649046-4383-1-git-send-email-ast@plumgrid.com> References: <1391649046-4383-1-git-send-email-ast@plumgrid.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org standalone BPF backend for LLVM 3.2, 3.3 and 3.4 See tools/bpf/llvm/README.txt Written in LLVM codying style and LLVM license. Most of the lib/Target/BPF/* is boilerplate code which is required for any LLVM backend. Backend enforces presence of 'license' section in the source C file. Makefile* is simplified LLVM build system Signed-off-by: Alexei Starovoitov --- tools/bpf/llvm/LICENSE.TXT | 70 ++ tools/bpf/llvm/Makefile.rules | 641 +++++++++++++++++++ tools/bpf/llvm/README.txt | 23 + tools/bpf/llvm/bld/.gitignore | 2 + tools/bpf/llvm/bld/Makefile | 27 + tools/bpf/llvm/bld/Makefile.common | 14 + tools/bpf/llvm/bld/Makefile.config | 124 ++++ .../llvm/bld/include/llvm/Config/AsmParsers.def | 8 + .../llvm/bld/include/llvm/Config/AsmPrinters.def | 9 + .../llvm/bld/include/llvm/Config/Disassemblers.def | 8 + tools/bpf/llvm/bld/include/llvm/Config/Targets.def | 9 + .../bpf/llvm/bld/include/llvm/Support/DataTypes.h | 96 +++ tools/bpf/llvm/bld/lib/Makefile | 11 + .../llvm/bld/lib/Target/BPF/InstPrinter/Makefile | 10 + .../llvm/bld/lib/Target/BPF/MCTargetDesc/Makefile | 11 + tools/bpf/llvm/bld/lib/Target/BPF/Makefile | 17 + .../llvm/bld/lib/Target/BPF/TargetInfo/Makefile | 10 + tools/bpf/llvm/bld/lib/Target/Makefile | 11 + tools/bpf/llvm/bld/tools/Makefile | 12 + tools/bpf/llvm/bld/tools/llc/Makefile | 15 + tools/bpf/llvm/lib/Target/BPF/BPF.h | 30 + tools/bpf/llvm/lib/Target/BPF/BPF.td | 29 + tools/bpf/llvm/lib/Target/BPF/BPFAsmPrinter.cpp | 100 +++ tools/bpf/llvm/lib/Target/BPF/BPFCFGFixup.cpp | 62 ++ tools/bpf/llvm/lib/Target/BPF/BPFCallingConv.td | 24 + tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.cpp | 36 ++ tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.h | 35 + tools/bpf/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp | 182 ++++++ tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.cpp | 676 ++++++++++++++++++++ tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.h | 105 +++ tools/bpf/llvm/lib/Target/BPF/BPFInstrFormats.td | 29 + tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.cpp | 162 +++++ tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.h | 53 ++ tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.td | 455 +++++++++++++ tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.cpp | 77 +++ tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.h | 40 ++ tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.cpp | 122 ++++ tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.h | 65 ++ tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.td | 39 ++ tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.cpp | 23 + tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.h | 33 + tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.cpp | 72 +++ tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.h | 69 ++ .../lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp | 79 +++ .../lib/Target/BPF/InstPrinter/BPFInstPrinter.h | 34 + .../lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 85 +++ .../llvm/lib/Target/BPF/MCTargetDesc/BPFBaseInfo.h | 33 + .../Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp | 119 ++++ .../lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h | 34 + .../Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp | 120 ++++ .../lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.h | 67 ++ .../Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp | 115 ++++ .../lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h | 56 ++ .../lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp | 13 + tools/bpf/llvm/tools/llc/llc.cpp | 381 +++++++++++ 55 files changed, 4782 insertions(+) create mode 100644 tools/bpf/llvm/LICENSE.TXT create mode 100644 tools/bpf/llvm/Makefile.rules create mode 100644 tools/bpf/llvm/README.txt create mode 100644 tools/bpf/llvm/bld/.gitignore create mode 100644 tools/bpf/llvm/bld/Makefile create mode 100644 tools/bpf/llvm/bld/Makefile.common create mode 100644 tools/bpf/llvm/bld/Makefile.config create mode 100644 tools/bpf/llvm/bld/include/llvm/Config/AsmParsers.def create mode 100644 tools/bpf/llvm/bld/include/llvm/Config/AsmPrinters.def create mode 100644 tools/bpf/llvm/bld/include/llvm/Config/Disassemblers.def create mode 100644 tools/bpf/llvm/bld/include/llvm/Config/Targets.def create mode 100644 tools/bpf/llvm/bld/include/llvm/Support/DataTypes.h create mode 100644 tools/bpf/llvm/bld/lib/Makefile create mode 100644 tools/bpf/llvm/bld/lib/Target/BPF/InstPrinter/Makefile create mode 100644 tools/bpf/llvm/bld/lib/Target/BPF/MCTargetDesc/Makefile create mode 100644 tools/bpf/llvm/bld/lib/Target/BPF/Makefile create mode 100644 tools/bpf/llvm/bld/lib/Target/BPF/TargetInfo/Makefile create mode 100644 tools/bpf/llvm/bld/lib/Target/Makefile create mode 100644 tools/bpf/llvm/bld/tools/Makefile create mode 100644 tools/bpf/llvm/bld/tools/llc/Makefile create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPF.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPF.td create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFAsmPrinter.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFCFGFixup.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFCallingConv.td create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFInstrFormats.td create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.td create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.td create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFBaseInfo.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp create mode 100644 tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h create mode 100644 tools/bpf/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp create mode 100644 tools/bpf/llvm/tools/llc/llc.cpp diff --git a/tools/bpf/llvm/LICENSE.TXT b/tools/bpf/llvm/LICENSE.TXT new file mode 100644 index 0000000..00cf601 --- /dev/null +++ b/tools/bpf/llvm/LICENSE.TXT @@ -0,0 +1,70 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf + llvm/projects/sample/autoconf +CellSPU backend llvm/lib/Target/CellSPU/README.txt +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} diff --git a/tools/bpf/llvm/Makefile.rules b/tools/bpf/llvm/Makefile.rules new file mode 100644 index 0000000..9689527 --- /dev/null +++ b/tools/bpf/llvm/Makefile.rules @@ -0,0 +1,641 @@ +#===-- Makefile.rules - Common make rules for LLVM ---------*- Makefile -*--===# +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# This file is included by all of the LLVM makefiles. For details on how to use +# it properly, please see the document MakefileGuide.html in the docs directory. + +# TARGETS: Define standard targets that can be invoked + +# Define the various target sets +RecursiveTargets := all clean clean-all install uninstall +LocalTargets := all-local clean-local clean-all-local check-local \ + install-local uninstall-local +TopLevelTargets := check dist-clean +UserTargets := $(RecursiveTargets) $(LocalTargets) $(TopLevelTargets) +InternalTargets := preconditions + +# INITIALIZATION: Basic things the makefile needs + +# Set the VPATH so that we can find source files. +VPATH=$(PROJ_SRC_DIR) + +# Reset the list of suffixes we know how to build. +.SUFFIXES: +.SUFFIXES: .c .cpp .cc .h .hpp .o .a +.SUFFIXES: $(SHLIBEXT) $(SUFFIXES) + +# Mark all of these targets as phony to avoid implicit rule search +.PHONY: $(UserTargets) $(InternalTargets) + +# Make sure all the user-target rules are double colon rules and +# they are defined first. + +$(UserTargets):: + +# PRECONDITIONS: that which must be built/checked first + +SrcMakefiles := $(filter %Makefile %Makefile.tests,\ + $(wildcard $(PROJ_SRC_DIR)/Makefile*)) +ObjMakefiles := $(subst $(PROJ_SRC_DIR),$(PROJ_OBJ_DIR),$(SrcMakefiles)) +MakefileConfig := $(PROJ_OBJ_ROOT)/Makefile.config +MakefileCommon := $(PROJ_OBJ_ROOT)/Makefile.common +PreConditions := $(ObjMakefiles) +PreConditions += $(MakefileCommon) +PreConditions += $(MakefileConfig) + +preconditions: $(PreConditions) + +# Make sure the BUILT_SOURCES are built first +$(filter-out clean clean-local,$(UserTargets)):: $(BUILT_SOURCES) + +clean-all-local:: +ifneq ($(strip $(BUILT_SOURCES)),) + -$(Verb) $(RM) -f $(BUILT_SOURCES) +endif + +$(BUILT_SOURCES) : $(ObjMakefiles) + +ifndef PROJ_MAKEFILE +PROJ_MAKEFILE := $(PROJ_OBJ_DIR)/Makefile +endif + +# Set up the basic dependencies +$(UserTargets):: $(PreConditions) + +all:: all-local +clean:: clean-local +clean-all:: clean-local clean-all-local +install:: install-local +uninstall:: uninstall-local +install-local:: all-local + +# VARIABLES: Set up various variables based on configuration data + +# Variable for if this make is for a "cleaning" target +ifneq ($(strip $(filter clean clean-local dist-clean,$(MAKECMDGOALS))),) + IS_CLEANING_TARGET=1 +endif + +# Variables derived from configuration we are building + +CPP.Defines := +ifeq ($(ENABLE_OPTIMIZED),1) + BuildMode := Release + OmitFramePointer := -fomit-frame-pointer + + CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + LD.Flags += $(OPTIMIZE_OPTION) + ifdef DEBUG_SYMBOLS + BuildMode := $(BuildMode)+Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +else + ifdef NO_DEBUG_SYMBOLS + BuildMode := Unoptimized + CXX.Flags += + C.Flags += + LD.Flags += + KEEP_SYMBOLS := 1 + else + BuildMode := Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +endif + +ifeq ($(ENABLE_WERROR),1) + CXX.Flags += -Werror + C.Flags += -Werror +endif + +ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) + CXX.Flags += -fvisibility-inlines-hidden +endif + +CXX.Flags += -fno-exceptions + +CXX.Flags += -fno-rtti + +# If DISABLE_ASSERTIONS=1 is specified (make command line or configured), +# then disable assertions by defining the appropriate preprocessor symbols. +ifeq ($(DISABLE_ASSERTIONS),1) + CPP.Defines += -DNDEBUG +else + BuildMode := $(BuildMode)+Asserts + CPP.Defines += -D_DEBUG +endif + +# If ENABLE_EXPENSIVE_CHECKS=1 is specified (make command line or +# configured), then enable expensive checks by defining the +# appropriate preprocessor symbols. +ifeq ($(ENABLE_EXPENSIVE_CHECKS),1) + BuildMode := $(BuildMode)+Checks + CPP.Defines += -DXDEBUG +endif + +DOTDIR_TIMESTAMP_COMMAND := $(DATE) + +CXX.Flags += -Woverloaded-virtual +CPP.BaseFlags += $(CPP.Defines) +AR.Flags := cru + +# Directory locations + +ObjRootDir := $(PROJ_OBJ_DIR)/$(BuildMode) +ObjDir := $(ObjRootDir) +LibDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/lib +ToolDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/bin +ExmplDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/examples +LLVMLibDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/lib +LLVMToolDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/bin +LLVMExmplDir:= $(LLVM_OBJ_ROOT)/$(BuildMode)/examples + +# Locations of shared libraries +SharedPrefix := lib +SharedLibDir := $(LibDir) +LLVMSharedLibDir := $(LLVMLibDir) + +# Full Paths To Compiled Tools and Utilities +EchoCmd := $(ECHO) llvm[$(MAKELEVEL)]: + +Echo := @$(EchoCmd) +LLVMToolDir := $(shell $(LLVM_CONFIG) --bindir) +LLVMLibDir := $(shell $(LLVM_CONFIG) --libdir) +LLVMIncludeDir := $(shell $(LLVM_CONFIG) --includedir) +ifndef LLVM_TBLGEN +LLVM_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT) +endif + +SharedLinkOptions=-shared + +ifdef TOOL_VERBOSE + C.Flags += -v + CXX.Flags += -v + LD.Flags += -v + VERBOSE := 1 +endif + +# Adjust settings for verbose mode +ifndef VERBOSE + Verb := @ + AR.Flags += >/dev/null 2>/dev/null +endif + +# By default, strip symbol information from executable +ifndef KEEP_SYMBOLS + Strip := $(PLATFORMSTRIPOPTS) + StripWarnMsg := "(without symbols)" + Install.StripFlag += -s +endif + +ifdef TOOL_NO_EXPORTS + DynamicFlags := +else + DynamicFlag := $(RDYNAMIC) +endif + +# Adjust linker flags for building an executable +ifdef TOOLNAME + LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' + LD.Flags += $(RPATH) -Wl,$(ToolDir) $(DynamicFlag) +endif + +# Options To Invoke Tools +ifdef EXTRA_LD_OPTIONS +LD.Flags += $(EXTRA_LD_OPTIONS) +endif + +ifndef NO_PEDANTIC +CompileCommonOpts += -pedantic -Wno-long-long +endif +CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ + $(EXTRA_OPTIONS) +# Enable cast-qual for C++; the workaround is to use const_cast. +CXX.Flags += -Wcast-qual + +LD.Flags += -L$(LibDir) -L$(LLVMLibDir) + +CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS +# All -I flags should go here, so that they don't confuse llvm-config. +CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ + $(patsubst %,-I%/include,\ + $(PROJ_OBJ_ROOT) $(PROJ_SRC_ROOT) \ + $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ + -I$(LLVMIncludeDir) $(CPP.BaseFlags) + +Compile.Wrapper := + +Compile.C = $(Compile.Wrapper) \ + $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Compile.CXX = $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Link = $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ + $(LDFLAGS) $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) + +ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 +ScriptInstall = $(INSTALL) -m 0755 +DataInstall = $(INSTALL) -m 0644 + +TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ + -I $(call SYSPATH, $(LLVMIncludeDir)) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target) +LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags) + +Archive = $(AR) $(AR.Flags) +ifdef RANLIB +Ranlib = $(RANLIB) +else +Ranlib = ranlib +endif + +AliasTool = ln -s + +# Get the list of source files and compute object file +# names from them. +ifndef SOURCES + Sources := $(notdir $(wildcard $(PROJ_SRC_DIR)/*.cpp \ + $(PROJ_SRC_DIR)/*.cc $(PROJ_SRC_DIR)/*.c)) +else + Sources := $(SOURCES) +endif + +ifdef BUILT_SOURCES +Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) +endif + +BaseNameSources := $(sort $(basename $(Sources))) + +ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) + +ECHOPATH := $(Verb)$(ECHO) + +# DIRECTORIES: Handle recursive descent of directory structure + +# Provide rules to make install dirs. This must be early +# in the file so they get built before dependencies + +$(DESTDIR)$(PROJ_bindir):: + $(Verb) $(MKDIR) $@ + +# To create other directories, as needed, and timestamp their creation +%/.dir: + $(Verb) $(MKDIR) $* > /dev/null + $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@ + +.PRECIOUS: $(ObjDir)/.dir $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir + +# Handle the DIRS options for sequential construction + +SubDirs := +ifdef DIRS +SubDirs += $(DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +endif + +endif + +# Handle the PARALLEL_DIRS options for parallel construction +ifdef PARALLEL_DIRS + +SubDirs += $(PARALLEL_DIRS) + +# Unfortunately, this list must be maintained if new recursive targets are added +all :: $(addsuffix /.makeall ,$(PARALLEL_DIRS)) +clean :: $(addsuffix /.makeclean ,$(PARALLEL_DIRS)) +clean-all:: $(addsuffix /.makeclean-all,$(PARALLEL_DIRS)) +install :: $(addsuffix /.makeinstall ,$(PARALLEL_DIRS)) +uninstall:: $(addsuffix /.makeuninstall,$(PARALLEL_DIRS)) + +ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T)) + +$(ParallelTargets) : + $(Verb) \ + SD=$(PROJ_SRC_DIR)/$(@D); \ + DD=$(@D); \ + if [ ! -f $$SD/Makefile ]; then \ + SD=$(@D); \ + DD=$(notdir $(@D)); \ + fi; \ + if ([ ! -f $$DD/Makefile ] || \ + command test $$DD/Makefile -ot \ + $$SD/Makefile ); then \ + $(MKDIR) $$DD; \ + $(CP) $$SD/Makefile $$DD/Makefile; \ + fi; \ + $(MAKE) -C $$DD $(subst $(@D)/.make,,$@) +endif + +# Set up variables for building libraries + +# Define various command line options pertaining to the +# libraries needed when linking. There are "Proj" libs +# (defined by the user's project) and "LLVM" libs (defined +# by the LLVM project). + +ifdef USEDLIBS +ProjLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +ProjLibsOptions := $(patsubst %.o, $(LibDir)/%.o, $(ProjLibsOptions)) +ProjUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(USEDLIBS))) +ProjLibsPaths := $(addprefix $(LibDir)/,$(ProjUsedLibs)) +endif + +ifdef LLVMLIBS +LLVMLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsOptions := $(patsubst %.o, $(LLVMLibDir)/%.o, $(LLVMLibsOptions)) +LLVMUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsPaths := $(addprefix $(LLVMLibDir)/,$(LLVMUsedLibs)) +endif + +ifndef IS_CLEANING_TARGET +ifdef LINK_COMPONENTS + +LLVMConfigLibs := $(shell $(LLVM_CONFIG) --libs $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibs),Error) +$(error llvm-config --libs failed) +endif +LLVMLibsOptions += $(LLVMConfigLibs) +LLVMConfigLibfiles := $(shell $(LLVM_CONFIG) --libfiles $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibfiles),Error) +$(error llvm-config --libfiles failed) +endif +LLVMLibsPaths += $(LLVMConfigLibfiles) + +endif +endif + +# Library Build Rules: Four ways to build a library + +# if we're building a library ... +ifdef LIBRARYNAME + +# Make sure there isn't any extraneous whitespace on the LIBRARYNAME option +LIBRARYNAME := $(strip $(LIBRARYNAME)) +BaseLibName.A := lib$(LIBRARYNAME).a +BaseLibName.SO := $(SharedPrefix)$(LIBRARYNAME)$(SHLIBEXT) +LibName.A := $(LibDir)/$(BaseLibName.A) +LibName.SO := $(SharedLibDir)/$(BaseLibName.SO) +LibName.O := $(LibDir)/$(LIBRARYNAME).o + +# Library Targets: +# If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to +# building an archive. +ifndef NO_BUILD_ARCHIVE +ifndef BUILD_ARCHIVE +ifndef LOADABLE_MODULE +BUILD_ARCHIVE = 1 +endif +endif +endif + +# Archive Library Targets: +# If the user wanted a regular archive library built, +# then we provide targets for building them. +ifdef BUILD_ARCHIVE + +all-local:: $(LibName.A) + +$(LibName.A): $(ObjectsO) $(LibDir)/.dir + $(Echo) Building $(BuildMode) Archive Library $(notdir $@) + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-local:: +ifneq ($(strip $(LibName.A)),) + -$(Verb) $(RM) -f $(LibName.A) +endif + +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +endif + +# endif LIBRARYNAME +endif + +# Tool Build Rules: Build executable tool based on TOOLNAME option + +ifdef TOOLNAME + +# Set up variables for building a tool. +TOOLEXENAME := $(strip $(TOOLNAME))$(EXEEXT) +ToolBuildPath := $(ToolDir)/$(TOOLEXENAME) + +# Provide targets for building the tools +all-local:: $(ToolBuildPath) + +clean-local:: +ifneq ($(strip $(ToolBuildPath)),) + -$(Verb) $(RM) -f $(ToolBuildPath) +endif + +$(ToolBuildPath): $(ToolDir)/.dir + +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else + +ToolBinDir = $(DESTDIR)$(PROJ_bindir) +DestTool = $(ToolBinDir)/$(program_prefix)$(TOOLEXENAME) + +install-local:: $(DestTool) + +$(DestTool): $(ToolBuildPath) + $(Echo) Installing $(BuildMode) $(DestTool) + $(Verb) $(MKDIR) $(ToolBinDir) + $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestTool) + -$(Verb) $(RM) -f $(DestTool) + +endif +endif + +# Create .o files in the ObjDir directory from the .cpp and .c files... + +DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ + -MT "$(ObjDir)/$*.o" -MT "$(ObjDir)/$*.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ + else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi + +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +# TABLEGEN: Provide rules for running tblgen to produce *.inc files + +ifdef TARGET +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef TABLEGEN_INC_FILES_COMMON + +INCFiles := $(filter %.inc,$(BUILT_SOURCES)) +INCTMPFiles := $(INCFiles:%=$(ObjDir)/%.tmp) +.PRECIOUS: $(INCTMPFiles) $(INCFiles) + +# INCFiles rule: All of the tblgen generated files are emitted to +# $(ObjDir)/%.inc.tmp, instead of emitting them directly to %.inc. This allows +# us to only "touch" the real file if the contents of it change. IOW, if +# tblgen is modified, all of the .inc.tmp files are regenerated, but no +# dependencies of the .inc files are, unless the contents of the .inc file +# changes. +$(INCFiles) : %.inc : $(ObjDir)/%.inc.tmp + $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ + +endif # TABLEGEN_INC_FILES_COMMON + +ifdef TARGET + +TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ + $(LLVMIncludeDir)/llvm/Target/Target.td \ + $(LLVMIncludeDir)/llvm/Target/TargetCallingConv.td \ + $(LLVMIncludeDir)/llvm/Target/TargetSchedule.td \ + $(LLVMIncludeDir)/llvm/Target/TargetSelectionDAG.td \ + $(LLVMIncludeDir)/llvm/CodeGen/ValueTypes.td) \ + $(wildcard $(LLVMIncludeDir)/llvm/Intrinsics*.td) + +# All .inc.tmp files depend on the .td files. +$(INCTMPFiles) : $(TDFiles) + +$(TARGET:%=$(ObjDir)/%GenRegisterInfo.inc.tmp): \ +$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN) + $(Echo) "Building $( +#else +#include +#endif + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including Support/DataTypes.h" +#endif + +/* Note that includes , if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/tools/bpf/llvm/bld/lib/Makefile b/tools/bpf/llvm/bld/lib/Makefile new file mode 100644 index 0000000..5c7e219 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Makefile @@ -0,0 +1,11 @@ +##===- lib/Makefile ----------------------------------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +LEVEL = .. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS := Target + +include $(LEVEL)/Makefile.common + diff --git a/tools/bpf/llvm/bld/lib/Target/BPF/InstPrinter/Makefile b/tools/bpf/llvm/bld/lib/Target/BPF/InstPrinter/Makefile new file mode 100644 index 0000000..d9a4522 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Target/BPF/InstPrinter/Makefile @@ -0,0 +1,10 @@ +##===- lib/Target/BPF/InstPrinter/Makefile ----------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +LEVEL = ../../../.. +LIBRARYNAME = LLVMBPFAsmPrinter + +# Hack: we need to include 'main' BPF target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/tools/bpf/llvm/bld/lib/Target/BPF/MCTargetDesc/Makefile b/tools/bpf/llvm/bld/lib/Target/BPF/MCTargetDesc/Makefile new file mode 100644 index 0000000..5f2e209 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Target/BPF/MCTargetDesc/Makefile @@ -0,0 +1,11 @@ +##===- lib/Target/BPF/TargetDesc/Makefile ----------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. + +LEVEL = ../../../.. +LIBRARYNAME = LLVMBPFDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/tools/bpf/llvm/bld/lib/Target/BPF/Makefile b/tools/bpf/llvm/bld/lib/Target/BPF/Makefile new file mode 100644 index 0000000..14dea1a3 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Target/BPF/Makefile @@ -0,0 +1,17 @@ +##===- lib/Target/BPF/Makefile ---------------------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. + +LEVEL = ../../.. +LIBRARYNAME = LLVMBPFCodeGen +TARGET = BPF + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = BPFGenRegisterInfo.inc BPFGenInstrInfo.inc \ + BPFGenAsmWriter.inc BPFGenAsmMatcher.inc BPFGenDAGISel.inc \ + BPFGenMCCodeEmitter.inc BPFGenSubtargetInfo.inc BPFGenCallingConv.inc + +DIRS = InstPrinter TargetInfo MCTargetDesc + +include $(LEVEL)/Makefile.common + diff --git a/tools/bpf/llvm/bld/lib/Target/BPF/TargetInfo/Makefile b/tools/bpf/llvm/bld/lib/Target/BPF/TargetInfo/Makefile new file mode 100644 index 0000000..fdf9056 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Target/BPF/TargetInfo/Makefile @@ -0,0 +1,10 @@ +##===- lib/Target/BPF/TargetInfo/Makefile ----------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +LEVEL = ../../../.. +LIBRARYNAME = LLVMBPFInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/tools/bpf/llvm/bld/lib/Target/Makefile b/tools/bpf/llvm/bld/lib/Target/Makefile new file mode 100644 index 0000000..06e5185 --- /dev/null +++ b/tools/bpf/llvm/bld/lib/Target/Makefile @@ -0,0 +1,11 @@ +#===- lib/Target/Makefile ----------------------------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. + +LEVEL = ../.. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS := $(TARGETS_TO_BUILD) + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/bpf/llvm/bld/tools/Makefile b/tools/bpf/llvm/bld/tools/Makefile new file mode 100644 index 0000000..6613681 --- /dev/null +++ b/tools/bpf/llvm/bld/tools/Makefile @@ -0,0 +1,12 @@ +##===- tools/Makefile --------------------------------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. + +LEVEL := .. + +include $(LEVEL)/Makefile.config + +DIRS := +PARALLEL_DIRS := llc + +include $(LEVEL)/Makefile.common diff --git a/tools/bpf/llvm/bld/tools/llc/Makefile b/tools/bpf/llvm/bld/tools/llc/Makefile new file mode 100644 index 0000000..499feb0 --- /dev/null +++ b/tools/bpf/llvm/bld/tools/llc/Makefile @@ -0,0 +1,15 @@ +#===- tools/llc/Makefile -----------------------------------*- Makefile -*-===## +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. + +LEVEL := ../.. +TOOLNAME := llc +ifneq (,$(filter $(shell $(LLVM_CONFIG) --version),3.3 3.4)) +LINK_COMPONENTS := asmparser asmprinter codegen bitreader core mc selectiondag support target irreader +else +LINK_COMPONENTS := asmparser asmprinter codegen bitreader core mc selectiondag support target +endif +USEDLIBS := LLVMBPFCodeGen.a LLVMBPFDesc.a LLVMBPFInfo.a LLVMBPFAsmPrinter.a + +include $(LEVEL)/Makefile.common + diff --git a/tools/bpf/llvm/lib/Target/BPF/BPF.h b/tools/bpf/llvm/lib/Target/BPF/BPF.h new file mode 100644 index 0000000..7412b51 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPF.h @@ -0,0 +1,30 @@ +//===-- BPF.h - Top-level interface for BPF representation ----*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef TARGET_BPF_H +#define TARGET_BPF_H +#include "llvm/Config/config.h" +#undef LLVM_NATIVE_TARGET +#undef LLVM_NATIVE_ASMPRINTER +#undef LLVM_NATIVE_ASMPARSER +#undef LLVM_NATIVE_DISASSEMBLER +#include "MCTargetDesc/BPFBaseInfo.h" +#include "MCTargetDesc/BPFMCTargetDesc.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class FunctionPass; +class TargetMachine; +class BPFTargetMachine; + +/// createBPFISelDag - This pass converts a legalized DAG into a +/// BPF-specific DAG, ready for instruction scheduling. +FunctionPass *createBPFISelDag(BPFTargetMachine &TM); + +FunctionPass *createBPFCFGFixup(BPFTargetMachine &TM); + +extern Target TheBPFTarget; +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPF.td b/tools/bpf/llvm/lib/Target/BPF/BPF.td new file mode 100644 index 0000000..867c7f8 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPF.td @@ -0,0 +1,29 @@ +//===- BPF.td - Describe the BPF Target Machine --------*- tablegen -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Target-independent interfaces which we are implementing +include "llvm/Target/Target.td" + +// BPF Subtarget features. +include "BPFRegisterInfo.td" +include "BPFCallingConv.td" +include "BPFInstrInfo.td" + +def BPFInstrInfo : InstrInfo; + +class Proc Features> + : Processor; + +def : Proc<"generic", []>; + +def BPFInstPrinter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; +} + +// Declare the target which we are implementing +def BPF : Target { + let InstructionSet = BPFInstrInfo; + let AssemblyWriters = [BPFInstPrinter]; +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFAsmPrinter.cpp new file mode 100644 index 0000000..9740d87 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -0,0 +1,100 @@ +//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer --------------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to the BPF assembly language. + +#define DEBUG_TYPE "asm-printer" +#include "BPF.h" +#include "BPFInstrInfo.h" +#include "BPFMCInstLower.h" +#include "BPFTargetMachine.h" +#include "InstPrinter/BPFInstPrinter.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class BPFAsmPrinter : public AsmPrinter { + public: + explicit BPFAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "BPF Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char* Modifier = 0); + void EmitInstruction(const MachineInstr *MI); + private: + void customEmitInstruction(const MachineInstr *MI); + }; +} + +void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << BPFInstPrinter::getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_GlobalAddress: +#if LLVM_VERSION_MINOR==4 + O << *getSymbol(MO.getGlobal()); +#else + O << *Mang->getSymbol(MO.getGlobal()); +#endif + break; + + default: + llvm_unreachable(""); + O << "bug"; + return; + } +} + +void BPFAsmPrinter::customEmitInstruction(const MachineInstr *MI) { + BPFMCInstLower MCInstLowering(OutContext, *Mang, *this); + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + OutStreamer.EmitInstruction(TmpInst); +} + +void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { + + MachineBasicBlock::const_instr_iterator I = MI; + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); + + do { + customEmitInstruction(I++); + } while ((I != E) && I->isInsideBundle()); +} + +// Force static initialization. +extern "C" void LLVMInitializeBPFAsmPrinter() { + RegisterAsmPrinter X(TheBPFTarget); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFCFGFixup.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFCFGFixup.cpp new file mode 100644 index 0000000..18401ba --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFCFGFixup.cpp @@ -0,0 +1,62 @@ +//===-- BPFCFGFixup.cpp - CFG fixup pass -----------------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#define DEBUG_TYPE "bpf_cfg" +#include "BPF.h" +#include "BPFInstrInfo.h" +#include "BPFSubtarget.h" +#include "BPFTargetMachine.h" +#include "BPFSubtarget.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +using namespace llvm; + +namespace { + +class BPFCFGFixup : public MachineFunctionPass { + private: + BPFTargetMachine& QTM; + const BPFSubtarget &QST; + + void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); + + public: + static char ID; + BPFCFGFixup(BPFTargetMachine& TM) : MachineFunctionPass(ID), + QTM(TM), + QST(*TM.getSubtargetImpl()) {} + + const char *getPassName() const { + return "BPF RET insn fixup"; + } + bool runOnMachineFunction(MachineFunction &Fn); +}; + +char BPFCFGFixup::ID = 0; + +bool BPFCFGFixup::runOnMachineFunction(MachineFunction &Fn) { + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + + MachineBasicBlock::iterator MII = MBB->getFirstTerminator(); + if (MII != MBB->end()) { + /* if last insn of this basic block is RET, make this BB last */ + if (MII->getOpcode() == BPF::RET) { + MBBe--; + if (MBB != MBBe) + MBB->moveAfter(MBBe); + break; + } + } + } + return true; +} +} + +FunctionPass *llvm::createBPFCFGFixup(BPFTargetMachine &TM) { + return new BPFCFGFixup(TM); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFCallingConv.td b/tools/bpf/llvm/lib/Target/BPF/BPFCallingConv.td new file mode 100644 index 0000000..27c327e --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFCallingConv.td @@ -0,0 +1,24 @@ +//===- BPFCallingConv.td - Calling Conventions BPF -------*- tablegen -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This describes the calling conventions for the BPF architectures. + +// BPF 64-bit C return-value convention. +def RetCC_BPF64 : CallingConv<[ + CCIfType<[i64], CCAssignToReg<[R0]>> +]>; + +// BPF 64-bit C Calling convention. +def CC_BPF64 : CallingConv<[ + // Promote i8/i16/i32 args to i64 + CCIfType<[i8, i16, i32], CCPromoteToType>, + + // All arguments get passed in integer registers if there is space. + CCIfType<[i64], CCAssignToReg<[R1, R2, R3, R4, R5]>>, + + // Alternatively, they are assigned to the stack in 8-byte aligned units. + CCAssignToStack<8, 8> +]>; + +def CSR: CalleeSavedRegs<(add R6, R7, R8, R9, R10)>; diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.cpp new file mode 100644 index 0000000..b263b5f --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.cpp @@ -0,0 +1,36 @@ +//===-- BPFFrameLowering.cpp - BPF Frame Information --------------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains the BPF implementation of TargetFrameLowering class. + +#include "BPFFrameLowering.h" +#include "BPFInstrInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +bool BPFFrameLowering::hasFP(const MachineFunction &MF) const { + return true; +} + +void BPFFrameLowering::emitPrologue(MachineFunction &MF) const { +} + +void BPFFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { +} + +void BPFFrameLowering:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineRegisterInfo& MRI = MF.getRegInfo(); + + MRI.setPhysRegUnused(BPF::R6); + MRI.setPhysRegUnused(BPF::R7); + MRI.setPhysRegUnused(BPF::R8); + MRI.setPhysRegUnused(BPF::R9); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.h b/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.h new file mode 100644 index 0000000..3e3d9ad --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFFrameLowering.h @@ -0,0 +1,35 @@ +//===-- BPFFrameLowering.h - Define frame lowering for BPF ---*- C++ -*--===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef BPF_FRAMEINFO_H +#define BPF_FRAMEINFO_H + +#include "BPF.h" +#include "BPFSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { +class BPFSubtarget; + +class BPFFrameLowering : public TargetFrameLowering { +public: + explicit BPFFrameLowering(const BPFSubtarget &sti) + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, 0) { + } + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool hasFP(const MachineFunction &MF) const; + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const; + + // llvm 3.3 defines it here + void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + MBB.erase(MI); + } +}; +} +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp new file mode 100644 index 0000000..85f905b --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -0,0 +1,182 @@ +//===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF --------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file defines an instruction selector for the BPF target. + +#define DEBUG_TYPE "bpf-isel" +#include "BPF.h" +#include "BPFRegisterInfo.h" +#include "BPFSubtarget.h" +#include "BPFTargetMachine.h" +#include "llvm/Support/CFG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// Instruction Selector Implementation +namespace { + +class BPFDAGToDAGISel : public SelectionDAGISel { + + /// TM - Keep a reference to BPFTargetMachine. + BPFTargetMachine &TM; + + /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can + /// make the right decision when generating code for different targets. + const BPFSubtarget &Subtarget; + +public: + explicit BPFDAGToDAGISel(BPFTargetMachine &tm) : + SelectionDAGISel(tm), + TM(tm), Subtarget(tm.getSubtarget()) {} + + // Pass Name + virtual const char *getPassName() const { + return "BPF DAG->DAG Pattern Instruction Selection"; + } + +private: + // Include the pieces autogenerated from the target description. + #include "BPFGenDAGISel.inc" + + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const BPFTargetMachine &getTargetMachine() { + return static_cast(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const BPFInstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + + SDNode *Select(SDNode *N); + + // Complex Pattern for address selection. + bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset); + + // getI32Imm - Return a target constant with the specified value, of type i32. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i64); + } +}; + +} + +/// ComplexPattern used on BPFInstrInfo +/// Used on BPF Load/Store instructions +bool BPFDAGToDAGISel:: +SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { + // if Address is FI, get the TargetFrameIndex. + if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + Offset = CurDAG->getTargetConstant(0, MVT::i64); + return true; + } + + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; + + // Addresses of the form FI+const or FI|const + if (CurDAG->isBaseWithConstantOffset(Addr)) { + ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)); + if (isInt<32>(CN->getSExtValue())) { + + // If the first operand is a FI, get the TargetFI Node + if (FrameIndexSDNode *FIN = dyn_cast + (Addr.getOperand(0))) + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + else + Base = Addr.getOperand(0); + + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i64); + return true; + } + } + + // Operand is a result from an ADD. + if (Addr.getOpcode() == ISD::ADD) { + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { + if (isInt<32>(CN->getSExtValue())) { + + // If the first operand is a FI, get the TargetFI Node + if (FrameIndexSDNode *FIN = dyn_cast + (Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + } else { + Base = Addr.getOperand(0); + } + + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i64); + return true; + } + } + } + + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i64); + return true; +} + +/// Select instructions not customized! Used for +/// expanded, promoted and normal instructions +SDNode* BPFDAGToDAGISel::Select(SDNode *Node) { + unsigned Opcode = Node->getOpcode(); + + // Dump information about the Node being selected + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); + + // If we have a custom node, we already have selected! + if (Node->isMachineOpcode()) { + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); + return NULL; + } + + // tablegen selection should be handled here. + switch(Opcode) { + default: break; + + case ISD::FrameIndex: { + int FI = dyn_cast(Node)->getIndex(); + EVT VT = Node->getValueType(0); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); + unsigned Opc = BPF::MOV_rr; + if (Node->hasOneUse()) + return CurDAG->SelectNodeTo(Node, Opc, VT, TFI); +#if LLVM_VERSION_MINOR==4 + return CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI); +#else + return CurDAG->getMachineNode(Opc, Node->getDebugLoc(), VT, TFI); +#endif + + } + } + + // Select the default instruction + SDNode *ResNode = SelectCode(Node); + + DEBUG(errs() << "=> "); + if (ResNode == NULL || ResNode == Node) + DEBUG(Node->dump(CurDAG)); + else + DEBUG(ResNode->dump(CurDAG)); + DEBUG(errs() << "\n"); + return ResNode; +} + +/// createBPFISelDag - This pass converts a legalized DAG into a +/// BPF-specific DAG, ready for instruction scheduling. +FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) { + return new BPFDAGToDAGISel(TM); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.cpp new file mode 100644 index 0000000..b065d31 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.cpp @@ -0,0 +1,676 @@ +//===-- BPFISelLowering.cpp - BPF DAG Lowering Implementation ----------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file implements the BPFTargetLowering class. + +#define DEBUG_TYPE "bpf-lower" + +#include "BPFISelLowering.h" +#include "BPF.h" +#include "BPFTargetMachine.h" +#include "BPFSubtarget.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +BPFTargetLowering::BPFTargetLowering(BPFTargetMachine &tm) : + TargetLowering(tm, new TargetLoweringObjectFileELF()), + Subtarget(*tm.getSubtargetImpl()), TM(tm) { + + // Set up the register classes. + addRegisterClass(MVT::i64, &BPF::GPRRegClass); + + // Compute derived properties from the register classes + computeRegisterProperties(); + + setStackPointerRegisterToSaveRestore(BPF::R11); + + setOperationAction(ISD::BR_CC, MVT::i64, Custom); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::SETCC, MVT::i64, Expand); + setOperationAction(ISD::SELECT, MVT::i64, Expand); + setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); + +// setCondCodeAction(ISD::SETLT, MVT::i64, Expand); + + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); + /*setOperationAction(ISD::BlockAddress, MVT::i64, Custom); + setOperationAction(ISD::JumpTable, MVT::i64, Custom); + setOperationAction(ISD::ConstantPool, MVT::i64, Custom);*/ + + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + +/* setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand);*/ + +// setOperationAction(ISD::SDIV, MVT::i64, Expand); +// setOperationAction(ISD::UDIV, MVT::i64, Expand); + + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); + +// setOperationAction(ISD::MUL, MVT::i64, Expand); + + setOperationAction(ISD::MULHU, MVT::i64, Expand); + setOperationAction(ISD::MULHS, MVT::i64, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + + setOperationAction(ISD::ADDC, MVT::i64, Expand); + setOperationAction(ISD::ADDE, MVT::i64, Expand); + setOperationAction(ISD::SUBC, MVT::i64, Expand); + setOperationAction(ISD::SUBE, MVT::i64, Expand); + + setOperationAction(ISD::ROTR, MVT::i64, Expand); + setOperationAction(ISD::ROTL, MVT::i64, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); + + setOperationAction(ISD::BSWAP, MVT::i64, Expand); + setOperationAction(ISD::CTTZ, MVT::i64, Custom); + setOperationAction(ISD::CTLZ, MVT::i64, Custom); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Custom); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Custom); + setOperationAction(ISD::CTPOP, MVT::i64, Expand); + + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand); + + // Extended load operations for i1 types must be promoted + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Expand); + + // Function alignments (log2) + setMinFunctionAlignment(3); + setPrefFunctionAlignment(3); + +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + MaxStoresPerMemcpy = 128; + MaxStoresPerMemcpyOptSize = 128; + MaxStoresPerMemset = 128; +#else + maxStoresPerMemcpy = 128; + maxStoresPerMemcpyOptSize = 128; + maxStoresPerMemset = 128; +#endif +} + +SDValue BPFTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + case ISD::BR_CC: return LowerBR_CC(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + default: + llvm_unreachable("unimplemented operand"); + } +} + +// Calling Convention Implementation +#include "BPFGenCallingConv.inc" + +SDValue +BPFTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl + &Ins, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG, + SmallVectorImpl &InVals) + const { + switch (CallConv) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::Fast: + break; + } + +/// LowerCCCArguments - transform physical registers into virtual registers and +/// generate load operations for arguments places on the stack. + MachineFunction &MF = DAG.getMachineFunction(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, CC_BPF64); + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + if (VA.isRegLoc()) { + // Arguments passed in registers + EVT RegVT = VA.getLocVT(); + switch (RegVT.getSimpleVT().SimpleTy) { + default: + { +#ifndef NDEBUG + errs() << "LowerFormalArguments Unhandled argument type: " + << RegVT.getSimpleVT().SimpleTy << "\n"; +#endif + llvm_unreachable(0); + } + case MVT::i64: + unsigned VReg = RegInfo.createVirtualRegister(&BPF::GPRRegClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); + + // If this is an 8/16/32-bit value, it is really passed promoted to 64 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + + InVals.push_back(ArgValue); + } + } else { + assert(VA.isMemLoc()); + errs() << "Function: " << MF.getName() << " "; + MF.getFunction()->getFunctionType()->dump(); + errs() << "\n"; + report_fatal_error("too many function args"); + } + } + + if (isVarArg || MF.getFunction()->hasStructRetAttr()) { + errs() << "Function: " << MF.getName() << " "; + MF.getFunction()->getFunctionType()->dump(); + errs() << "\n"; + report_fatal_error("functions with VarArgs or StructRet are not supported"); + } + + return Chain; +} + +SDValue +BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const { + SelectionDAG &DAG = CLI.DAG; + SmallVector &Outs = CLI.Outs; + SmallVector &OutVals = CLI.OutVals; + SmallVector &Ins = CLI.Ins; + SDValue Chain = CLI.Chain; + SDValue Callee = CLI.Callee; + bool &isTailCall = CLI.IsTailCall; + CallingConv::ID CallConv = CLI.CallConv; + bool isVarArg = CLI.IsVarArg; + + // BPF target does not support tail call optimization. + isTailCall = false; + + switch (CallConv) { + default: + report_fatal_error("Unsupported calling convention"); + case CallingConv::Fast: + case CallingConv::C: + break; + } + +/// LowerCCCCallTo - functions arguments are copied from virtual regs to +/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallOperands(Outs, CC_BPF64); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + // Create local copies for byval args. + SmallVector ByValArgs; + + if (Outs.size() >= 6) { + errs() << "too many arguments to a function "; + Callee.dump(); + report_fatal_error("too many args\n"); + } + + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + ISD::ArgFlagsTy Flags = Outs[i].Flags; + if (!Flags.isByVal()) + continue; + + Callee.dump(); + report_fatal_error("cannot pass by value"); + } + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes, + getPointerTy(), true) +#if LLVM_VERSION_MINOR==4 + , CLI.DL +#endif + ); + + SmallVector, 4> RegsToPass; + SDValue StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = OutVals[i]; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, CLI.DL, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, CLI.DL, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, CLI.DL, VA.getLocVT(), Arg); + break; + } + + // Use local copy if it is a byval arg. + if (Flags.isByVal()) + Arg = ByValArgs[j++]; + + // Arguments that can be passed on register must be kept at RegsToPass + // vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + llvm_unreachable("call arg pass bug"); + } + } + + SDValue InFlag; + + // Build a sequence of copy-to-reg nodes chained together with token chain and + // flag operands which copy the outgoing args into registers. The InFlag in + // necessary since all emitted instructions must be stuck together. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress node (quite common, every direct call is) + // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. + // Likewise ExternalSymbol -> TargetExternalSymbol. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, getPointerTy(), G->getOffset()/*0*/, + 0); + } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), + 0); + } + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(BPFISD::CALL, CLI.DL, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getConstant(NumBytes, getPointerTy(), true), + DAG.getConstant(0, getPointerTy(), true), + InFlag +#if LLVM_VERSION_MINOR==4 + , CLI.DL +#endif + ); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, CLI.DL, + DAG, InVals); +} + +SDValue +BPFTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG) const { + + // CCValAssign - represent the assignment of the return value to a location + SmallVector RVLocs; + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + + // Analize return values. + CCInfo.AnalyzeReturn(Outs, RetCC_BPF64); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. +#if LLVM_VERSION_MINOR==2 + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } +#endif + + SDValue Flag; +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + SmallVector RetOps(1, Chain); +#endif + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + OutVals[i], Flag); + + // Guarantee that all emitted copies are stuck together, + // avoiding something bad. + Flag = Chain.getValue(1); +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); +#endif + } + + if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) { + errs() << "Function: " << DAG.getMachineFunction().getName() << " "; + DAG.getMachineFunction().getFunction()->getFunctionType()->dump(); + errs() << "\n"; + report_fatal_error("BPF doesn't support struct return"); + } + + unsigned Opc = BPFISD::RET_FLAG; +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + RetOps[0] = Chain; // Update chain. + + // Add the flag if we have it. + if (Flag.getNode()) + RetOps.push_back(Flag); + + return DAG.getNode(Opc, dl, MVT::Other, &RetOps[0], RetOps.size()); +#else + if (Flag.getNode()) + return DAG.getNode(Opc, dl, MVT::Other, Chain, Flag); + + // Return Void + return DAG.getNode(Opc, dl, MVT::Other, Chain); +#endif +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +SDValue +BPFTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallResult(Ins, RetCC_BPF64); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), + RVLocs[i].getValVT(), InFlag).getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } + + return Chain; +} + +static bool NegateCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) +{ + switch (CC) { + default: + return false; + case ISD::SETULT: + CC = ISD::SETUGT; + std::swap(LHS, RHS); + return true; + case ISD::SETULE: + CC = ISD::SETUGE; + std::swap(LHS, RHS); + return true; + case ISD::SETLT: + CC = ISD::SETGT; + std::swap(LHS, RHS); + return true; + case ISD::SETLE: + CC = ISD::SETGE; + std::swap(LHS, RHS); + return true; + } +} + +SDValue BPFTargetLowering::LowerBR_CC(SDValue Op, + SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue Dest = Op.getOperand(4); +#if LLVM_VERSION_MINOR==4 + SDLoc dl(Op); +#else + DebugLoc dl = Op.getDebugLoc(); +#endif + + NegateCC(LHS, RHS, CC); + + return DAG.getNode(BPFISD::BR_CC, dl, Op.getValueType(), + Chain, LHS, RHS, DAG.getConstant(CC, MVT::i64), Dest); +} + +SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, + SelectionDAG &DAG) const { + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue TrueV = Op.getOperand(2); + SDValue FalseV = Op.getOperand(3); + ISD::CondCode CC = cast(Op.getOperand(4))->get(); +#if LLVM_VERSION_MINOR==4 + SDLoc dl(Op); +#else + DebugLoc dl = Op.getDebugLoc(); +#endif + + NegateCC(LHS, RHS, CC); + + SDValue TargetCC = DAG.getConstant(CC, MVT::i64); + + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + Ops.push_back(TargetCC); + Ops.push_back(TrueV); + Ops.push_back(FalseV); + + SDValue sel = DAG.getNode(BPFISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); + DEBUG(errs() << "LowerSELECT_CC:\n"; sel.dumpr(); errs() << "\n"); + return sel; +} + +const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return NULL; + case BPFISD::ADJDYNALLOC: return "BPFISD::ADJDYNALLOC"; + case BPFISD::RET_FLAG: return "BPFISD::RET_FLAG"; + case BPFISD::CALL: return "BPFISD::CALL"; + case BPFISD::SELECT_CC: return "BPFISD::SELECT_CC"; + case BPFISD::BR_CC: return "BPFISD::BR_CC"; + case BPFISD::Wrapper: return "BPFISD::Wrapper"; + } +} + +SDValue BPFTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + Op.dump(); + report_fatal_error("LowerGlobalAddress: BPF cannot access global variables"); + return SDValue(); +} + +MachineBasicBlock* +BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const { + unsigned Opc = MI->getOpcode(); + + const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + assert(Opc == BPF::Select && "Unexpected instr type to insert"); + + // To "insert" a SELECT instruction, we actually have to insert the diamond + // control-flow pattern. The incoming instruction knows the destination vreg + // to set, the condition code register to branch on, the true/false values to + // select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator I = BB; + ++I; + + // thisMBB: + // ... + // TrueVal = ... + // jmp_XX r1, r2 goto copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); + + F->insert(I, copy0MBB); + F->insert(I, copy1MBB); + // Update machine-CFG edges by transferring all successors of the current + // block to the new block which will contain the Phi node for the select. + copy1MBB->splice(copy1MBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + copy1MBB->transferSuccessorsAndUpdatePHIs(BB); + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(copy1MBB); + + // Insert Branch if Flag + unsigned LHS = MI->getOperand(1).getReg(); + unsigned RHS = MI->getOperand(2).getReg(); + int CC = MI->getOperand(3).getImm(); + switch (CC) { + case ISD::SETGT: + BuildMI(BB, dl, TII.get(BPF::JSGT_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + case ISD::SETUGT: + BuildMI(BB, dl, TII.get(BPF::JUGT_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + case ISD::SETGE: + BuildMI(BB, dl, TII.get(BPF::JSGE_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + case ISD::SETUGE: + BuildMI(BB, dl, TII.get(BPF::JUGE_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + case ISD::SETEQ: + BuildMI(BB, dl, TII.get(BPF::JEQ_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + case ISD::SETNE: + BuildMI(BB, dl, TII.get(BPF::JNE_rr)) + .addReg(LHS).addReg(RHS).addMBB(copy1MBB); + break; + default: + report_fatal_error("unimplemented select CondCode " + Twine(CC)); + } + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to copy1MBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(copy1MBB); + + // copy1MBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = copy1MBB; + BuildMI(*BB, BB->begin(), dl, TII.get(BPF::PHI), + MI->getOperand(0).getReg()) + .addReg(MI->getOperand(5).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(4).getReg()).addMBB(thisMBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + return BB; +} + diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.h b/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.h new file mode 100644 index 0000000..0850a9e --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFISelLowering.h @@ -0,0 +1,105 @@ +//===-- BPFISelLowering.h - BPF DAG Lowering Interface -......-*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file defines the interfaces that BPF uses to lower LLVM code into a +// selection DAG. + +#ifndef LLVM_TARGET_BPF_ISELLOWERING_H +#define LLVM_TARGET_BPF_ISELLOWERING_H + +#include "BPF.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + namespace BPFISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + ADJDYNALLOC, + + /// Return with a flag operand. Operand 0 is the chain operand. + RET_FLAG, + + /// CALL - These operations represent an abstract call instruction, which + /// includes a bunch of information. + CALL, + + /// SELECT_CC - Operand 0 and operand 1 are selection variable, operand 3 + /// is condition code and operand 4 is flag operand. + SELECT_CC, + + // BR_CC - Used to glue together a l.bf to a l.sfXX + BR_CC, + + /// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol, + /// and TargetGlobalAddress. + Wrapper + }; + } + + class BPFSubtarget; + class BPFTargetMachine; + + class BPFTargetLowering : public TargetLowering { + public: + explicit BPFTargetLowering(BPFTargetMachine &TM); + + /// LowerOperation - Provide custom lowering hooks for some operations. + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + /// getTargetNodeName - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + + MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const; + + private: + const BPFSubtarget &Subtarget; + const BPFTargetMachine &TM; + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const; + + SDValue LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + SDValue LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, +#if LLVM_VERSION_MINOR==4 + SDLoc dl, +#else + DebugLoc dl, +#endif + SelectionDAG &DAG) const; + }; +} + +#endif // LLVM_TARGET_BPF_ISELLOWERING_H diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFInstrFormats.td b/tools/bpf/llvm/lib/Target/BPF/BPFInstrFormats.td new file mode 100644 index 0000000..122ff19 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFInstrFormats.td @@ -0,0 +1,29 @@ +//===- BPFInstrFormats.td - BPF Instruction Formats ----*- tablegen -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +class InstBPF pattern> + : Instruction { + field bits<64> Inst; + field bits<64> SoftFail = 0; + let Size = 8; + + let Namespace = "BPF"; + let DecoderNamespace = "BPF"; + + bits<3> bpfClass; + let Inst{58-56} = bpfClass; + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; +} + +// Pseudo instructions +class Pseudo pattern> + : InstBPF { + let Inst{63-0} = 0; + let isPseudo = 1; +} + diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.cpp new file mode 100644 index 0000000..943de85 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.cpp @@ -0,0 +1,162 @@ +//===-- BPFInstrInfo.cpp - BPF Instruction Information --------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains the BPF implementation of the TargetInstrInfo class. + +#include "BPF.h" +#include "BPFInstrInfo.h" +#include "BPFSubtarget.h" +#include "BPFTargetMachine.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +#define GET_INSTRINFO_CTOR_DTOR /* for 3.4 */ +#define GET_INSTRINFO_CTOR /* for 3.2, 3.3 */ +#include "BPFGenInstrInfo.inc" + +using namespace llvm; + +BPFInstrInfo::BPFInstrInfo() + : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP), + RI(*this) { +} + +void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + if (BPF::GPRRegClass.contains(DestReg, SrcReg)) + BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + else + llvm_unreachable("Impossible reg-to-reg copy"); +} + +void BPFInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (RC == &BPF::GPRRegClass) + BuildMI(MBB, I, DL, get(BPF::STD)).addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0); + else + llvm_unreachable("Can't store this register to stack slot"); +} + +void BPFInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (RC == &BPF::GPRRegClass) + BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); + else + llvm_unreachable("Can't load this register from stack slot"); +} + +bool BPFInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // Start from the bottom of the block and work up, examining the + // terminator instructions. + MachineBasicBlock::iterator I = MBB.end(); + while (I != MBB.begin()) { + --I; + if (I->isDebugValue()) + continue; + + // Working from the bottom, when we see a non-terminator + // instruction, we're done. + if (!isUnpredicatedTerminator(I)) + break; + + // A terminator that isn't a branch can't easily be handled + // by this analysis. + if (!I->isBranch()) + return true; + + // Handle unconditional branches. + if (I->getOpcode() == BPF::JMP) { + if (!AllowModify) { + TBB = I->getOperand(0).getMBB(); + continue; + } + + // If the block has any instructions after a J, delete them. + while (llvm::next(I) != MBB.end()) + llvm::next(I)->eraseFromParent(); + Cond.clear(); + FBB = 0; + + // Delete the J if it's equivalent to a fall-through. + if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { + TBB = 0; + I->eraseFromParent(); + I = MBB.end(); + continue; + } + + // TBB is used to indicate the unconditinal destination. + TBB = I->getOperand(0).getMBB(); + continue; + } + // Cannot handle conditional branches + return true; + } + + return false; +} + +unsigned +BPFInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const { + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + + if (Cond.empty()) { + // Unconditional branch + assert(!FBB && "Unconditional branch with multiple successors!"); + BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); + return 1; + } + + llvm_unreachable("Unexpected conditional branch"); + return 0; +} + +unsigned BPFInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + unsigned Count = 0; + + while (I != MBB.begin()) { + --I; + if (I->isDebugValue()) + continue; + if (I->getOpcode() != BPF::JMP) + break; + // Remove the branch. + I->eraseFromParent(); + I = MBB.end(); + ++Count; + } + + return Count; +} + diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.h b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.h new file mode 100644 index 0000000..911387d --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.h @@ -0,0 +1,53 @@ +//===- BPFInstrInfo.h - BPF Instruction Information ---------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef BPFINSTRUCTIONINFO_H +#define BPFINSTRUCTIONINFO_H + +#include "BPFRegisterInfo.h" +#include "BPFSubtarget.h" +#include "llvm/Target/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "BPFGenInstrInfo.inc" + +namespace llvm { + +class BPFInstrInfo : public BPFGenInstrInfo { + const BPFRegisterInfo RI; +public: + BPFInstrInfo(); + + virtual const BPFRegisterInfo &getRegisterInfo() const { return RI; } + + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + bool AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const; + + unsigned RemoveBranch(MachineBasicBlock &MBB) const; + unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const; +}; +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.td b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.td new file mode 100644 index 0000000..ca95d9c --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -0,0 +1,455 @@ +//===-- BPFInstrInfo.td - Target Description for BPF Target -------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file describes the BPF instructions in TableGen format. + +include "BPFInstrFormats.td" + +// Instruction Operands and Patterns + +// These are target-independent nodes, but have target-specific formats. +def SDT_BPFCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, iPTR> ]>; +def SDT_BPFCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, iPTR>, + SDTCisVT<1, iPTR> ]>; +def SDT_BPFCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; +def SDT_BPFSetFlag : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>; +def SDT_BPFSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, SDTCisSameAs<0, 4>, + SDTCisSameAs<4, 5>]>; +def SDT_BPFBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, SDTCisVT<3, OtherVT>]>; + +def SDT_BPFWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisPtrTy<0>]>; +//def SDT_BPFAdjDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, +// SDTCisVT<1, i64>]>; + +def call : SDNode<"BPFISD::CALL", SDT_BPFCall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; +def retflag : SDNode<"BPFISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_BPFCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_BPFCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +def BPFbrcc : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC, + [SDNPHasChain, SDNPOutGlue, SDNPInGlue]>; + +def BPFselectcc : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>; +def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>; + +//def BPFadjdynalloc : SDNode<"BPFISD::ADJDYNALLOC", SDT_BPFAdjDynAlloc>; + +// helper macros to produce 64-bit constant +// 0x11223344 55667788 -> +// reg = 0x11223344 +// reg <<= 32 +// reg += 0x55667788 +// +// 0x11223344 FF667788 -> +// reg = 0x11223345 +// reg <<= 32 +// reg += (long long)(int)0xFF667788 +def LO32 : SDNodeXFormgetTargetConstant((int64_t)(int32_t)(uint64_t)N->getZExtValue(), + MVT::i64); +}]>; +def HI32 : SDNodeXFormgetTargetConstant(((int64_t)N->getZExtValue() - + (int64_t)(int32_t)(uint64_t)N->getZExtValue()) >> 32, MVT::i64); +}]>; + + +def brtarget : Operand; +def calltarget : Operand; + +def s32imm : Operand { + let PrintMethod = "printS32ImmOperand"; +} + +def immSExt32 : PatLeaf<(imm), + [{return isInt<32>(N->getSExtValue()); }]>; + +// Addressing modes. +def ADDRri : ComplexPattern; + +// Address operands +def MEMri : Operand { + let PrintMethod = "printMemOperand"; + let EncoderMethod = "getMemoryOpValue"; + let DecoderMethod = "todo_decode_memri"; + let MIOperandInfo = (ops GPR, i16imm); +} + +// Conditional code predicates - used for pattern matching for SF instructions +def BPF_CC_EQ : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETEQ);}]>; +def BPF_CC_NE : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETNE);}]>; +def BPF_CC_GE : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETGE);}]>; +def BPF_CC_GT : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETGT);}]>; +def BPF_CC_GTU : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETUGT);}]>; +def BPF_CC_GEU : PatLeaf<(imm), + [{return (N->getZExtValue() == ISD::SETUGE);}]>; + +// jump instructions +class JMP_RR br_op, string asmstr, PatLeaf Cond> + : InstBPF<(outs), (ins GPR:$rA, GPR:$rX, brtarget:$dst), + !strconcat(asmstr, "\t$rA, $rX goto $dst"), + [(BPFbrcc (i64 GPR:$rA), (i64 GPR:$rX), Cond, bb:$dst)]> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<4> rX; + bits<16> dst; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{55-52} = rX; + let Inst{51-48} = rA; + let Inst{47-32} = dst; + + let op = br_op; + let src = 1; + let bpfClass = 5; // BPF_JUMP +} + +class JMP_RI br_op, string asmstr, PatLeaf Cond> + : InstBPF<(outs), (ins GPR:$rA, s32imm:$imm, brtarget:$dst), + !strconcat(asmstr, "i\t$rA, $imm goto $dst"), + [(BPFbrcc (i64 GPR:$rA), immSExt32:$imm, Cond, bb:$dst)]> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<16> dst; + bits<32> imm; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{51-48} = rA; + let Inst{47-32} = dst; + let Inst{31-0} = imm; + + let op = br_op; + let src = 0; + let bpfClass = 5; // BPF_JUMP +} + +multiclass J op2Val, string asmstr, PatLeaf Cond> { + def _rr : JMP_RR; + def _ri : JMP_RI; +} + +let isBranch = 1, isTerminator = 1, hasDelaySlot=0 in { +// cmp+goto instructions +defm JEQ : J<0x1, "jeq", BPF_CC_EQ>; +defm JUGT : J<0x2, "jgt", BPF_CC_GTU>; +defm JUGE : J<0x3, "jge", BPF_CC_GEU>; +defm JNE : J<0x5, "jne", BPF_CC_NE>; +defm JSGT : J<0x6, "jsgt", BPF_CC_GT>; +defm JSGE : J<0x7, "jsge", BPF_CC_GE>; +} + +// ALU instructions +class ALU_RI aluOp, string asmstr, SDNode OpNode> + : InstBPF<(outs GPR:$rA), (ins GPR:$rS, s32imm:$imm), + !strconcat(asmstr, "i\t$rA, $imm"), + [(set GPR:$rA, (OpNode GPR:$rS, immSExt32:$imm))]> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<32> imm; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{51-48} = rA; + let Inst{31-0} = imm; + + let op = aluOp; + let src = 0; + let bpfClass = 4; +} + +class ALU_RR aluOp, string asmstr, SDNode OpNode> + : InstBPF<(outs GPR:$rA), (ins GPR:$rS, GPR:$rX), + !strconcat(asmstr, "\t$rA, $rX"), + [(set GPR:$rA, (OpNode (i64 GPR:$rS), (i64 GPR:$rX)))]> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<4> rX; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{55-52} = rX; + let Inst{51-48} = rA; + + let op = aluOp; + let src = 1; + let bpfClass = 4; +} + +multiclass ALU opVal, string asmstr, SDNode OpNode> { + def _rr : ALU_RR; + def _ri : ALU_RI; +} + +let Constraints = "$rA = $rS" in { +let isAsCheapAsAMove = 1 in { + defm ADD : ALU<0x0, "add", add>; + defm SUB : ALU<0x1, "sub", sub>; + defm OR : ALU<0x4, "or", or>; + defm AND : ALU<0x5, "and", and>; + defm SLL : ALU<0x6, "sll", shl>; + defm SRL : ALU<0x7, "srl", srl>; + defm XOR : ALU<0xa, "xor", xor>; + defm SRA : ALU<0xc, "sra", sra>; +} + defm MUL : ALU<0x2, "mul", mul>; + defm DIV : ALU<0x3, "div", udiv>; +} + +class MOV_RR + : InstBPF<(outs GPR:$rA), (ins GPR:$rX), + !strconcat(asmstr, "\t$rA, $rX"), + []> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<4> rX; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{55-52} = rX; + let Inst{51-48} = rA; + + let op = 0xb; + let src = 1; + let bpfClass = 4; +} + +class MOV_RI + : InstBPF<(outs GPR:$rA), (ins s32imm:$imm), + !strconcat(asmstr, "\t$rA, $imm"), + [(set GPR:$rA, (i64 immSExt32:$imm))]> { + bits<4> op; + bits<1> src; + bits<4> rA; + bits<32> imm; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{51-48} = rA; + let Inst{31-0} = imm; + + let op = 0xb; + let src = 0; + let bpfClass = 4; +} +def MOV_rr : MOV_RR<"mov">; +def MOV_ri : MOV_RI<"mov">; + +// STORE instructions +class STORE sizeOp, string asmstring, list pattern> + : InstBPF<(outs), (ins GPR:$rX, MEMri:$addr), + !strconcat(asmstring, "\t$addr, $rX"), pattern> { + bits<3> mode; + bits<2> size; + bits<4> rX; + bits<20> addr; + + let Inst{63-61} = mode; + let Inst{60-59} = size; + let Inst{51-48} = addr{19-16}; // base reg + let Inst{55-52} = rX; + let Inst{47-32} = addr{15-0}; // offset + + let mode = 6; // BPF_REL + let size = sizeOp; + let bpfClass = 3; // BPF_STX +} + +class STOREi64 subOp, string asmstring, PatFrag opNode> + : STORE; + +def STW : STOREi64<0x0, "stw", truncstorei32>; +def STH : STOREi64<0x1, "sth", truncstorei16>; +def STB : STOREi64<0x2, "stb", truncstorei8>; +def STD : STOREi64<0x3, "std", store>; + +// LOAD instructions +class LOAD sizeOp, string asmstring, list pattern> + : InstBPF<(outs GPR:$rA), (ins MEMri:$addr), + !strconcat(asmstring, "\t$rA, $addr"), pattern> { + bits<3> mode; + bits<2> size; + bits<4> rA; + bits<20> addr; + + let Inst{63-61} = mode; + let Inst{60-59} = size; + let Inst{51-48} = rA; + let Inst{55-52} = addr{19-16}; + let Inst{47-32} = addr{15-0}; + + let mode = 6; // BPF_REL + let size = sizeOp; + let bpfClass = 1; // BPF_LDX +} + +class LOADi64 sizeOp, string asmstring, PatFrag opNode> + : LOAD; + +def LDW : LOADi64<0x0, "ldw", zextloadi32>; +def LDH : LOADi64<0x1, "ldh", zextloadi16>; +def LDB : LOADi64<0x2, "ldb", zextloadi8>; +def LDD : LOADi64<0x3, "ldd", load>; + +//def LDBS : LOADi64<0x2, "ldbs", sextloadi8>; +//def LDHS : LOADi64<0x1, "ldhs", sextloadi16>; +//def LDWS : LOADi64<0x0, "ldws", sextloadi32>; + +class BRANCH subOp, string asmstring, list pattern> + : InstBPF<(outs), (ins brtarget:$dst), + !strconcat(asmstring, "\t$dst"), pattern> { + bits<4> op; + bits<16> dst; + bits<1> src; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{47-32} = dst; + + let op = subOp; + let src = 1; + let bpfClass = 5; // BPF_JUMP +} + +class CALL + : InstBPF<(outs), (ins calltarget:$dst), + !strconcat(asmstring, "\t$dst"), []> { + bits<4> op; + bits<32> dst; + bits<1> src; + + let Inst{63-60} = op; + let Inst{59} = src; + let Inst{31-0} = dst; + + let op = 8; // BPF_CALL + let src = 0; + let bpfClass = 5; // BPF_JUMP +} + +// Jump always +let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in { + def JMP : BRANCH<0x0, "jmp", [(br bb:$dst)]>; +} + +// Jump and link +let isCall=1, hasDelaySlot=0, + Uses = [R11], + // Potentially clobbered registers + Defs = [R0, R1, R2, R3, R4, R5] in { + def JAL : CALL<"call">; +} + +class NOP_I + : InstBPF<(outs), (ins i32imm:$imm), + !strconcat(asmstr, "\t$imm"), []> { + bits<32> imm; + + let Inst{31-0} = imm; + + let Inst{63-59} = 0; + let bpfClass = 7; // BPF_MISC +} + +let neverHasSideEffects = 1 in + def NOP : NOP_I<"nop">; + +class RET + : InstBPF<(outs), (ins), + !strconcat(asmstring, ""), [(retflag)]> { + let Inst{63-59} = 0; + let bpfClass = 6; // BPF_RET +} + +let isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1, isNotDuplicable = 1 in { + def RET : RET<"ret">; +} + +// ADJCALLSTACKDOWN/UP pseudo insns +let Defs = [R11], Uses = [R11] in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt), + "#ADJCALLSTACKDOWN $amt", + [(callseq_start timm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), + "#ADJCALLSTACKUP $amt1 $amt2", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + + +//let Defs = [R11], Uses = [R11] in { +// def ADJDYNALLOC : Pseudo<(outs GPR:$dst), (ins GPR:$src), +// "#ADJDYNALLOC $dst $src", +// [(set GPR:$dst, (BPFadjdynalloc GPR:$src))]>; +//} + + +let usesCustomInserter = 1 in { + def Select : Pseudo<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs, s32imm:$imm, GPR:$src, GPR:$src2), + "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", + [(set (i64 GPR:$dst), + (BPFselectcc (i64 GPR:$lhs), (i64 GPR:$rhs), (i64 imm:$imm), (i64 GPR:$src), (i64 GPR:$src2)))]>; +} + +// Non-Instruction Patterns + +// arbitrary immediate +def : Pat<(i64 imm:$imm), (ADD_ri (SLL_ri (MOV_ri (HI32 imm:$imm)), 32), (LO32 imm:$imm))>; + +// 0xffffFFFF doesn't fit into simm32, optimize common case +def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>; + +// Calls +def : Pat<(call tglobaladdr:$dst), (JAL tglobaladdr:$dst)>; +//def : Pat<(call texternalsym:$dst), (JAL texternalsym:$dst)>; +//def : Pat<(call (i32 imm:$dst)), (JAL (i32 imm:$dst))>; +//def : Pat<(call imm:$dst), (JAL imm:$dst)>; + +// Loads +def : Pat<(extloadi8 ADDRri:$src), (i64 (LDB ADDRri:$src))>; +def : Pat<(extloadi16 ADDRri:$src), (i64 (LDH ADDRri:$src))>; +def : Pat<(extloadi32 ADDRri:$src), (i64 (LDW ADDRri:$src))>; + +// Atomics +class XADD sizeOp, string asmstr, PatFrag opNode> + : InstBPF<(outs GPR:$dst), (ins MEMri:$addr, GPR:$val), + !strconcat(asmstr, "\t$dst, $addr, $val"), + [(set GPR:$dst, (opNode ADDRri:$addr, GPR:$val))]> { + bits<3> mode; + bits<2> size; + bits<4> rX; + bits<20> addr; + + let Inst{63-61} = mode; + let Inst{60-59} = size; + let Inst{51-48} = addr{19-16}; // base reg + let Inst{55-52} = rX; + let Inst{47-32} = addr{15-0}; // offset + + let mode = 7; // BPF_XADD + let size = sizeOp; + let bpfClass = 3; // BPF_STX +} + +let Constraints = "$dst = $val" in { +def XADD32 : XADD<0, "xadd32", atomic_load_add_32>; +def XADD16 : XADD<1, "xadd16", atomic_load_add_16>; +def XADD8 : XADD<2, "xadd8", atomic_load_add_8>; +def XADD64 : XADD<3, "xadd64", atomic_load_add_64>; +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.cpp new file mode 100644 index 0000000..5c15ed7 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.cpp @@ -0,0 +1,77 @@ +//=-- BPFMCInstLower.cpp - Convert BPF MachineInstr to an MCInst ----------=// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains code to lower BPF MachineInstrs to their corresponding +// MCInst records. + +#include "BPFMCInstLower.h" +#include "MCTargetDesc/BPFBaseInfo.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + +MCSymbol *BPFMCInstLower:: +GetGlobalAddressSymbol(const MachineOperand &MO) const { +#if LLVM_VERSION_MINOR==4 + return Printer.getSymbol(MO.getGlobal()); +#else + return Printer.Mang->getSymbol(MO.getGlobal()); +#endif +} + +MCOperand BPFMCInstLower:: +LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { + + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + + if (!MO.isJTI() && MO.getOffset()) + llvm_unreachable("unknown symbol op"); +// Expr = MCBinaryExpr::CreateAdd(Expr, +// MCConstantExpr::Create(MO.getOffset(), Ctx), +// Ctx); + return MCOperand::CreateExpr(Expr); +} + +void BPFMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + MO.getMBB()->getSymbol(), Ctx)); + break; + case MachineOperand::MO_RegisterMask: + continue; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + } + + OutMI.addOperand(MCOp); + } +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.h b/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.h new file mode 100644 index 0000000..aaff0c3 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFMCInstLower.h @@ -0,0 +1,40 @@ +//===-- BPFMCInstLower.h - Lower MachineInstr to MCInst --------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef BPF_MCINSTLOWER_H +#define BPF_MCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + class AsmPrinter; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + class Mangler; + + /// BPFMCInstLower - This class is used to lower an MachineInstr + /// into an MCInst. +class LLVM_LIBRARY_VISIBILITY BPFMCInstLower { + MCContext &Ctx; + Mangler &Mang; + + AsmPrinter &Printer; +public: + BPFMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer) + : Ctx(ctx), Mang(mang), Printer(printer) {} + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; +}; + +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.cpp new file mode 100644 index 0000000..7d46041 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.cpp @@ -0,0 +1,122 @@ +//===-- BPFRegisterInfo.cpp - BPF Register Information --------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains the BPF implementation of the TargetRegisterInfo class. + +#include "BPF.h" +#include "BPFRegisterInfo.h" +#include "BPFSubtarget.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" + +#define GET_REGINFO_TARGET_DESC +#include "BPFGenRegisterInfo.inc" +using namespace llvm; + +BPFRegisterInfo::BPFRegisterInfo(const TargetInstrInfo &tii) + : BPFGenRegisterInfo(BPF::R0), TII(tii) { +} + +const uint16_t* +BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + return CSR_SaveList; +} + +BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(BPF::R10); + Reserved.set(BPF::R11); + return Reserved; +} + +bool +BPFRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { + return true; +} + +void +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 +BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { +#else +BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { +#endif + assert(SPAdj == 0 && "Unexpected"); + + unsigned i = 0; + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + DebugLoc dl = MI.getDebugLoc(); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + unsigned FrameReg = getFrameRegister(MF); + int FrameIndex = MI.getOperand(i).getIndex(); + + if (MI.getOpcode() == BPF::MOV_rr) { + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + + MI.getOperand(i).ChangeToRegister(FrameReg, false); + + MachineBasicBlock &MBB = *MI.getParent(); + unsigned reg = MI.getOperand(i - 1).getReg(); + BuildMI(MBB, ++ II, dl, TII.get(BPF::ADD_ri), reg) + .addReg(reg).addImm(Offset); + return; + } + + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + + MI.getOperand(i+1).getImm(); + + if (!isInt<32>(Offset)) { + llvm_unreachable("bug in frame offset"); + } + + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Offset); +} + +void BPFRegisterInfo:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const {} + +bool BPFRegisterInfo::hasBasePointer(const MachineFunction &MF) const { + return false; +} + +bool BPFRegisterInfo::needsStackRealignment(const MachineFunction &MF) const { + return false; +} + +unsigned BPFRegisterInfo::getRARegister() const { + return BPF::R0; +} + +unsigned BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return BPF::R10; +} + +unsigned BPFRegisterInfo::getBaseRegister() const { + llvm_unreachable("What is the base register"); + return 0; +} + +unsigned BPFRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned BPFRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.h b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.h new file mode 100644 index 0000000..8aeb341 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.h @@ -0,0 +1,65 @@ +//===- BPFRegisterInfo.h - BPF Register Information Impl ------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file contains the BPF implementation of the TargetRegisterInfo class. + +#ifndef BPFREGISTERINFO_H +#define BPFREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "BPFGenRegisterInfo.inc" + +namespace llvm { + +class TargetInstrInfo; +class Type; + +struct BPFRegisterInfo : public BPFGenRegisterInfo { + const TargetInstrInfo &TII; + + BPFRegisterInfo(const TargetInstrInfo &tii); + + /// Code Generation virtual methods... + const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + bool requiresRegisterScavenging(const MachineFunction &MF) const; + + // llvm 3.2 defines it here + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. + MBB.erase(I); + } + +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + void eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS = NULL) const; +#else + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; +#endif + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + bool hasBasePointer(const MachineFunction &MF) const; + bool needsStackRealignment(const MachineFunction &MF) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + unsigned getBaseRegister() const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + int getDwarfRegNum(unsigned RegNum, bool isEH) const; +}; +} +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.td b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.td new file mode 100644 index 0000000..fac0817 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFRegisterInfo.td @@ -0,0 +1,39 @@ +//===- BPFRegisterInfo.td - BPF Register defs ------------*- tablegen -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// Declarations that describe the BPF register file + +class BPFReg : Register { + field bits<4> Num; + let Namespace = "BPF"; +} + +// Registers are identified with 4-bit ID numbers. +// Ri - 64-bit integer registers +class Ri num, string n> : BPFReg { + let Num = num; +} + +// Integer registers +def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>; +def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>; +def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>; +def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>; +def R4 : Ri< 4, "r4">, DwarfRegNum<[4]>; +def R5 : Ri< 5, "r5">, DwarfRegNum<[5]>; +def R6 : Ri< 6, "r6">, DwarfRegNum<[6]>; +def R7 : Ri< 7, "r7">, DwarfRegNum<[7]>; +def R8 : Ri< 8, "r8">, DwarfRegNum<[8]>; +def R9 : Ri< 9, "r9">, DwarfRegNum<[9]>; +def R10 : Ri<10, "r10">, DwarfRegNum<[10]>; +def R11 : Ri<11, "r11">, DwarfRegNum<[11]>; + +// Register classes. +def GPR : RegisterClass<"BPF", [i64], 64, (add R1, R2, R3, R4, R5, + R6, R7, R8, R9, // callee saved + R0, // return value + R11, // stack ptr + R10 // frame ptr + )>; + diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.cpp new file mode 100644 index 0000000..6e98f6d --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.cpp @@ -0,0 +1,23 @@ +//===- BPFSubtarget.cpp - BPF Subtarget Information -----------*- C++ -*-=// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "BPF.h" +#include "BPFSubtarget.h" +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "BPFGenSubtargetInfo.inc" +using namespace llvm; + +void BPFSubtarget::anchor() { } + +BPFSubtarget::BPFSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS) + : BPFGenSubtargetInfo(TT, CPU, FS) +{ + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; + + ParseSubtargetFeatures(CPUName, FS); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.h b/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.h new file mode 100644 index 0000000..cd5d875 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFSubtarget.h @@ -0,0 +1,33 @@ +//=====-- BPFSubtarget.h - Define Subtarget for the BPF -----*- C++ -*--==// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef BPFSUBTARGET_H +#define BPFSUBTARGET_H + +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Target/TargetMachine.h" + +#include + +#define GET_SUBTARGETINFO_HEADER +#include "BPFGenSubtargetInfo.inc" + +namespace llvm { + +class BPFSubtarget : public BPFGenSubtargetInfo { + virtual void anchor(); +public: + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + BPFSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); +}; +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.cpp new file mode 100644 index 0000000..bd811fd --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -0,0 +1,72 @@ +//===-- BPFTargetMachine.cpp - Define TargetMachine for BPF ---------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// Implements the info about BPF target spec. + +#include "BPF.h" +#include "BPFTargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +extern "C" void LLVMInitializeBPFTarget() { + // Register the target. + RegisterTargetMachine X(TheBPFTarget); +} + +// DataLayout --> Little-endian, 64-bit pointer/ABI/alignment +// The stack is always 8 byte aligned +// On function prologue, the stack is created by decrementing +// its pointer. Once decremented, all references are done with positive +// offset from the stack/frame pointer. +BPFTargetMachine:: +BPFTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + Subtarget(TT, CPU, FS), + // x86-64 like + DL("e-p:64:64-s:64-f64:64:64-i64:64:64-n8:16:32:64-S128"), + InstrInfo(), TLInfo(*this), TSInfo(*this), + FrameLowering(Subtarget) { +#if LLVM_VERSION_MINOR==4 + initAsmInfo(); +#endif +} +namespace { +/// BPF Code Generator Pass Configuration Options. +class BPFPassConfig : public TargetPassConfig { +public: + BPFPassConfig(BPFTargetMachine *TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + BPFTargetMachine &getBPFTargetMachine() const { + return getTM(); + } + + virtual bool addInstSelector(); + virtual bool addPreEmitPass(); +}; +} + +TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) { + return new BPFPassConfig(this, PM); +} + +// Install an instruction selector pass using +// the ISelDag to gen BPF code. +bool BPFPassConfig::addInstSelector() { + addPass(createBPFISelDag(getBPFTargetMachine())); + + return false; +} + +bool BPFPassConfig::addPreEmitPass() { + addPass(createBPFCFGFixup(getBPFTargetMachine())); + return true; +} diff --git a/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.h b/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.h new file mode 100644 index 0000000..1d6b070 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/BPFTargetMachine.h @@ -0,0 +1,69 @@ +//===-- BPFTargetMachine.h - Define TargetMachine for BPF --- C++ ---===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file declares the BPF specific subclass of TargetMachine. + +#ifndef BPF_TARGETMACHINE_H +#define BPF_TARGETMACHINE_H + +#include "BPFSubtarget.h" +#include "BPFInstrInfo.h" +#include "BPFISelLowering.h" +#include "llvm/Target/TargetSelectionDAGInfo.h" +#include "BPFFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#if !defined(LLVM_VERSION_MINOR) +#error "Uknown version" +#endif +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 +#include "llvm/IR/DataLayout.h" +#else +#include "llvm/DataLayout.h" +#endif +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + class formatted_raw_ostream; + + class BPFTargetMachine : public LLVMTargetMachine { + BPFSubtarget Subtarget; + const DataLayout DL; // Calculates type size & alignment + BPFInstrInfo InstrInfo; + BPFTargetLowering TLInfo; + TargetSelectionDAGInfo TSInfo; + BPFFrameLowering FrameLowering; + public: + BPFTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); + + virtual const BPFInstrInfo *getInstrInfo() const + { return &InstrInfo; } + + virtual const TargetFrameLowering *getFrameLowering() const + { return &FrameLowering; } + + virtual const BPFSubtarget *getSubtargetImpl() const + { return &Subtarget; } + + virtual const DataLayout *getDataLayout() const + { return &DL;} + + virtual const BPFRegisterInfo *getRegisterInfo() const + { return &InstrInfo.getRegisterInfo(); } + + virtual const BPFTargetLowering *getTargetLowering() const + { return &TLInfo; } + + virtual const TargetSelectionDAGInfo* getSelectionDAGInfo() const + { return &TSInfo; } + + // Pass Pipeline Configuration + virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); + }; +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp b/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp new file mode 100644 index 0000000..89d5cdb --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp @@ -0,0 +1,79 @@ +//===-- BPFInstPrinter.cpp - Convert BPF MCInst to asm syntax -----------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This class prints an BPF MCInst to a .s file. + +#define DEBUG_TYPE "asm-printer" +#include "BPF.h" +#include "BPFInstPrinter.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + + +// Include the auto-generated portion of the assembly writer. +#include "BPFGenAsmWriter.inc" + +void BPFInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot) { + printInstruction(MI, O); + printAnnotation(O, Annot); +} + +static void printExpr(const MCExpr *Expr, raw_ostream &O) { + const MCSymbolRefExpr *SRE; + + if (const MCBinaryExpr *BE = dyn_cast(Expr)) + SRE = dyn_cast(BE->getLHS()); + else + SRE = dyn_cast(Expr); + assert(SRE && "Unexpected MCExpr type."); + + MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); + + assert(Kind == MCSymbolRefExpr::VK_None); + O << *Expr; +} + +void BPFInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << getRegisterName(Op.getReg()); + } else if (Op.isImm()) { + O << (int32_t)Op.getImm(); + } else { + assert(Op.isExpr() && "Expected an expression"); + printExpr(Op.getExpr(), O); + } +} + +void BPFInstPrinter::printMemOperand(const MCInst *MI, int OpNo, + raw_ostream &O, const char *Modifier) { + const MCOperand &RegOp = MI->getOperand(OpNo); + const MCOperand &OffsetOp = MI->getOperand(OpNo+1); + // offset + if (OffsetOp.isImm()) { + O << OffsetOp.getImm(); + } else { + assert(0 && "Expected an immediate"); +// assert(OffsetOp.isExpr() && "Expected an expression"); +// printExpr(OffsetOp.getExpr(), O); + } + // register + assert(RegOp.isReg() && "Register operand not a register"); + O << "(" << getRegisterName(RegOp.getReg()) << ")"; +} + +void BPFInstPrinter::printS32ImmOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + assert(Op.isImm() && "Immediate operand not an immediate"); + O << (int32_t)Op.getImm(); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.h b/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.h new file mode 100644 index 0000000..4f0cba5 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/InstPrinter/BPFInstPrinter.h @@ -0,0 +1,34 @@ +//= BPFInstPrinter.h - Convert BPF MCInst to asm syntax ---------*- C++ -*--// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This class prints a BPF MCInst to a .s file. + +#ifndef BPFINSTPRINTER_H +#define BPFINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class MCOperand; + + class BPFInstPrinter : public MCInstPrinter { + public: + BPFInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); + void printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier = 0); + void printMemOperand(const MCInst *MI, int OpNo,raw_ostream &O, + const char *Modifier = 0); + void printS32ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + }; +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp new file mode 100644 index 0000000..8d5b5c9 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -0,0 +1,85 @@ +//===-- BPFAsmBackend.cpp - BPF Assembler Backend -----------------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "MCTargetDesc/BPFMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class BPFAsmBackend : public MCAsmBackend { +public: + BPFAsmBackend(): MCAsmBackend() {} + virtual ~BPFAsmBackend() {} + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const; + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const; + + // No instruction requires relaxation +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const { return false; } +#else + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCInstFragment *DF, + const MCAsmLayout &Layout) const { return false; } +#endif + + unsigned getNumFixupKinds() const { return 1; } + + bool mayNeedRelaxation(const MCInst &Inst) const { return false; } + + void relaxInstruction(const MCInst &Inst, MCInst &Res) const {} + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; +}; + +bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { + if ((Count % 8) != 0) + return false; + + for (uint64_t i = 0; i < Count; i += 8) + OW->Write64(0x15000000); + + return true; +} + +void BPFAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value) const { + + assert (Fixup.getKind() == FK_PCRel_2); + *(uint16_t*)&Data[Fixup.getOffset() + 2] = (uint16_t) ((Value - 8) / 8); + + if (0) + errs() << "\n"; +} + +MCObjectWriter *BPFAsmBackend::createObjectWriter(raw_ostream &OS) const { + return createBPFELFObjectWriter(OS, 0); +} + +} + +MCAsmBackend *llvm::createBPFAsmBackend(const Target &T, +#if LLVM_VERSION_MINOR==4 + const MCRegisterInfo &MRI, +#endif + StringRef TT, StringRef CPU) { + return new BPFAsmBackend(); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFBaseInfo.h b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFBaseInfo.h new file mode 100644 index 0000000..9d03073 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFBaseInfo.h @@ -0,0 +1,33 @@ +//===-- BPFBaseInfo.h - Top level definitions for BPF MC ------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +#ifndef BPFBASEINFO_H +#define BPFBASEINFO_H + +#include "BPFMCTargetDesc.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +static inline unsigned getBPFRegisterNumbering(unsigned Reg) { + switch(Reg) { + case BPF::R0 : return 0; + case BPF::R1 : return 1; + case BPF::R2 : return 2; + case BPF::R3 : return 3; + case BPF::R4 : return 4; + case BPF::R5 : return 5; + case BPF::R6 : return 6; + case BPF::R7 : return 7; + case BPF::R8 : return 8; + case BPF::R9 : return 9; + case BPF::R10 : return 10; + case BPF::R11 : return 11; + default: llvm_unreachable("Unknown register number!"); + } +} + +} +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp new file mode 100644 index 0000000..22cf0d6 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp @@ -0,0 +1,119 @@ +//===-- BPFELFObjectWriter.cpp - BPF Writer -------------------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "MCTargetDesc/BPFBaseInfo.h" +#include "MCTargetDesc/BPFMCTargetDesc.h" +#include "MCTargetDesc/BPFMCCodeEmitter.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class BPFObjectWriter : public MCObjectWriter { + public: + BPFObjectWriter(raw_ostream &_OS): + MCObjectWriter(_OS, true/*isLittleEndian*/) {} + virtual ~BPFObjectWriter() {} + virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + virtual void RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) {} + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) {} + +}; +} + +static void WriteSectionData(MCAssembler &Asm, const MCSectionData &SD) { + MCObjectWriter *OW = &Asm.getWriter(); + for (MCSectionData::const_iterator it = SD.begin(), + ie = SD.end(); it != ie; ++it) { + const MCFragment &F = *it; + switch (F.getKind()) { + case MCFragment::FT_Align: + continue; + case MCFragment::FT_Data: { + const MCDataFragment &DF = cast(F); + OW->WriteBytes(DF.getContents()); + break; + } + case MCFragment::FT_Fill: { + const MCFillFragment &FF = cast(F); + + assert(FF.getValueSize() && "Invalid virtual align in concrete fragment!"); + + for (uint64_t i = 0, e = FF.getSize() / FF.getValueSize(); i != e; ++i) { + switch (FF.getValueSize()) { + default: llvm_unreachable("Invalid size!"); + case 1: OW->Write8 (uint8_t (FF.getValue())); break; + case 2: OW->Write16(uint16_t(FF.getValue())); break; + case 4: OW->Write32(uint32_t(FF.getValue())); break; + case 8: OW->Write64(uint64_t(FF.getValue())); break; + } + } + break; + } + default: + errs() << "MCFrag " << F.getKind() << "\n"; + } + } +} + +void BPFObjectWriter::WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + bool LicenseSeen = false; + MCObjectWriter *OW = &Asm.getWriter(); + OW->WriteBytes(StringRef("bpf"), 4); + + BPFMCCodeEmitter *CE = (BPFMCCodeEmitter*)(&Asm.getEmitter()); +// Asm.dump(); + for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; + ++i) { + const MCSectionELF &Section = + static_cast(i->getSection()); + const StringRef SectionName = Section.getSectionName(); + const MCSectionData &SD = Asm.getSectionData(Section); + int SectionSize = Layout.getSectionAddressSize(&SD); + if (SectionSize > 0) { + CE->getStrtabIndex(SectionName); + if (SectionName == "license") + LicenseSeen = true; + } + } + + if (!LicenseSeen) + report_fatal_error("BPF source is missing license"); + + OW->Write32(CE->Strtab->length()); + OW->WriteBytes(StringRef(*CE->Strtab)); + + for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; + ++i) { + const MCSectionELF &Section = + static_cast(i->getSection()); + const StringRef SectionName = Section.getSectionName(); + const MCSectionData &SD = Asm.getSectionData(Section); + int SectionSize = Layout.getSectionAddressSize(&SD); + if (SectionSize > 0 && + /* ignore .rodata.* for now */ + !(Section.getFlags() & ELF::SHF_STRINGS)) { + OW->Write32(SectionSize); + OW->Write32(CE->getStrtabIndex(SectionName)); + WriteSectionData(Asm, SD); + } + } +} + +MCObjectWriter *llvm::createBPFELFObjectWriter(raw_ostream &OS, + uint8_t OSABI) { + return new BPFObjectWriter(OS); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h new file mode 100644 index 0000000..99132ee --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h @@ -0,0 +1,34 @@ +//=====-- BPFMCAsmInfo.h - BPF asm properties -----------*- C++ -*--====// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#ifndef BPF_MCASM_INFO_H +#define BPF_MCASM_INFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class Target; + + class BPFMCAsmInfo : public MCAsmInfo { + public: +#if LLVM_VERSION_MINOR==4 + explicit BPFMCAsmInfo(StringRef TT) { +#else + explicit BPFMCAsmInfo(const Target &T, StringRef TT) { +#endif + PrivateGlobalPrefix = ".L"; + WeakRefDirective = "\t.weak\t"; + + // BPF assembly requires ".section" before ".bss" + UsesELFSectionDirectiveForBSS = true; + + HasSingleParameterDotFile = false; + HasDotTypeDotSizeDirective = false; + } + }; + +} + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp new file mode 100644 index 0000000..9e3f52c --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp @@ -0,0 +1,120 @@ +//===-- BPFMCCodeEmitter.cpp - Convert BPF code to machine code ---------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#define DEBUG_TYPE "mccodeemitter" +#include "MCTargetDesc/BPFBaseInfo.h" +#include "MCTargetDesc/BPFMCTargetDesc.h" +#include "MCTargetDesc/BPFMCCodeEmitter.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +MCCodeEmitter *llvm::createBPFMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new BPFMCCodeEmitter(MCII, STI, Ctx); +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned BPFMCCodeEmitter:: +getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups) const { + if (MO.isReg()) + return getBPFRegisterNumbering(MO.getReg()); + if (MO.isImm()) + return static_cast(MO.getImm()); + + assert(MO.isExpr()); + + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + +/* if (Kind == MCExpr::Binary) { + Expr = static_cast(Expr)->getLHS(); + Kind = Expr->getKind(); + }*/ + + assert (Kind == MCExpr::SymbolRef); + + if (MI.getOpcode() == BPF::JAL) { + /* func call name */ +// Fixups.push_back(MCFixup::Create(0, MO.getExpr(), FK_SecRel_4)); + const MCSymbolRefExpr *SRE = dyn_cast(Expr); + return getStrtabIndex(SRE->getSymbol().getName()); + + } else { + /* bb label */ + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), FK_PCRel_2)); + return 0; + } +} + +// Emit one byte through output stream +void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) { + OS << (char)C; + ++CurByte; +} + +// Emit a series of bytes (little endian) +void EmitLEConstant(uint64_t Val, unsigned Size, unsigned &CurByte, + raw_ostream &OS) { + assert(Size <= 8 && "size too big in emit constant"); + + for (unsigned i = 0; i != Size; ++i) { + EmitByte(Val & 255, CurByte, OS); + Val >>= 8; + } +} + +// Emit a series of bytes (big endian) +void EmitBEConstant(uint64_t Val, unsigned Size, unsigned &CurByte, + raw_ostream &OS) { + assert(Size <= 8 && "size too big in emit constant"); + + for (int i = (Size-1)*8; i >= 0; i-=8) + EmitByte((Val >> i) & 255, CurByte, OS); +} + +void BPFMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups) const { +// unsigned Opcode = MI.getOpcode(); +// const MCInstrDesc &Desc = MCII.get(Opcode); + // Keep track of the current byte being emitted + unsigned CurByte = 0; + + // Get instruction encoding and emit it + ++MCNumEmitted; // Keep track of the number of emitted insns. + uint64_t Value = getBinaryCodeForInstr(MI, Fixups); + EmitByte(Value >> 56, CurByte, OS); + EmitByte((Value >> 48) & 0xff, CurByte, OS); + EmitLEConstant((Value >> 32) & 0xffff, 2, CurByte, OS); + EmitLEConstant(Value & 0xffffFFFF, 4, CurByte, OS); +} + +// Encode BPF Memory Operand +uint64_t BPFMCCodeEmitter::getMemoryOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + uint64_t encoding; + const MCOperand op1 = MI.getOperand(1); + assert(op1.isReg() && "First operand is not register."); + encoding = getBPFRegisterNumbering(op1.getReg()); + encoding <<= 16; + MCOperand op2 = MI.getOperand(2); + assert(op2.isImm() && "Second operand is not immediate."); + encoding |= op2.getImm() & 0xffff; + return encoding; +} + +#include "BPFGenMCCodeEmitter.inc" diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.h b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.h new file mode 100644 index 0000000..84d86c0 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.h @@ -0,0 +1,67 @@ +//===-- BPFMCCodeEmitter.h - Convert BPF code to machine code ---------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "MCTargetDesc/BPFBaseInfo.h" +#include "MCTargetDesc/BPFMCTargetDesc.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { +class BPFMCCodeEmitter : public MCCodeEmitter { + BPFMCCodeEmitter(const BPFMCCodeEmitter &); + void operator=(const BPFMCCodeEmitter &); + const MCInstrInfo &MCII; + const MCSubtargetInfo &STI; + MCContext &Ctx; + +public: + BPFMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) + : MCII(mcii), STI(sti), Ctx(ctx) { + Strtab = new std::string; + Strtab->push_back('\0'); + } + + ~BPFMCCodeEmitter() {delete Strtab;} + + std::string *Strtab; + + int getStrtabIndex(const StringRef Name) const { + std::string Sym = Name.str(); + Sym.push_back('\0'); + + std::string::size_type pos = Strtab->find(Sym); + if (pos == std::string::npos) { + Strtab->append(Sym); + pos = Strtab->find(Sym); + assert (pos != std::string::npos); + } + return pos; + } + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups) const; + + // getMachineOpValue - Return binary encoding of operand. If the machin + // operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, + SmallVectorImpl &Fixups) const; + + uint64_t getMemoryOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups) const; +}; +} diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp new file mode 100644 index 0000000..db043d7 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp @@ -0,0 +1,115 @@ +//===-- BPFMCTargetDesc.cpp - BPF Target Descriptions -----------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file provides BPF specific target descriptions. + +#include "BPF.h" +#include "BPFMCTargetDesc.h" +#include "BPFMCAsmInfo.h" +#include "InstPrinter/BPFInstPrinter.h" +#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "BPFGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "BPFGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "BPFGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createBPFMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitBPFMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createBPFMCRegisterInfo(StringRef TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitBPFMCRegisterInfo(X, BPF::R9); + return X; +} + +static MCSubtargetInfo *createBPFMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitBPFMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +static MCCodeGenInfo *createBPFMCCodeGenInfo(StringRef TT, Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + X->InitMCCodeGenInfo(RM, CM, OL); + return X; +} + +static MCStreamer *createBPFMCStreamer(const Target &T, StringRef TT, + MCContext &Ctx, MCAsmBackend &MAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack) { +#if LLVM_VERSION_MINOR==4 + return createELFStreamer(Ctx, 0, MAB, _OS, _Emitter, RelaxAll, NoExecStack); +#else + return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack); +#endif +} + +static MCInstPrinter *createBPFMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI) { + if (SyntaxVariant == 0) + return new BPFInstPrinter(MAI, MII, MRI); + return 0; +} + +extern "C" void LLVMInitializeBPFTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfo X(TheBPFTarget); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(TheBPFTarget, + createBPFMCCodeGenInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheBPFTarget, createBPFMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheBPFTarget, createBPFMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheBPFTarget, + createBPFMCSubtargetInfo); + + // Register the MC code emitter + TargetRegistry::RegisterMCCodeEmitter(TheBPFTarget, + llvm::createBPFMCCodeEmitter); + + // Register the ASM Backend + TargetRegistry::RegisterMCAsmBackend(TheBPFTarget, + createBPFAsmBackend); + + // Register the object streamer + TargetRegistry::RegisterMCObjectStreamer(TheBPFTarget, + createBPFMCStreamer); + + + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(TheBPFTarget, + createBPFMCInstPrinter); +} diff --git a/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h new file mode 100644 index 0000000..b337a00 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h @@ -0,0 +1,56 @@ +//===-- BPFMCTargetDesc.h - BPF Target Descriptions -----------*- C++ -*-===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file provides BPF specific target descriptions. + +#ifndef BPFMCTARGETDESC_H +#define BPFMCTARGETDESC_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Config/config.h" + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class Target; +class StringRef; +class raw_ostream; + +extern Target TheBPFTarget; + +MCCodeEmitter *createBPFMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx); + +MCAsmBackend *createBPFAsmBackend(const Target &T, +#if LLVM_VERSION_MINOR==4 + const MCRegisterInfo &MRI, +#endif + StringRef TT, StringRef CPU); + + +MCObjectWriter *createBPFELFObjectWriter(raw_ostream &OS, uint8_t OSABI); +} + +// Defines symbolic names for BPF registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "BPFGenRegisterInfo.inc" + +// Defines symbolic names for the BPF instructions. +// +#define GET_INSTRINFO_ENUM +#include "BPFGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "BPFGenSubtargetInfo.inc" + +#endif diff --git a/tools/bpf/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp b/tools/bpf/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp new file mode 100644 index 0000000..4d16305 --- /dev/null +++ b/tools/bpf/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp @@ -0,0 +1,13 @@ +//===-- BPFTargetInfo.cpp - BPF Target Implementation -----------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "BPF.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheBPFTarget; + +extern "C" void LLVMInitializeBPFTargetInfo() { + RegisterTarget X(TheBPFTarget, "bpf", "BPF"); +} diff --git a/tools/bpf/llvm/tools/llc/llc.cpp b/tools/bpf/llvm/tools/llc/llc.cpp new file mode 100644 index 0000000..517a7a8 --- /dev/null +++ b/tools/bpf/llvm/tools/llc/llc.cpp @@ -0,0 +1,381 @@ +//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This is the llc code generator driver. It provides a convenient +// command-line interface for generating native assembly-language code +// or C code, given LLVM bitcode. + +#include "llvm/Config/config.h" +#undef LLVM_NATIVE_TARGET +#undef LLVM_NATIVE_ASMPRINTER +#undef LLVM_NATIVE_ASMPARSER +#undef LLVM_NATIVE_DISASSEMBLER +#if LLVM_VERSION_MINOR==3 || LLVM_VERSION_MINOR==4 +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Support/SourceMgr.h" +#else +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/DataLayout.h" +#include "llvm/Support/IRReader.h" +#endif +#include "llvm/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/CodeGen/LinkAllAsmWriterComponents.h" +#include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Target/TargetMachine.h" +#include +using namespace llvm; + +extern "C" { +void AnnotateHappensBefore(const char *file, int line, + const volatile void *cv) {} +void AnnotateHappensAfter(const char *file, int line, + const volatile void *cv) {} +void AnnotateIgnoreWritesBegin(const char *file, int line) {} +void AnnotateIgnoreWritesEnd(const char *file, int line) {} +} + +__attribute__((weak)) bool llvm::DebugFlag; + +__attribute__((weak)) bool llvm::isCurrentDebugType(const char *Type) { + return false; +} + +// General options for llc. Other pass-specific options are specified +// within the corresponding llc passes, and target-specific options +// and back-end code generation options are specified with the target machine. +// +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); + +// Determine optimization level. +static cl::opt +OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, + cl::ZeroOrMore, + cl::init(' ')); + +static cl::opt +TargetTriple("mtriple", cl::desc("Override target triple for module")); + +static cl::list +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +cl::opt +FileType("filetype", cl::init(TargetMachine::CGFT_ObjectFile), + cl::desc("Choose a file type (not all types are supported by all targets):"), + cl::values( + clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", + "Emit an assembly ('.s') file"), + clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", + "Emit a native object ('.o') file"), + clEnumValN(TargetMachine::CGFT_Null, "null", + "Emit nothing, for performance testing"), + clEnumValEnd)); + +cl::opt NoVerify("disable-verify", cl::Hidden, + cl::desc("Do not verify input module")); + +static cl::opt +DontPlaceZerosInBSS("nozero-initialized-in-bss", + cl::desc("Don't place zero-initialized symbols into bss section"), + cl::init(false)); + +static cl::opt +DisableSimplifyLibCalls("disable-simplify-libcalls", + cl::desc("Disable simplify-libcalls"), + cl::init(false)); + +static cl::opt +EnableGuaranteedTailCallOpt("tailcallopt", + cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), + cl::init(false)); + +static cl::opt +DisableTailCalls("disable-tail-calls", + cl::desc("Never emit tail calls"), + cl::init(false)); + +static cl::opt StopAfter("stop-after", + cl::desc("Stop compilation after a specific pass"), + cl::value_desc("pass-name"), + cl::init("")); +static cl::opt StartAfter("start-after", + cl::desc("Resume compilation after a specific pass"), + cl::value_desc("pass-name"), + cl::init("")); + +// GetFileNameRoot - Helper function to get the basename of a filename. +static inline std::string +GetFileNameRoot(const std::string &InputFilename) { + std::string IFN = InputFilename; + std::string outputFilename; + int Len = IFN.length(); + if ((Len > 2) && + IFN[Len-3] == '.' && + ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') || + (IFN[Len-2] == 'l' && IFN[Len-1] == 'l'))) { + outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ + } else { + outputFilename = IFN; + } + return outputFilename; +} + +static tool_output_file *GetOutputStream(const char *TargetName, + Triple::OSType OS, + const char *ProgName) { + // If we don't yet have an output filename, make one. + if (OutputFilename.empty()) { + if (InputFilename == "-") + OutputFilename = "-"; + else { + OutputFilename = GetFileNameRoot(InputFilename); + + switch (FileType) { + case TargetMachine::CGFT_AssemblyFile: + if (TargetName[0] == 'c') { + if (TargetName[1] == 0) + OutputFilename += ".cbe.c"; + else if (TargetName[1] == 'p' && TargetName[2] == 'p') + OutputFilename += ".cpp"; + else + OutputFilename += ".s"; + } else + OutputFilename += ".s"; + break; + case TargetMachine::CGFT_ObjectFile: + OutputFilename += ".o"; + break; + case TargetMachine::CGFT_Null: + OutputFilename += ".null"; + break; + } + } + } + + // Decide if we need "binary" output. + bool Binary = false; + switch (FileType) { + case TargetMachine::CGFT_AssemblyFile: + break; + case TargetMachine::CGFT_ObjectFile: + case TargetMachine::CGFT_Null: + Binary = true; + break; + } + + // Open the file. + std::string error; +#if LLVM_VERSION_MINOR==4 + sys::fs::OpenFlags OpenFlags = sys::fs::F_None; + if (Binary) + OpenFlags |= sys::fs::F_Binary; +#else + unsigned OpenFlags = 0; + if (Binary) OpenFlags |= raw_fd_ostream::F_Binary; +#endif + tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error, + OpenFlags); + if (!error.empty()) { + errs() << error << '\n'; + delete FDOut; + return 0; + } + + return FDOut; +} + +// main - Entry point for the llc compiler. +// +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + // Enable debug stream buffering. + EnableDebugBuffering = true; + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets first, so that --version shows registered targets. + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + // Initialize codegen and IR passes used by llc so that the -print-after, + // -print-before, and -stop-after options work. + PassRegistry *Registry = PassRegistry::getPassRegistry(); + initializeCore(*Registry); + initializeCodeGen(*Registry); + initializeLoopStrengthReducePass(*Registry); + initializeLowerIntrinsicsPass(*Registry); + initializeUnreachableBlockElimPass(*Registry); + + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + + cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); + + // Load the module to be compiled... + SMDiagnostic Err; + std::auto_ptr M; + Module *mod = 0; + Triple TheTriple; + + M.reset(ParseIRFile(InputFilename, Err, Context)); + mod = M.get(); + if (mod == 0) { + Err.print(argv[0], errs()); + return 1; + } + + // If we are supposed to override the target triple, do so now. + if (!TargetTriple.empty()) + mod->setTargetTriple(Triple::normalize(TargetTriple)); + TheTriple = Triple(mod->getTargetTriple()); + + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getDefaultTargetTriple()); + + // Get the target specific parser. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget("bpf", TheTriple, + Error); + if (!TheTarget) { + errs() << argv[0] << ": " << Error; + return 1; + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + switch (OptLevel) { + default: + errs() << argv[0] << ": invalid optimization level.\n"; + return 1; + case ' ': break; + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + } + + TargetOptions Options; + Options.NoZerosInBSS = DontPlaceZerosInBSS; + Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; + Options.DisableTailCalls = DisableTailCalls; + + std::auto_ptr + target(TheTarget->createTargetMachine(TheTriple.getTriple(), + "", FeaturesStr, Options, + Reloc::Default, CodeModel::Default, OLvl)); + assert(target.get() && "Could not allocate target machine!"); + assert(mod && "Should have exited after outputting help!"); + TargetMachine &Target = *target.get(); + + Target.setMCUseLoc(false); + + Target.setMCUseCFI(false); + + // Figure out where we are going to send the output. + OwningPtr Out + (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); + if (!Out) return 1; + + // Build up all of the passes that we want to do to the module. + PassManager PM; + + // Add an appropriate TargetLibraryInfo pass for the module's triple. + TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple); + if (DisableSimplifyLibCalls) + TLI->disableAllFunctions(); + PM.add(TLI); + + // Add the target data from the target machine, if it exists, or the module. + if (const DataLayout *TD = Target.getDataLayout()) + PM.add(new DataLayout(*TD)); + else + PM.add(new DataLayout(mod)); + + // Override default to generate verbose assembly. + Target.setAsmVerbosityDefault(true); + + { + formatted_raw_ostream FOS(Out->os()); + + AnalysisID StartAfterID = 0; + AnalysisID StopAfterID = 0; + const PassRegistry *PR = PassRegistry::getPassRegistry(); + if (!StartAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StartAfter); + if (!PI) { + errs() << argv[0] << ": start-after pass is not registered.\n"; + return 1; + } + StartAfterID = PI->getTypeInfo(); + } + if (!StopAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StopAfter); + if (!PI) { + errs() << argv[0] << ": stop-after pass is not registered.\n"; + return 1; + } + StopAfterID = PI->getTypeInfo(); + } + + // Ask the target to add backend passes as necessary. + if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify, + StartAfterID, StopAfterID)) { + errs() << argv[0] << ": target does not support generation of this" + << " file type!\n"; + return 1; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + PM.run(*mod); + } + + // Declare success. + Out->keep(); + + return 0; +} -- 1.7.9.5