summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-03-10 17:45:15 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-03-10 17:45:15 +0000
commit9e2446b38c94db61b2416c28fee415c03663c11c (patch)
tree231646bba785a129b3a2d409badb74e7ccd1594c
parent9bef28eb9e224d641ce31a423e215ccf82bf1d43 (diff)
downloadFreeBSD-src-9e2446b38c94db61b2416c28fee415c03663c11c.zip
FreeBSD-src-9e2446b38c94db61b2416c28fee415c03663c11c.tar.gz
Update LLVM to r98164.
-rw-r--r--bindings/ocaml/Makefile.ocaml123
-rw-r--r--docs/CodeGenerator.html47
-rw-r--r--docs/LangRef.html9
-rw-r--r--docs/SourceLevelDebugging.html200
-rw-r--r--docs/WritingAnLLVMPass.html16
-rw-r--r--docs/tutorial/OCamlLangImpl3.html8
-rw-r--r--docs/tutorial/OCamlLangImpl4.html39
-rw-r--r--docs/tutorial/OCamlLangImpl5.html34
-rw-r--r--docs/tutorial/OCamlLangImpl6.html26
-rw-r--r--docs/tutorial/OCamlLangImpl7.html26
-rw-r--r--examples/Makefile4
-rw-r--r--include/llvm/ADT/APFloat.h2
-rw-r--r--include/llvm/ADT/DenseMap.h7
-rw-r--r--include/llvm/ADT/DenseSet.h16
-rw-r--r--include/llvm/Analysis/DebugInfo.h190
-rw-r--r--include/llvm/Analysis/InlineCost.h5
-rw-r--r--include/llvm/Analysis/PostDominators.h4
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h8
-rw-r--r--include/llvm/CodeGen/DwarfWriter.h9
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h25
-rw-r--r--include/llvm/MC/MCAsmInfo.h21
-rw-r--r--include/llvm/MC/MCContext.h13
-rw-r--r--include/llvm/MC/MCExpr.h4
-rw-r--r--include/llvm/MC/MCStreamer.h5
-rw-r--r--include/llvm/Metadata.h6
-rw-r--r--include/llvm/Support/Dwarf.h3
-rw-r--r--include/llvm/Target/TargetLowering.h4
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h23
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h3
-rw-r--r--include/llvm/Transforms/IPO/InlinerPass.h4
-rw-r--r--lib/Analysis/DebugInfo.cpp236
-rw-r--r--lib/Analysis/InlineCost.cpp47
-rw-r--r--lib/Analysis/LoopInfo.cpp17
-rw-r--r--lib/Analysis/ScalarEvolution.cpp11
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp75
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp71
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h58
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp739
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h41
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp160
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfLabel.cpp32
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfLabel.h52
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.cpp205
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.h76
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfWriter.cpp12
-rw-r--r--lib/CodeGen/BranchFolding.cpp97
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp8
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp9
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp9
-rw-r--r--lib/CodeGen/MachineCSE.cpp120
-rw-r--r--lib/CodeGen/MachineFunction.cpp4
-rw-r--r--lib/CodeGen/MachineInstr.cpp2
-rw-r--r--lib/CodeGen/MachineModuleInfo.cpp12
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp14
-rw-r--r--lib/CodeGen/PrologEpilogInserter.h3
-rw-r--r--lib/CodeGen/SelectionDAG/SDDbgValue.h14
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp9
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp12
-rw-r--r--lib/CodeGen/TargetLoweringObjectFileImpl.cpp42
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp10
-rw-r--r--lib/MC/MCAsmInfo.cpp3
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp11
-rw-r--r--lib/MC/MCAssembler.cpp90
-rw-r--r--lib/MC/MCContext.cpp21
-rw-r--r--lib/MC/MCExpr.cpp5
-rw-r--r--lib/MC/MCNullStreamer.cpp6
-rw-r--r--lib/MC/MCParser/AsmParser.cpp8
-rw-r--r--lib/MC/MCStreamer.cpp5
-rw-r--r--lib/Support/APFloat.cpp2
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.h2
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp9
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.h2
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp2
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp5
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td87
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td25
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td14
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td48
-rw-r--r--lib/Target/ARM/ARMMCAsmInfo.cpp1
-rw-r--r--lib/Target/ARM/ARMSubtarget.cpp40
-rw-r--r--lib/Target/ARM/ARMSubtarget.h4
-rw-r--r--lib/Target/ARM/ARMTargetObjectFile.cpp54
-rw-r--r--lib/Target/ARM/ARMTargetObjectFile.h42
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp38
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp4
-rw-r--r--lib/Target/ARM/CMakeLists.txt1
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp12
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.h2
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.cpp28
-rw-r--r--lib/Target/Alpha/AlphaInstrInfo.td2
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.cpp2
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.h2
-rw-r--r--lib/Target/Blackfin/BlackfinRegisterInfo.cpp2
-rw-r--r--lib/Target/Blackfin/BlackfinRegisterInfo.h2
-rw-r--r--lib/Target/CellSPU/CellSDKIntrinsics.td1
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.td2
-rw-r--r--lib/Target/CellSPU/SPUMathInstr.td6
-rw-r--r--lib/Target/CellSPU/SPUNodes.td2
-rw-r--r--lib/Target/CellSPU/SPURegisterInfo.cpp3
-rw-r--r--lib/Target/CellSPU/SPURegisterInfo.h2
-rw-r--r--lib/Target/MBlaze/MBlazeCallingConv.td15
-rw-r--r--lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp8
-rw-r--r--lib/Target/MBlaze/MBlazeISelLowering.cpp166
-rw-r--r--lib/Target/MBlaze/MBlazeISelLowering.h3
-rw-r--r--lib/Target/MBlaze/MBlazeRegisterInfo.cpp59
-rw-r--r--lib/Target/MBlaze/MBlazeRegisterInfo.h8
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp23
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp23
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp4
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.cpp2
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.h2
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp2
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h2
-rw-r--r--lib/Target/PIC16/PIC16DebugInfo.cpp2
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.cpp2
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.h2
-rw-r--r--lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp8
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp10
-rw-r--r--lib/Target/PowerPC/PPCInstrAltivec.td14
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.cpp2
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.h2
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.cpp2
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.h2
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td3
-rw-r--r--lib/Target/SystemZ/SystemZOperands.td4
-rw-r--r--lib/Target/SystemZ/SystemZRegisterInfo.cpp2
-rw-r--r--lib/Target/SystemZ/SystemZRegisterInfo.h2
-rw-r--r--lib/Target/TargetLoweringObjectFile.cpp11
-rw-r--r--lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp8
-rw-r--r--lib/Target/X86/AsmPrinter/X86MCInstLower.cpp11
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp47
-rw-r--r--lib/Target/X86/X86ISelLowering.h13
-rw-r--r--lib/Target/X86/X86Instr64bit.td2
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp5
-rw-r--r--lib/Target/X86/X86InstrInfo.td70
-rw-r--r--lib/Target/X86/X86InstrMMX.td9
-rw-r--r--lib/Target/X86/X86InstrSSE.td20
-rw-r--r--lib/Target/X86/X86MCAsmInfo.cpp2
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp8
-rw-r--r--lib/Target/X86/X86RegisterInfo.h2
-rw-r--r--lib/Target/X86/X86TargetObjectFile.cpp9
-rw-r--r--lib/Target/XCore/XCoreISelDAGToDAG.cpp18
-rw-r--r--lib/Target/XCore/XCoreISelLowering.cpp282
-rw-r--r--lib/Target/XCore/XCoreISelLowering.h19
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.cpp2
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.h2
-rw-r--r--lib/Transforms/IPO/InlineAlways.cpp5
-rw-r--r--lib/Transforms/IPO/InlineSimple.cpp3
-rw-r--r--lib/Transforms/IPO/Inliner.cpp15
-rw-r--r--lib/Transforms/InstCombine/InstCombine.h1
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp141
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp134
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp6
-rw-r--r--lib/Transforms/Utils/LoopSimplify.cpp2
-rw-r--r--lib/VMCore/Metadata.cpp9
-rw-r--r--lib/VMCore/Verifier.cpp9
-rw-r--r--runtime/Makefile2
-rw-r--r--test/Analysis/ScalarEvolution/unreachable-code.ll13
-rw-r--r--test/CodeGen/ARM/armv4.ll13
-rw-r--r--test/CodeGen/ARM/indirectbr.ll4
-rw-r--r--test/CodeGen/MBlaze/cc.ll28
-rw-r--r--test/CodeGen/MSP430/AddrMode-bis-rx.ll4
-rw-r--r--test/CodeGen/MSP430/AddrMode-bis-xr.ll4
-rw-r--r--test/CodeGen/MSP430/AddrMode-mov-rx.ll4
-rw-r--r--test/CodeGen/MSP430/AddrMode-mov-xr.ll4
-rw-r--r--test/CodeGen/PowerPC/2010-03-09-indirect-call.ll19
-rw-r--r--test/CodeGen/PowerPC/indirectbr.ll12
-rw-r--r--test/CodeGen/Thumb/2009-08-20-ISelBug.ll2
-rw-r--r--test/CodeGen/Thumb2/2010-03-08-addi12-ccout.ll266
-rw-r--r--test/CodeGen/Thumb2/machine-licm.ll6
-rw-r--r--test/CodeGen/X86/2007-10-16-IllegalAsm.ll272
-rw-r--r--test/CodeGen/X86/2009-08-06-inlineasm.ll10
-rw-r--r--test/CodeGen/X86/aliases.ll4
-rw-r--r--test/CodeGen/X86/machine-cse.ll39
-rw-r--r--test/CodeGen/X86/pre-split6.ll2
-rw-r--r--test/CodeGen/X86/sibcall.ll (renamed from test/CodeGen/X86/tailcall2.ll)0
-rw-r--r--test/CodeGen/X86/stack-color-with-reg.ll3
-rw-r--r--test/CodeGen/XCore/addsub64.ll38
-rw-r--r--test/CodeGen/XCore/ladd_lsub_combine.ll67
-rw-r--r--test/CodeGen/XCore/mul64.ll39
-rw-r--r--test/FrontendC++/2010-02-17-DbgArtificialArg.cpp2
-rw-r--r--test/MC/AsmParser/X86/x86_32-new-encoder.s10
-rw-r--r--test/MC/Disassembler/simple-tests.txt11
-rw-r--r--test/MC/MachO/reloc-diff.s55
-rw-r--r--test/MC/MachO/reloc-pcrel.s62
-rw-r--r--test/MC/MachO/zerofill-4.s35
-rw-r--r--test/MC/MachO/zerofill-sect-align.s15
-rw-r--r--test/Transforms/InstCombine/memset_chk.ll (renamed from test/Transforms/SimplifyLibCalls/memset_chk.ll)2
-rw-r--r--test/Transforms/InstCombine/objsize.ll20
-rw-r--r--test/Transforms/InstCombine/strcpy_chk.ll (renamed from test/Transforms/SimplifyLibCalls/strcpy_chk.ll)2
-rw-r--r--test/Transforms/LCSSA/unreachable-use.ll27
-rw-r--r--test/lit.cfg3
-rw-r--r--tools/Makefile3
-rw-r--r--unittests/Makefile.unittest18
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp8
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp55
-rw-r--r--utils/TableGen/DAGISelMatcher.h44
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp14
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp132
-rw-r--r--utils/lit/lit/TestRunner.py18
-rw-r--r--utils/lit/lit/TestingConfig.py8
-rw-r--r--utils/unittest/UnitTestMain/Makefile6
-rw-r--r--utils/unittest/googletest/Makefile10
206 files changed, 3948 insertions, 2395 deletions
diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml
index 4e5de80..1cff422 100644
--- a/bindings/ocaml/Makefile.ocaml
+++ b/bindings/ocaml/Makefile.ocaml
@@ -66,35 +66,64 @@ Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \
Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o)
Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o)
+ifdef OCAMLOPT
+Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o)
+else
+Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o)
+endif
+
# Source files
OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml))
-OcamlHeaders1 := $(OcamlSources1:.ml=.mli)
+OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli))
+
+OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1))
+OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1))
-OcamlSources := $(OcamlSources1:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
-OcamlHeaders := $(OcamlHeaders1:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
+OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
+OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
# Intermediate files
-LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma
-LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa
ObjectsCMI := $(OcamlSources:%.ml=%.cmi)
ObjectsCMO := $(OcamlSources:%.ml=%.cmo)
ObjectsCMX := $(OcamlSources:%.ml=%.cmx)
+ifdef LIBRARYNAME
+LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma
+LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa
+endif
+
+ifdef TOOLNAME
+ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT)
+endif
+
# Output files
# The .cmo files are the only intermediates; all others are to be installed.
-LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a
-OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma)
-OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa)
OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi)
OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx)
OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%)
+ifdef LIBRARYNAME
+LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a
+OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma)
+OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa)
+endif
+
+ifdef TOOLNAME
+ifdef EXAMPLE_TOOL
+OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT)
+else
+OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT)
+endif
+endif
+
# Installation targets
+DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%)
+
+ifdef LIBRARYNAME
DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a
DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma
DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa
-DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%)
-
+endif
##===- Dependencies -------------------------------------------------------===##
# Copy the sources into the intermediate directory because older ocamlc doesn't
@@ -106,18 +135,27 @@ $(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir
$(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir
$(Verb) $(CP) -f $< $@
+$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi)
+
+ifdef LIBRARYNAME
$(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \
$(OcamlDir)/.dir $(ObjDir)/.dir
$(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@
-$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi)
-
-include $(ObjDir)/$(LIBRARYNAME).ocamldep
+endif
+
+ifdef TOOLNAME
+$(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \
+ $(OcamlDir)/.dir $(ObjDir)/.dir
+ $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@
+-include $(ObjDir)/$(TOOLNAME).ocamldep
+endif
##===- Build static library from C sources --------------------------------===##
-ifneq ($(ObjectsO),)
+ifdef LibraryA
all-local:: $(LibraryA)
clean-local:: clean-a
install-local:: install-a
@@ -160,7 +198,7 @@ $(OcamlDir)/%.o: $(LibDir)/%.o
$(Verb) ln -sf $< $@
clean-deplibs:
- $(Verb) rm -f $(OutputLibs)
+ $(Verb) $(RM) -f $(OutputLibs)
install-deplibs:
$(Verb) $(MKDIR) $(PROJ_libocamldir)
@@ -169,11 +207,12 @@ install-deplibs:
done
uninstall-deplibs:
- $(Verb) rm -f $(DestLibs)
+ $(Verb) $(RM) -f $(DestLibs)
##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===##
+ifneq ($(OcamlHeaders),)
all-local:: build-cmis
clean-local:: clean-cmis
install-local:: install-cmis
@@ -212,10 +251,16 @@ uninstall-cmis::
$(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \
$(RM) -f "$(PROJ_libocamldir)/$$i"; \
done
+endif
##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===##
+$(ObjDir)/%.cmo: $(ObjDir)/%.ml
+ $(Echo) "Compiling $(notdir $<) for $(BuildMode) build"
+ $(Verb) $(Compile.CMO) $@ $<
+
+ifdef LIBRARYNAME
all-local:: $(OutputCMA)
clean-local:: clean-cma
install-local:: install-cma
@@ -228,10 +273,6 @@ $(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
$(Verb) $(Archive.CMA) $@ $(ObjectsCMO)
-$(ObjDir)/%.cmo: $(ObjDir)/%.ml
- $(Echo) "Compiling $(notdir $<) for $(BuildMode) build"
- $(Verb) $(Compile.CMO) $@ $<
-
clean-cma::
$(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%)
@@ -243,7 +284,7 @@ install-cma:: $(OutputCMA)
uninstall-cma::
$(Echo) "Uninstalling $(DestCMA)"
-$(Verb) $(RM) -f $(DestCMA)
-
+endif
##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===##
@@ -251,6 +292,14 @@ uninstall-cma::
# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config.
ifdef OCAMLOPT
+$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx
+ $(Verb) $(CP) -f $< $@
+
+$(ObjDir)/%.cmx: $(ObjDir)/%.ml
+ $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build"
+ $(Verb) $(Compile.CMX) $@ $<
+
+ifdef LIBRARYNAME
all-local:: $(OutputCMXA) $(OutputsCMX)
clean-local:: clean-cmxa
install-local:: install-cmxa
@@ -260,18 +309,11 @@ $(OutputCMXA): $(LibraryCMXA)
$(Verb) $(CP) -f $< $@
$(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a)
-$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx
- $(Verb) $(CP) -f $< $@
-
$(LibraryCMXA): $(ObjectsCMX)
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
$(Verb) $(Archive.CMXA) $@ $(ObjectsCMX)
$(Verb) $(RM) -f $(@:.cmxa=.o)
-$(ObjDir)/%.cmx: $(ObjDir)/%.ml
- $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build"
- $(Verb) $(Compile.CMX) $@ $<
-
clean-cmxa::
$(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX)
@@ -295,7 +337,27 @@ uninstall-cmxa::
$(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \
$(RM) -f $(PROJ_libocamldir)/$$i; \
done
+endif
+endif
+
+##===- Build executables --------------------------------------------------===##
+
+ifdef TOOLNAME
+all-local:: $(OutputEXE)
+clean-local:: clean-exe
+
+$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir
+ $(Verb) $(CP) -f $< $@
+ifndef OCAMLOPT
+$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir
+ $(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
+ $(Verb) $(Archive.EXE) $@ $<
+else
+$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir
+ $(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
+ $(Verb) $(Archive.EXE) $@ $<
+endif
endif
##===- Generate documentation ---------------------------------------------===##
@@ -325,7 +387,10 @@ printcamlvars::
$(Echo) "LibraryCMA : " '$(LibraryCMA)'
$(Echo) "LibraryCMXA : " '$(LibraryCMXA)'
$(Echo) "OcamlSources1: " '$(OcamlSources1)'
+ $(Echo) "OcamlSources2: " '$(OcamlSources2)'
$(Echo) "OcamlSources : " '$(OcamlSources)'
+ $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)'
+ $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)'
$(Echo) "OcamlHeaders : " '$(OcamlHeaders)'
$(Echo) "ObjectsCMI : " '$(ObjectsCMI)'
$(Echo) "ObjectsCMO : " '$(ObjectsCMO)'
@@ -340,4 +405,6 @@ printcamlvars::
.PHONY: printcamlvars build-cmis \
clean-a clean-cmis clean-cma clean-cmxa \
install-a install-cmis install-cma install-cmxa \
- uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa
+ install-exe \
+ uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \
+ uninstall-exe
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index ad6222d..dcfe794 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -86,6 +86,7 @@
<li><a href="#targetimpls">Target-specific Implementation Notes</a>
<ul>
<li><a href="#tailcallopt">Tail call optimization</a></li>
+ <li><a href="#sibcallopt">Sibling call optimization</a></li>
<li><a href="#x86">The X86 backend</a></li>
<li><a href="#ppc">The PowerPC backend</a>
<ul>
@@ -1734,6 +1735,50 @@ define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
</div>
<!-- ======================================================================= -->
<div class="doc_subsection">
+ <a name="sibcallopt">Sibling call optimization</a>
+</div>
+
+<div class="doc_text">
+
+<p>Sibling call optimization is a restricted form of tail call optimization.
+ Unlike tail call optimization described in the previous section, it can be
+ performed automatically on any tail calls when <tt>-tailcallopt</tt> option
+ is not specified.</p>
+
+<p>Sibling call optimization is currently performed on x86/x86-64 when the
+ following constraints are met:</p>
+
+<ul>
+ <li>Caller and callee have the same calling convention. It can be either
+ <tt>c</tt> or <tt>fastcc</tt>.
+
+ <li>The call is a tail call - in tail position (ret immediately follows call
+ and ret uses value of call or is void).</li>
+
+ <li>Caller and callee have matching return type or the callee result is not
+ used.
+
+ <li>If any of the callee arguments are being passed in stack, they must be
+ available in caller's own incoming argument stack and the frame offsets
+ must be the same.
+</ul>
+
+<p>Example:</p>
+<div class="doc_code">
+<pre>
+declare i32 @bar(i32, i32)
+
+define i32 @foo(i32 %a, i32 %b, i32 %c) {
+entry:
+ %0 = tail call i32 @bar(i32 %a, i32 %b)
+ ret i32 %0
+}
+</pre>
+</div>
+
+</div>
+<!-- ======================================================================= -->
+<div class="doc_subsection">
<a name="x86">The X86 backend</a>
</div>
@@ -2116,7 +2161,7 @@ MOVSX32rm16 -&gt; movsx, 32-bit register, 16-bit memory
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
+ Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
diff --git a/docs/LangRef.html b/docs/LangRef.html
index f7ecb76..f1abdb5 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -5149,8 +5149,11 @@ Loop: ; Infinite loop that counts from 0 on up...
a <a href="#i_ret"><tt>ret</tt></a> instruction. If the "tail" marker is
present, the function call is eligible for tail call optimization,
but <a href="CodeGenerator.html#tailcallopt">might not in fact be
- optimized into a jump</a>. As of this writing, the extra requirements for
- a call to actually be optimized are:
+ optimized into a jump</a>. The code generator may optimize calls marked
+ "tail" with either 1) automatic <a href="CodeGenerator.html#sibcallopt">
+ sibling call optimization</a> when the caller and callee have
+ matching signatures, or 2) forced tail call optimization when the
+ following extra requirements are met:
<ul>
<li>Caller and callee both have the calling
convention <tt>fastcc</tt>.</li>
@@ -7470,7 +7473,7 @@ LLVM</a>.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-03-05 00:44:48 +0100 (Fri, 05 Mar 2010) $
+ Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html
index 83c979b..9af8fab 100644
--- a/docs/SourceLevelDebugging.html
+++ b/docs/SourceLevelDebugging.html
@@ -25,6 +25,7 @@
<li><a href="#debug_info_descriptors">Debug information descriptors</a>
<ul>
<li><a href="#format_compile_units">Compile unit descriptors</a></li>
+ <li><a href="#format_files">File descriptors</a></li>
<li><a href="#format_global_variables">Global variable descriptors</a></li>
<li><a href="#format_subprograms">Subprogram descriptors</a></li>
<li><a href="#format_blocks">Block descriptors</a></li>
@@ -255,7 +256,7 @@ height="369">
<p>To provide basic functionality, the LLVM debugger does have to make some
assumptions about the source-level language being debugged, though it keeps
these to a minimum. The only common features that the LLVM debugger assumes
- exist are <a href="#format_compile_units">source files</a>,
+ exist are <a href="#format_files">source files</a>,
and <a href="#format_global_variables">program objects</a>. These abstract
objects are used by a debugger to form stack traces, show information about
local variables, etc.</p>
@@ -307,8 +308,8 @@ height="369">
of tags are loosely bound to the tag values of DWARF information entries.
However, that does not restrict the use of the information supplied to DWARF
targets. To facilitate versioning of debug information, the tag is augmented
- with the current debug version (LLVMDebugVersion = 7 << 16 or 0x70000 or
- 458752.)</a></p>
+ with the current debug version (LLVMDebugVersion = 8 << 16 or 0x80000 or
+ 524288.)</a></p>
<p>The details of the various descriptors follow.</p>
@@ -346,18 +347,36 @@ height="369">
that produced it.</p>
<p>Compile unit descriptors provide the root context for objects declared in a
- specific source file. Global variables and top level functions would be
- defined using this context. Compile unit descriptors also provide context
- for source line correspondence.</p>
+ specific compilation unit. File descriptors are defined using this context.</p>
-<p>Each input file is encoded as a separate compile unit in LLVM debugging
- information output. However, many target specific tool chains prefer to
- encode only one compile unit in an object file. In this situation, the LLVM
- code generator will include debugging information entities in the compile
- unit that is marked as main compile unit. The code generator accepts maximum
- one main compile unit per module. If a module does not contain any main
- compile unit then the code generator will emit multiple compile units in the
- output object file.</p>
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection">
+ <a name="format_files">File descriptors</a>
+</div>
+
+<div class="doc_text">
+
+<div class="doc_code">
+<pre>
+!0 = metadata !{
+ i32, ;; Tag = 41 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a>
+ ;; (DW_TAG_file_type)
+ metadata, ;; Source file name
+ metadata, ;; Source file directory (includes trailing slash)
+ metadata ;; Reference to compile unit where defined
+}
+</pre>
+</div>
+
+<p>These descriptors contain informations for a file. Global variables and top
+ level functions would be defined using this context.k File descriptors also
+ provide context for source line correspondence. </p>
+
+<p>Each input file is encoded as a separate file descriptor in LLVM debugging
+ information output. Each file descriptor would be defined using a
+ compile unit. </p>
</div>
@@ -378,7 +397,7 @@ height="369">
metadata, ;; Name
metadata, ;; Display name (fully qualified C++ name)
metadata, ;; MIPS linkage name (for C++)
- metadata, ;; Reference to compile unit where defined
+ metadata, ;; Reference to file where defined
i32, ;; Line number where defined
metadata, ;; Reference to type descriptor
i1, ;; True if the global is local to compile unit (static)
@@ -410,7 +429,7 @@ provide details such as name, type and where the variable is defined.</p>
metadata, ;; Name
metadata, ;; Display name (fully qualified C++ name)
metadata, ;; MIPS linkage name (for C++)
- metadata, ;; Reference to compile unit where defined
+ metadata, ;; Reference to file where defined
i32, ;; Line number where defined
metadata, ;; Reference to type descriptor
i1, ;; True if the global is local to compile unit (static)
@@ -461,7 +480,7 @@ provide details such as name, type and where the variable is defined.</p>
;; (DW_TAG_base_type)
metadata, ;; Reference to context (typically a compile unit)
metadata, ;; Name (may be "" for anonymous types)
- metadata, ;; Reference to compile unit where defined (may be NULL)
+ metadata, ;; Reference to file where defined (may be NULL)
i32, ;; Line number where defined (may be 0)
i64, ;; Size in bits
i64, ;; Alignment in bits
@@ -512,7 +531,7 @@ DW_ATE_unsigned_char = 8
i32, ;; Tag (see below)
metadata, ;; Reference to context
metadata, ;; Name (may be "" for anonymous types)
- metadata, ;; Reference to compile unit where defined (may be NULL)
+ metadata, ;; Reference to file where defined (may be NULL)
i32, ;; Line number where defined (may be 0)
i32, ;; Size in bits
i32, ;; Alignment in bits
@@ -580,7 +599,7 @@ DW_TAG_restrict_type = 55
i32, ;; Tag (see below)
metadata, ;; Reference to context
metadata, ;; Name (may be "" for anonymous types)
- metadata, ;; Reference to compile unit where defined (may be NULL)
+ metadata, ;; Reference to file where defined (may be NULL)
i32, ;; Line number where defined (may be 0)
i64, ;; Size in bits
i64, ;; Alignment in bits
@@ -715,7 +734,7 @@ DW_TAG_inheritance = 28
i32, ;; Tag (see below)
metadata, ;; Context
metadata, ;; Name
- metadata, ;; Reference to compile unit where defined
+ metadata, ;; Reference to file where defined
i32, ;; Line number where defined
metadata ;; Type descriptor
}
@@ -1012,10 +1031,10 @@ int main(int argc, char *argv[]) {
<pre>
...
;;
-;; Define the compile unit for the source file "/Users/mine/sources/MySource.cpp".
+;; Define the compile unit for the main source file "/Users/mine/sources/MySource.cpp".
;;
-!3 = metadata !{
- i32 458769, ;; Tag
+!2 = metadata !{
+ i32 524305, ;; Tag
i32 0, ;; Unused
i32 4, ;; Language Id
metadata !"MySource.cpp",
@@ -1027,19 +1046,24 @@ int main(int argc, char *argv[]) {
i32 0} ;; Runtime version
;;
-;; Define the compile unit for the header file "/Users/mine/sources/MyHeader.h".
+;; Define the file for the file "/Users/mine/sources/MySource.cpp".
;;
!1 = metadata !{
- i32 458769, ;; Tag
- i32 0, ;; Unused
- i32 4, ;; Language Id
- metadata !"MyHeader.h",
+ i32 524329, ;; Tag
+ metadata !"MySource.cpp",
metadata !"/Users/mine/sources",
- metadata !"4.2.1 (Based on Apple Inc. build 5649) (LLVM build 00)",
- i1 false, ;; Main Compile Unit
- i1 false, ;; Optimized compile unit
- metadata !"", ;; Compiler flags
- i32 0} ;; Runtime version
+ metadata !3 ;; Compile unit
+}
+
+;;
+;; Define the file for the file "/Users/mine/sources/Myheader.h"
+;;
+!3 = metadata !{
+ i32 524329, ;; Tag
+ metadata !"Myheader.h"
+ metadata !"/Users/mine/sources",
+ metadata !3 ;; Compile unit
+}
...
</pre>
@@ -1081,15 +1105,15 @@ int MyGlobal = 100;
;; variable anchor and the global variable itself.
;;
!0 = metadata !{
- i32 458804, ;; Tag
+ i32 524340, ;; Tag
i32 0, ;; Unused
metadata !1, ;; Context
metadata !"MyGlobal", ;; Name
metadata !"MyGlobal", ;; Display Name
metadata !"MyGlobal", ;; Linkage Name
- metadata !1, ;; Compile Unit
+ metadata !3, ;; Compile Unit
i32 1, ;; Line Number
- metadata !2, ;; Type
+ metadata !4, ;; Type
i1 false, ;; Is a local variable
i1 true, ;; Is this a definition
i32* @MyGlobal ;; The global variable
@@ -1099,11 +1123,11 @@ int MyGlobal = 100;
;; Define the basic type of 32 bit signed integer. Note that since int is an
;; intrinsic type the source file is NULL and line 0.
;;
-!2 = metadata !{
- i32 458788, ;; Tag
+!4 = metadata !{
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"int", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in Bits
i64 32, ;; Align in Bits
@@ -1143,16 +1167,16 @@ int main(int argc, char *argv[]) {
;; anchor is 46, which is the same as the tag for subprograms
;; (46 = DW_TAG_subprogram.)
;;
-!0 = metadata !{
- i32 458798, ;; Tag
+!6 = metadata !{
+ i32 524334, ;; Tag
i32 0, ;; Unused
metadata !1, ;; Context
metadata !"main", ;; Name
metadata !"main", ;; Display name
metadata !"main", ;; Linkage name
- metadata !1, ;; Compile unit
+ metadata !1, ;; File
i32 1, ;; Line number
- metadata !2, ;; Type
+ metadata !4, ;; Type
i1 false, ;; Is local
i1 true ;; Is definition
}
@@ -1188,10 +1212,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"bool", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 8, ;; Size in Bits
i64 8, ;; Align in Bits
@@ -1214,10 +1238,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"char", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 8, ;; Size in Bits
i64 8, ;; Align in Bits
@@ -1240,10 +1264,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"unsigned char",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 8, ;; Size in Bits
i64 8, ;; Align in Bits
@@ -1266,10 +1290,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"short int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 16, ;; Size in Bits
i64 16, ;; Align in Bits
@@ -1292,10 +1316,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"short unsigned int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 16, ;; Size in Bits
i64 16, ;; Align in Bits
@@ -1318,10 +1342,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"int", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in Bits
i64 32, ;; Align in Bits
@@ -1343,10 +1367,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"unsigned int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in Bits
i64 32, ;; Align in Bits
@@ -1369,10 +1393,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"long long int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 64, ;; Size in Bits
i64 64, ;; Align in Bits
@@ -1395,10 +1419,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"long long unsigned int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 64, ;; Size in Bits
i64 64, ;; Align in Bits
@@ -1421,10 +1445,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"float",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in Bits
i64 32, ;; Align in Bits
@@ -1447,10 +1471,10 @@ define i32 @main(i32 %argc, i8** %argv) {
<div class="doc_code">
<pre>
!2 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"double",;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 64, ;; Size in Bits
i64 64, ;; Align in Bits
@@ -1486,10 +1510,10 @@ typedef const int *IntPtr;
;; Define the typedef "IntPtr".
;;
!2 = metadata !{
- i32 458774, ;; Tag
+ i32 524310, ;; Tag
metadata !1, ;; Context
metadata !"IntPtr", ;; Name
- metadata !3, ;; Compile unit
+ metadata !3, ;; File
i32 0, ;; Line number
i64 0, ;; Size in bits
i64 0, ;; Align in bits
@@ -1502,10 +1526,10 @@ typedef const int *IntPtr;
;; Define the pointer type.
;;
!4 = metadata !{
- i32 458767, ;; Tag
+ i32 524303, ;; Tag
metadata !1, ;; Context
metadata !"", ;; Name
- metadata !1, ;; Compile unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 64, ;; Size in bits
i64 64, ;; Align in bits
@@ -1517,10 +1541,10 @@ typedef const int *IntPtr;
;; Define the const type.
;;
!5 = metadata !{
- i32 458790, ;; Tag
+ i32 524326, ;; Tag
metadata !1, ;; Context
metadata !"", ;; Name
- metadata !1, ;; Compile unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1532,10 +1556,10 @@ typedef const int *IntPtr;
;; Define the int type.
;;
!6 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"int", ;; Name
- metadata !1, ;; Compile unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1575,10 +1599,10 @@ struct Color {
;; Define basic type for unsigned int.
;;
!5 = metadata !{
- i32 458788, ;; Tag
+ i32 524324, ;; Tag
metadata !1, ;; Context
metadata !"unsigned int",
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 0, ;; Line number
i64 32, ;; Size in Bits
i64 32, ;; Align in Bits
@@ -1590,7 +1614,7 @@ struct Color {
;; Define composite type for struct Color.
;;
!2 = metadata !{
- i32 458771, ;; Tag
+ i32 524307, ;; Tag
metadata !1, ;; Context
metadata !"Color", ;; Name
metadata !1, ;; Compile unit
@@ -1608,10 +1632,10 @@ struct Color {
;; Define the Red field.
;;
!4 = metadata !{
- i32 458765, ;; Tag
+ i32 524301, ;; Tag
metadata !1, ;; Context
metadata !"Red", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 2, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1624,10 +1648,10 @@ struct Color {
;; Define the Green field.
;;
!6 = metadata !{
- i32 458765, ;; Tag
+ i32 524301, ;; Tag
metadata !1, ;; Context
metadata !"Green", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 3, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1640,10 +1664,10 @@ struct Color {
;; Define the Blue field.
;;
!7 = metadata !{
- i32 458765, ;; Tag
+ i32 524301, ;; Tag
metadata !1, ;; Context
metadata !"Blue", ;; Name
- metadata !1, ;; Compile Unit
+ metadata !1, ;; File
i32 4, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1688,10 +1712,10 @@ enum Trees {
;; Define composite type for enum Trees
;;
!2 = metadata !{
- i32 458756, ;; Tag
+ i32 524292, ;; Tag
metadata !1, ;; Context
metadata !"Trees", ;; Name
- metadata !1, ;; Compile unit
+ metadata !1, ;; File
i32 1, ;; Line number
i64 32, ;; Size in bits
i64 32, ;; Align in bits
@@ -1710,17 +1734,17 @@ enum Trees {
;;
;; Define Spruce enumerator.
;;
-!4 = metadata !{i32 458792, metadata !"Spruce", i64 100}
+!4 = metadata !{i32 524328, metadata !"Spruce", i64 100}
;;
;; Define Oak enumerator.
;;
-!5 = metadata !{i32 458792, metadata !"Oak", i64 200}
+!5 = metadata !{i32 524328, metadata !"Oak", i64 200}
;;
;; Define Maple enumerator.
;;
-!6 = metadata !{i32 458792, metadata !"Maple", i64 300}
+!6 = metadata !{i32 524328, metadata !"Maple", i64 300}
</pre>
</div>
@@ -1738,7 +1762,7 @@ enum Trees {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-01-11 23:53:48 +0100 (Mon, 11 Jan 2010) $
+ Last modified: $Date: 2010-03-09 01:44:10 +0100 (Tue, 09 Mar 2010) $
</address>
</body>
diff --git a/docs/WritingAnLLVMPass.html b/docs/WritingAnLLVMPass.html
index d18181e..7618657 100644
--- a/docs/WritingAnLLVMPass.html
+++ b/docs/WritingAnLLVMPass.html
@@ -909,16 +909,22 @@ finalization.</p>
<p>A <tt>MachineFunctionPass</tt> is a part of the LLVM code generator that
executes on the machine-dependent representation of each LLVM function in the
-program. A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
+program.</p>
+
+<p>Code generator passes are registered and initialized specially by
+<tt>TargetMachine::addPassesToEmitFile</tt> and similar routines, so they
+cannot generally be run from the <tt>opt</tt> or <tt>bugpoint</tt>
+commands.</p>
+
+<p>A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
the restrictions that apply to a <tt>FunctionPass</tt> also apply to it.
<tt>MachineFunctionPass</tt>es also have additional restrictions. In particular,
<tt>MachineFunctionPass</tt>es are not allowed to do any of the following:</p>
<ol>
-<li>Modify any LLVM Instructions, BasicBlocks or Functions.</li>
+<li>Modify or create any LLVM IR Instructions, BasicBlocks, Arguments,
+ Functions, GlobalVariables, GlobalAliases, or Modules.</li>
<li>Modify a MachineFunction other than the one currently being processed.</li>
-<li>Add or remove MachineFunctions from the current Module.</li>
-<li>Add or remove global variables from the current Module.</li>
<li>Maintain state across invocations of <a
href="#runOnMachineFunction"><tt>runOnMachineFunction</tt></a> (including global
data)</li>
@@ -1829,7 +1835,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-02-18 15:37:52 +0100 (Thu, 18 Feb 2010) $
+ Last modified: $Date: 2010-03-10 02:29:39 +0100 (Wed, 10 Mar 2010) $
</address>
</body>
diff --git a/docs/tutorial/OCamlLangImpl3.html b/docs/tutorial/OCamlLangImpl3.html
index c69f644..01fe62f 100644
--- a/docs/tutorial/OCamlLangImpl3.html
+++ b/docs/tutorial/OCamlLangImpl3.html
@@ -98,6 +98,7 @@ exception Error of string
let the_module = create_module (global_context ()) "my cool jit"
let builder = builder (global_context ())
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
</pre>
</div>
@@ -389,7 +390,7 @@ that there is an LLVM Function object that is ready to go for us.</p>
<div class="doc_code">
<pre>
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -903,6 +904,7 @@ let context = global_context ()
let the_module = create_module context "my cool jit"
let builder = builder context
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
let rec codegen_expr = function
| Ast.Number n -&gt; const_float double_type n
@@ -974,7 +976,7 @@ let codegen_func = function
let the_function = codegen_proto proto in
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -1085,7 +1087,7 @@ main ()
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
+ Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
</html>
diff --git a/docs/tutorial/OCamlLangImpl4.html b/docs/tutorial/OCamlLangImpl4.html
index 4a72f65..6d9a6c6 100644
--- a/docs/tutorial/OCamlLangImpl4.html
+++ b/docs/tutorial/OCamlLangImpl4.html
@@ -186,9 +186,8 @@ add a set of optimizations to run. The code looks like this:</p>
<div class="doc_code">
<pre>
(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
@@ -213,18 +212,11 @@ add a set of optimizations to run. The code looks like this:</p>
</pre>
</div>
-<p>This code defines two values, an <tt>Llvm.llmoduleprovider</tt> and a
-<tt>Llvm.PassManager.t</tt>. The former is basically a wrapper around our
-<tt>Llvm.llmodule</tt> that the <tt>Llvm.PassManager.t</tt> requires. It
-provides certain flexibility that we're not going to take advantage of here,
-so I won't dive into any details about it.</p>
-
<p>The meat of the matter here, is the definition of "<tt>the_fpm</tt>". It
-requires a pointer to the <tt>the_module</tt> (through the
-<tt>the_module_provider</tt>) to construct itself. Once it is set up, we use a
-series of "add" calls to add a bunch of LLVM passes. The first pass is
-basically boilerplate, it adds a pass so that later optimizations know how the
-data structures in the program are laid out. The
+requires a pointer to the <tt>the_module</tt> to construct itself. Once it is
+set up, we use a series of "add" calls to add a bunch of LLVM passes. The
+first pass is basically boilerplate, it adds a pass so that later optimizations
+know how the data structures in the program are laid out. The
"<tt>the_execution_engine</tt>" variable is related to the JIT, which we will
get to in the next section.</p>
@@ -320,8 +312,7 @@ by adding a global variable and a call in <tt>main</tt>:</p>
let main () =
...
<b>(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in</b>
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in</b>
...
</pre>
</div>
@@ -351,7 +342,7 @@ can change the code that parses a top-level expression to look like this:</p>
the_execution_engine in
print_string "Evaluated to ";
- print_float (GenericValue.as_float double_type result);
+ print_float (GenericValue.as_float Codegen.double_type result);
print_newline ();
</pre>
</div>
@@ -796,6 +787,7 @@ let context = global_context ()
let the_module = create_module context "my cool jit"
let builder = builder context
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
let rec codegen_expr = function
| Ast.Number n -&gt; const_float double_type n
@@ -867,7 +859,7 @@ let codegen_func the_fpm = function
let the_function = codegen_proto proto in
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -932,7 +924,7 @@ let rec main_loop the_fpm the_execution_engine stream =
the_execution_engine in
print_string "Evaluated to ";
- print_float (GenericValue.as_float double_type result);
+ print_float (GenericValue.as_float Codegen.double_type result);
print_newline ();
with Stream.Error s | Codegen.Error s -&gt;
(* Skip token for error recovery. *)
@@ -971,16 +963,15 @@ let main () =
let stream = Lexer.lex (Stream.of_channel stdin) in
(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
- add_instruction_combining the_fpm;
+ add_instruction_combination the_fpm;
(* reassociate expressions. *)
add_reassociation the_fpm;
@@ -1032,7 +1023,7 @@ extern double putchard(double X) {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
+ Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
</html>
diff --git a/docs/tutorial/OCamlLangImpl5.html b/docs/tutorial/OCamlLangImpl5.html
index 14f0efd..b0440ac 100644
--- a/docs/tutorial/OCamlLangImpl5.html
+++ b/docs/tutorial/OCamlLangImpl5.html
@@ -364,7 +364,7 @@ value as a 1-bit (bool) value.</p>
let start_bb = insertion_block builder in
let the_function = block_parent start_bb in
- let then_bb = append_block "then" the_function in
+ let then_bb = append_block context "then" the_function in
position_at_end then_bb builder;
</pre>
</div>
@@ -417,7 +417,7 @@ up-to-date value for code that will set up the Phi node.</p>
<div class="doc_code">
<pre>
(* Emit 'else' value. *)
- let else_bb = append_block "else" the_function in
+ let else_bb = append_block context "else" the_function in
position_at_end else_bb builder;
let else_val = codegen_expr else_ in
@@ -433,7 +433,7 @@ the 'then' block.</p>
<div class="doc_code">
<pre>
(* Emit merge block. *)
- let merge_bb = append_block "ifcont" the_function in
+ let merge_bb = append_block context "ifcont" the_function in
position_at_end merge_bb builder;
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
let phi = build_phi incoming "iftmp" builder in
@@ -704,7 +704,7 @@ block, but remember that the body code itself could consist of multiple blocks
* block. *)
let preheader_bb = insertion_block builder in
let the_function = block_parent preheader_bb in
- let loop_bb = append_block "loop" the_function in
+ let loop_bb = append_block context "loop" the_function in
(* Insert an explicit fall through from the current block to the
* loop_bb. *)
@@ -804,7 +804,7 @@ statement.</p>
<pre>
(* Create the "after loop" block and insert it. *)
let loop_end_bb = insertion_block builder in
- let after_bb = append_block "afterloop" the_function in
+ let after_bb = append_block context "afterloop" the_function in
(* Insert the conditional branch into the end of loop_end_bb. *)
ignore (build_cond_br end_cond loop_bb after_bb builder);
@@ -1204,6 +1204,7 @@ let context = global_context ()
let the_module = create_module context "my cool jit"
let builder = builder context
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
let rec codegen_expr = function
| Ast.Number n -&gt; const_float double_type n
@@ -1250,7 +1251,7 @@ let rec codegen_expr = function
let start_bb = insertion_block builder in
let the_function = block_parent start_bb in
- let then_bb = append_block "then" the_function in
+ let then_bb = append_block context "then" the_function in
(* Emit 'then' value. *)
position_at_end then_bb builder;
@@ -1262,7 +1263,7 @@ let rec codegen_expr = function
let new_then_bb = insertion_block builder in
(* Emit 'else' value. *)
- let else_bb = append_block "else" the_function in
+ let else_bb = append_block context "else" the_function in
position_at_end else_bb builder;
let else_val = codegen_expr else_ in
@@ -1271,7 +1272,7 @@ let rec codegen_expr = function
let new_else_bb = insertion_block builder in
(* Emit merge block. *)
- let merge_bb = append_block "ifcont" the_function in
+ let merge_bb = append_block context "ifcont" the_function in
position_at_end merge_bb builder;
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
let phi = build_phi incoming "iftmp" builder in
@@ -1297,7 +1298,7 @@ let rec codegen_expr = function
* block. *)
let preheader_bb = insertion_block builder in
let the_function = block_parent preheader_bb in
- let loop_bb = append_block "loop" the_function in
+ let loop_bb = append_block context "loop" the_function in
(* Insert an explicit fall through from the current block to the
* loop_bb. *)
@@ -1341,7 +1342,7 @@ let rec codegen_expr = function
(* Create the "after loop" block and insert it. *)
let loop_end_bb = insertion_block builder in
- let after_bb = append_block "afterloop" the_function in
+ let after_bb = append_block context "afterloop" the_function in
(* Insert the conditional branch into the end of loop_end_bb. *)
ignore (build_cond_br end_cond loop_bb after_bb builder);
@@ -1397,7 +1398,7 @@ let codegen_func the_fpm = function
let the_function = codegen_proto proto in
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -1462,7 +1463,7 @@ let rec main_loop the_fpm the_execution_engine stream =
the_execution_engine in
print_string "Evaluated to ";
- print_float (GenericValue.as_float double_type result);
+ print_float (GenericValue.as_float Codegen.double_type result);
print_newline ();
with Stream.Error s | Codegen.Error s -&gt;
(* Skip token for error recovery. *)
@@ -1501,16 +1502,15 @@ let main () =
let stream = Lexer.lex (Stream.of_channel stdin) in
(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
- add_instruction_combining the_fpm;
+ add_instruction_combination the_fpm;
(* reassociate expressions. *)
add_reassociation the_fpm;
@@ -1563,7 +1563,7 @@ operators</a>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
+ Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
</html>
diff --git a/docs/tutorial/OCamlLangImpl6.html b/docs/tutorial/OCamlLangImpl6.html
index e0503c0..de70698 100644
--- a/docs/tutorial/OCamlLangImpl6.html
+++ b/docs/tutorial/OCamlLangImpl6.html
@@ -300,7 +300,7 @@ let codegen_func the_fpm = function
end;</b>
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
...
</pre>
@@ -1177,6 +1177,7 @@ let context = global_context ()
let the_module = create_module context "my cool jit"
let builder = builder context
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
let rec codegen_expr = function
| Ast.Number n -&gt; const_float double_type n
@@ -1241,7 +1242,7 @@ let rec codegen_expr = function
let start_bb = insertion_block builder in
let the_function = block_parent start_bb in
- let then_bb = append_block "then" the_function in
+ let then_bb = append_block context "then" the_function in
(* Emit 'then' value. *)
position_at_end then_bb builder;
@@ -1253,7 +1254,7 @@ let rec codegen_expr = function
let new_then_bb = insertion_block builder in
(* Emit 'else' value. *)
- let else_bb = append_block "else" the_function in
+ let else_bb = append_block context "else" the_function in
position_at_end else_bb builder;
let else_val = codegen_expr else_ in
@@ -1262,7 +1263,7 @@ let rec codegen_expr = function
let new_else_bb = insertion_block builder in
(* Emit merge block. *)
- let merge_bb = append_block "ifcont" the_function in
+ let merge_bb = append_block context "ifcont" the_function in
position_at_end merge_bb builder;
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
let phi = build_phi incoming "iftmp" builder in
@@ -1288,7 +1289,7 @@ let rec codegen_expr = function
* block. *)
let preheader_bb = insertion_block builder in
let the_function = block_parent preheader_bb in
- let loop_bb = append_block "loop" the_function in
+ let loop_bb = append_block context "loop" the_function in
(* Insert an explicit fall through from the current block to the
* loop_bb. *)
@@ -1332,7 +1333,7 @@ let rec codegen_expr = function
(* Create the "after loop" block and insert it. *)
let loop_end_bb = insertion_block builder in
- let after_bb = append_block "afterloop" the_function in
+ let after_bb = append_block context "afterloop" the_function in
(* Insert the conditional branch into the end of loop_end_bb. *)
ignore (build_cond_br end_cond loop_bb after_bb builder);
@@ -1396,7 +1397,7 @@ let codegen_func the_fpm = function
end;
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -1461,7 +1462,7 @@ let rec main_loop the_fpm the_execution_engine stream =
the_execution_engine in
print_string "Evaluated to ";
- print_float (GenericValue.as_float double_type result);
+ print_float (GenericValue.as_float Codegen.double_type result);
print_newline ();
with Stream.Error s | Codegen.Error s -&gt;
(* Skip token for error recovery. *)
@@ -1500,16 +1501,15 @@ let main () =
let stream = Lexer.lex (Stream.of_channel stdin) in
(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
- add_instruction_combining the_fpm;
+ add_instruction_combination the_fpm;
(* reassociate expressions. *)
add_reassociation the_fpm;
@@ -1568,7 +1568,7 @@ SSA construction</a>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2010-02-03 18:27:31 +0100 (Wed, 03 Feb 2010) $
+ Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
</html>
diff --git a/docs/tutorial/OCamlLangImpl7.html b/docs/tutorial/OCamlLangImpl7.html
index 823b4c0..d4b7c9b 100644
--- a/docs/tutorial/OCamlLangImpl7.html
+++ b/docs/tutorial/OCamlLangImpl7.html
@@ -543,7 +543,7 @@ good codegen once again:</p>
<pre>
let main () =
...
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
@@ -1388,6 +1388,7 @@ let context = global_context ()
let the_module = create_module context "my cool jit"
let builder = builder context
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
(* Create an alloca instruction in the entry block of the function. This
* is used for mutable variables etc. *)
@@ -1482,7 +1483,7 @@ let rec codegen_expr = function
let start_bb = insertion_block builder in
let the_function = block_parent start_bb in
- let then_bb = append_block "then" the_function in
+ let then_bb = append_block context "then" the_function in
(* Emit 'then' value. *)
position_at_end then_bb builder;
@@ -1494,7 +1495,7 @@ let rec codegen_expr = function
let new_then_bb = insertion_block builder in
(* Emit 'else' value. *)
- let else_bb = append_block "else" the_function in
+ let else_bb = append_block context "else" the_function in
position_at_end else_bb builder;
let else_val = codegen_expr else_ in
@@ -1503,7 +1504,7 @@ let rec codegen_expr = function
let new_else_bb = insertion_block builder in
(* Emit merge block. *)
- let merge_bb = append_block "ifcont" the_function in
+ let merge_bb = append_block context "ifcont" the_function in
position_at_end merge_bb builder;
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
let phi = build_phi incoming "iftmp" builder in
@@ -1555,7 +1556,7 @@ let rec codegen_expr = function
(* Make the new basic block for the loop header, inserting after current
* block. *)
- let loop_bb = append_block "loop" the_function in
+ let loop_bb = append_block context "loop" the_function in
(* Insert an explicit fall through from the current block to the
* loop_bb. *)
@@ -1599,7 +1600,7 @@ let rec codegen_expr = function
let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
(* Create the "after loop" block and insert it. *)
- let after_bb = append_block "afterloop" the_function in
+ let after_bb = append_block context "afterloop" the_function in
(* Insert the conditional branch into the end of loop_end_bb. *)
ignore (build_cond_br end_cond loop_bb after_bb builder);
@@ -1723,7 +1724,7 @@ let codegen_func the_fpm = function
end;
(* Create a new basic block to start insertion into. *)
- let bb = append_block "entry" the_function in
+ let bb = append_block context "entry" the_function in
position_at_end bb builder;
try
@@ -1791,7 +1792,7 @@ let rec main_loop the_fpm the_execution_engine stream =
the_execution_engine in
print_string "Evaluated to ";
- print_float (GenericValue.as_float double_type result);
+ print_float (GenericValue.as_float Codegen.double_type result);
print_newline ();
with Stream.Error s | Codegen.Error s -&gt;
(* Skip token for error recovery. *)
@@ -1831,9 +1832,8 @@ let main () =
let stream = Lexer.lex (Stream.of_channel stdin) in
(* Create the JIT. *)
- let the_module_provider = ModuleProvider.create Codegen.the_module in
- let the_execution_engine = ExecutionEngine.create the_module_provider in
- let the_fpm = PassManager.create_function the_module_provider in
+ let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+ let the_fpm = PassManager.create_function Codegen.the_module in
(* Set up the optimizer pipeline. Start with registering info about how the
* target lays out data structures. *)
@@ -1843,7 +1843,7 @@ let main () =
add_memory_to_register_promotion the_fpm;
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
- add_instruction_combining the_fpm;
+ add_instruction_combination the_fpm;
(* reassociate expressions. *)
add_reassociation the_fpm;
@@ -1901,7 +1901,7 @@ extern double printd(double X) {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
- Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
+ Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
</address>
</body>
</html>
diff --git a/examples/Makefile b/examples/Makefile
index 0737eaf..5594c05 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -25,4 +25,8 @@ ifeq ($(LLVM_ON_UNIX),1)
endif
endif
+ifeq ($(filter $(BINDINGS_TO_BUILD),ocaml),ocaml)
+ PARALLEL_DIRS += OCaml-Kaleidoscope
+endif
+
include $(LEVEL)/Makefile.common
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 861b7b9..3cccc81 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -344,7 +344,7 @@ namespace llvm {
/// 1.01E-2 4 1 1.01E-2
void toString(SmallVectorImpl<char> &Str,
unsigned FormatPrecision = 0,
- unsigned FormatMaxPadding = 3);
+ unsigned FormatMaxPadding = 3) const;
private:
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 7350906..393473bd 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -192,6 +192,13 @@ public:
return true;
}
+ void swap(DenseMap& RHS) {
+ std::swap(NumBuckets, RHS.NumBuckets);
+ std::swap(Buckets, RHS.Buckets);
+ std::swap(NumEntries, RHS.NumEntries);
+ std::swap(NumTombstones, RHS.NumTombstones);
+ }
+
value_type& FindAndConstruct(const KeyT &Key) {
BucketT *TheBucket;
if (LookupBucketFor(Key, TheBucket))
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index 0898b96..9388338 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -45,6 +45,10 @@ public:
return TheMap.erase(V);
}
+ void swap(DenseSet& RHS) {
+ TheMap.swap(RHS.TheMap);
+ }
+
DenseSet &operator=(const DenseSet &RHS) {
TheMap = RHS.TheMap;
return *this;
@@ -55,6 +59,12 @@ public:
class Iterator {
typename MapTy::iterator I;
public:
+ typedef typename MapTy::iterator::difference_type difference_type;
+ typedef ValueT value_type;
+ typedef value_type *pointer;
+ typedef value_type &reference;
+ typedef std::forward_iterator_tag iterator_category;
+
Iterator(const typename MapTy::iterator &i) : I(i) {}
ValueT& operator*() { return I->first; }
@@ -68,6 +78,12 @@ public:
class ConstIterator {
typename MapTy::const_iterator I;
public:
+ typedef typename MapTy::const_iterator::difference_type difference_type;
+ typedef ValueT value_type;
+ typedef value_type *pointer;
+ typedef value_type &reference;
+ typedef std::forward_iterator_tag iterator_category;
+
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
const ValueT& operator*() { return I->first; }
diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h
index f105c20..9b1d1b30 100644
--- a/include/llvm/Analysis/DebugInfo.h
+++ b/include/llvm/Analysis/DebugInfo.h
@@ -44,11 +44,6 @@ namespace llvm {
protected:
MDNode *DbgNode;
- /// DIDescriptor constructor. If the specified node is non-null, check
- /// to make sure that the tag in the descriptor matches 'RequiredTag'. If
- /// not, the debug info is corrupt and we ignore it.
- DIDescriptor(MDNode *N, unsigned RequiredTag);
-
StringRef getStringField(unsigned Elt) const;
unsigned getUnsignedField(unsigned Elt) const {
return (unsigned)getUInt64Field(Elt);
@@ -67,7 +62,7 @@ namespace llvm {
explicit DIDescriptor() : DbgNode(0) {}
explicit DIDescriptor(MDNode *N) : DbgNode(N) {}
- bool isNull() const { return DbgNode == 0; }
+ bool Verify() const { return DbgNode != 0; }
MDNode *getNode() const { return DbgNode; }
@@ -92,6 +87,7 @@ namespace llvm {
bool isSubprogram() const;
bool isGlobalVariable() const;
bool isScope() const;
+ bool isFile() const;
bool isCompileUnit() const;
bool isNameSpace() const;
bool isLexicalBlock() const;
@@ -104,8 +100,7 @@ namespace llvm {
/// DISubrange - This is used to represent ranges, for array bounds.
class DISubrange : public DIDescriptor {
public:
- explicit DISubrange(MDNode *N = 0)
- : DIDescriptor(N, dwarf::DW_TAG_subrange_type) {}
+ explicit DISubrange(MDNode *N = 0) : DIDescriptor(N) {}
int64_t getLo() const { return (int64_t)getUInt64Field(1); }
int64_t getHi() const { return (int64_t)getUInt64Field(2); }
@@ -126,10 +121,7 @@ namespace llvm {
/// DIScope - A base class for various scopes.
class DIScope : public DIDescriptor {
public:
- explicit DIScope(MDNode *N = 0) : DIDescriptor (N) {
- if (DbgNode && !isScope())
- DbgNode = 0;
- }
+ explicit DIScope(MDNode *N = 0) : DIDescriptor (N) {}
virtual ~DIScope() {}
StringRef getFilename() const;
@@ -139,10 +131,7 @@ namespace llvm {
/// DICompileUnit - A wrapper for a compile unit.
class DICompileUnit : public DIScope {
public:
- explicit DICompileUnit(MDNode *N = 0) : DIScope(N) {
- if (DbgNode && !isCompileUnit())
- DbgNode = 0;
- }
+ explicit DICompileUnit(MDNode *N = 0) : DIScope(N) {}
unsigned getLanguage() const { return getUnsignedField(2); }
StringRef getFilename() const { return getStringField(3); }
@@ -170,13 +159,24 @@ namespace llvm {
void dump() const;
};
+ /// DIFile - This is a wrapper for a file.
+ class DIFile : public DIScope {
+ public:
+ explicit DIFile(MDNode *N = 0) : DIScope(N) {
+ if (DbgNode && !isFile())
+ DbgNode = 0;
+ }
+ StringRef getFilename() const { return getStringField(1); }
+ StringRef getDirectory() const { return getStringField(2); }
+ DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
+ };
+
/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
/// FIXME: it seems strange that this doesn't have either a reference to the
/// type/precision or a file/line pair for location info.
class DIEnumerator : public DIDescriptor {
public:
- explicit DIEnumerator(MDNode *N = 0)
- : DIDescriptor(N, dwarf::DW_TAG_enumerator) {}
+ explicit DIEnumerator(MDNode *N = 0) : DIDescriptor(N) {}
StringRef getName() const { return getStringField(1); }
uint64_t getEnumValue() const { return getUInt64Field(2); }
@@ -185,7 +185,7 @@ namespace llvm {
/// DIType - This is a wrapper for a type.
/// FIXME: Types should be factored much better so that CV qualifiers and
/// others do not require a huge and empty descriptor full of zeros.
- class DIType : public DIDescriptor {
+ class DIType : public DIScope {
public:
enum {
FlagPrivate = 1 << 0,
@@ -199,11 +199,9 @@ namespace llvm {
};
protected:
- DIType(MDNode *N, unsigned Tag)
- : DIDescriptor(N, Tag) {}
// This ctor is used when the Tag has already been validated by a derived
// ctor.
- DIType(MDNode *N, bool, bool) : DIDescriptor(N) {}
+ DIType(MDNode *N, bool, bool) : DIScope(N) {}
public:
@@ -214,9 +212,15 @@ namespace llvm {
explicit DIType() {}
virtual ~DIType() {}
- DIDescriptor getContext() const { return getDescriptorField(1); }
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
- DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
+ DICompileUnit getCompileUnit() const{
+ if (getVersion() == llvm::LLVMDebugVersion7)
+ return getFieldAs<DICompileUnit>(3);
+
+ DIFile F = getFieldAs<DIFile>(3);
+ return F.getCompileUnit();
+ }
unsigned getLineNumber() const { return getUnsignedField(4); }
uint64_t getSizeInBits() const { return getUInt64Field(5); }
uint64_t getAlignInBits() const { return getUInt64Field(6); }
@@ -246,7 +250,11 @@ namespace llvm {
bool isArtificial() const {
return (getFlags() & FlagArtificial) != 0;
}
-
+ bool isValid() const {
+ return DbgNode && (isBasicType() || isDerivedType() || isCompositeType());
+ }
+ StringRef getFilename() const { return getCompileUnit().getFilename();}
+ StringRef getDirectory() const { return getCompileUnit().getDirectory();}
/// dump - print type.
void dump() const;
};
@@ -254,8 +262,7 @@ namespace llvm {
/// DIBasicType - A basic type, like 'int' or 'float'.
class DIBasicType : public DIType {
public:
- explicit DIBasicType(MDNode *N = 0)
- : DIType(N, dwarf::DW_TAG_base_type) {}
+ explicit DIBasicType(MDNode *N = 0) : DIType(N) {}
unsigned getEncoding() const { return getUnsignedField(9); }
@@ -271,10 +278,7 @@ namespace llvm {
: DIType(N, true, true) {}
public:
explicit DIDerivedType(MDNode *N = 0)
- : DIType(N, true, true) {
- if (DbgNode && !isDerivedType())
- DbgNode = 0;
- }
+ : DIType(N, true, true) {}
DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); }
@@ -317,17 +321,23 @@ namespace llvm {
/// DIGlobal - This is a common class for global variables and subprograms.
class DIGlobal : public DIDescriptor {
protected:
- explicit DIGlobal(MDNode *N, unsigned RequiredTag)
- : DIDescriptor(N, RequiredTag) {}
+ explicit DIGlobal(MDNode *N) : DIDescriptor(N) {}
public:
virtual ~DIGlobal() {}
- DIDescriptor getContext() const { return getDescriptorField(2); }
+ DIScope getContext() const { return getFieldAs<DIScope>(2); }
StringRef getName() const { return getStringField(3); }
StringRef getDisplayName() const { return getStringField(4); }
StringRef getLinkageName() const { return getStringField(5); }
- DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); }
+ DICompileUnit getCompileUnit() const{
+ if (getVersion() == llvm::LLVMDebugVersion7)
+ return getFieldAs<DICompileUnit>(6);
+
+ DIFile F = getFieldAs<DIFile>(6);
+ return F.getCompileUnit();
+ }
+
unsigned getLineNumber() const { return getUnsignedField(7); }
DIType getType() const { return getFieldAs<DIType>(8); }
@@ -343,16 +353,19 @@ namespace llvm {
/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
class DISubprogram : public DIScope {
public:
- explicit DISubprogram(MDNode *N = 0) : DIScope(N) {
- if (DbgNode && !isSubprogram())
- DbgNode = 0;
- }
+ explicit DISubprogram(MDNode *N = 0) : DIScope(N) {}
- DIDescriptor getContext() const { return getDescriptorField(2); }
+ DIScope getContext() const { return getFieldAs<DIScope>(2); }
StringRef getName() const { return getStringField(3); }
StringRef getDisplayName() const { return getStringField(4); }
StringRef getLinkageName() const { return getStringField(5); }
- DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); }
+ DICompileUnit getCompileUnit() const{
+ if (getVersion() == llvm::LLVMDebugVersion7)
+ return getFieldAs<DICompileUnit>(6);
+
+ DIFile F = getFieldAs<DIFile>(6);
+ return F.getCompileUnit();
+ }
unsigned getLineNumber() const { return getUnsignedField(7); }
DICompositeType getType() const { return getFieldAs<DICompositeType>(8); }
@@ -360,7 +373,7 @@ namespace llvm {
/// DIType or as DICompositeType.
StringRef getReturnTypeName() const {
DICompositeType DCT(getFieldAs<DICompositeType>(8));
- if (!DCT.isNull()) {
+ if (DCT.Verify()) {
DIArray A = DCT.getTypeArray();
DIType T(A.getElement(0).getNode());
return T.getName();
@@ -399,8 +412,7 @@ namespace llvm {
/// DIGlobalVariable - This is a wrapper for a global variable.
class DIGlobalVariable : public DIGlobal {
public:
- explicit DIGlobalVariable(MDNode *N = 0)
- : DIGlobal(N, dwarf::DW_TAG_variable) {}
+ explicit DIGlobalVariable(MDNode *N = 0) : DIGlobal(N) {}
GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
@@ -416,14 +428,17 @@ namespace llvm {
class DIVariable : public DIDescriptor {
public:
explicit DIVariable(MDNode *N = 0)
- : DIDescriptor(N) {
- if (DbgNode && !isVariable())
- DbgNode = 0;
- }
+ : DIDescriptor(N) {}
- DIDescriptor getContext() const { return getDescriptorField(1); }
- StringRef getName() const { return getStringField(2); }
- DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
+ StringRef getName() const { return getStringField(2); }
+ DICompileUnit getCompileUnit() const{
+ if (getVersion() == llvm::LLVMDebugVersion7)
+ return getFieldAs<DICompileUnit>(3);
+
+ DIFile F = getFieldAs<DIFile>(3);
+ return F.getCompileUnit();
+ }
unsigned getLineNumber() const { return getUnsignedField(4); }
DIType getType() const { return getFieldAs<DIType>(5); }
@@ -455,10 +470,7 @@ namespace llvm {
/// DILexicalBlock - This is a wrapper for a lexical block.
class DILexicalBlock : public DIScope {
public:
- explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) {
- if (DbgNode && !isLexicalBlock())
- DbgNode = 0;
- }
+ explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getDirectory() const { return getContext().getDirectory(); }
StringRef getFilename() const { return getContext().getFilename(); }
@@ -469,16 +481,18 @@ namespace llvm {
/// DINameSpace - A wrapper for a C++ style name space.
class DINameSpace : public DIScope {
public:
- explicit DINameSpace(MDNode *N = 0) : DIScope(N) {
- if (DbgNode && !isNameSpace())
- DbgNode = 0;
- }
-
+ explicit DINameSpace(MDNode *N = 0) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
StringRef getDirectory() const { return getContext().getDirectory(); }
StringRef getFilename() const { return getContext().getFilename(); }
- DICompileUnit getCompileUnit() const { return getFieldAs<DICompileUnit>(3);}
+ DICompileUnit getCompileUnit() const{
+ if (getVersion() == llvm::LLVMDebugVersion7)
+ return getFieldAs<DICompileUnit>(3);
+
+ DIFile F = getFieldAs<DIFile>(3);
+ return F.getCompileUnit();
+ }
unsigned getLineNumber() const { return getUnsignedField(4); }
};
@@ -494,6 +508,7 @@ namespace llvm {
DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); }
StringRef getFilename() const { return getScope().getFilename(); }
StringRef getDirectory() const { return getScope().getDirectory(); }
+ bool Verify() const;
};
/// DIFactory - This object assists with the construction of the various
@@ -531,19 +546,22 @@ namespace llvm {
StringRef Flags = "",
unsigned RunTimeVer = 0);
+ /// CreateFile - Create a new descriptor for the specified file.
+ DIFile CreateFile(StringRef Filename, StringRef Directory, DICompileUnit CU);
+
/// CreateEnumerator - Create a single enumerator value.
DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name,
- DICompileUnit CompileUnit, unsigned LineNumber,
+ DIFile F, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
unsigned Encoding);
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name,
- DICompileUnit CompileUnit, unsigned LineNumber,
+ DIFile F, unsigned LineNumber,
Constant *SizeInBits, Constant *AlignInBits,
Constant *OffsetInBits, unsigned Flags,
unsigned Encoding);
@@ -552,7 +570,7 @@ namespace llvm {
/// pointer, typedef, etc.
DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
@@ -561,17 +579,18 @@ namespace llvm {
/// CreateDerivedType - Create a derived type like const qualified type,
/// pointer, typedef, etc.
DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context,
- StringRef Name,
- DICompileUnit CompileUnit,
- unsigned LineNumber,
- Constant *SizeInBits, Constant *AlignInBits,
- Constant *OffsetInBits, unsigned Flags,
- DIType DerivedFrom);
+ StringRef Name,
+ DIFile F,
+ unsigned LineNumber,
+ Constant *SizeInBits,
+ Constant *AlignInBits,
+ Constant *OffsetInBits, unsigned Flags,
+ DIType DerivedFrom);
/// CreateCompositeType - Create a composite type like array, struct, etc.
DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
@@ -586,22 +605,23 @@ namespace llvm {
/// CreateCompositeType - Create a composite type like array, struct, etc.
DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context,
- StringRef Name,
- DICompileUnit CompileUnit,
- unsigned LineNumber,
- Constant *SizeInBits,
- Constant *AlignInBits,
- Constant *OffsetInBits, unsigned Flags,
- DIType DerivedFrom,
- DIArray Elements,
- unsigned RunTimeLang = 0);
+ StringRef Name,
+ DIFile F,
+ unsigned LineNumber,
+ Constant *SizeInBits,
+ Constant *AlignInBits,
+ Constant *OffsetInBits,
+ unsigned Flags,
+ DIType DerivedFrom,
+ DIArray Elements,
+ unsigned RunTimeLang = 0);
/// CreateSubprogram - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields.
DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
- DICompileUnit CompileUnit, unsigned LineNo,
+ DIFile F, unsigned LineNo,
DIType Ty, bool isLocalToUnit,
bool isDefinition,
unsigned VK = 0,
@@ -618,21 +638,21 @@ namespace llvm {
CreateGlobalVariable(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNo, DIType Ty, bool isLocalToUnit,
bool isDefinition, llvm::GlobalVariable *GV);
/// CreateVariable - Create a new descriptor for the specified variable.
DIVariable CreateVariable(unsigned Tag, DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit, unsigned LineNo,
+ DIFile F, unsigned LineNo,
DIType Ty);
/// CreateComplexVariable - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context,
const std::string &Name,
- DICompileUnit CompileUnit, unsigned LineNo,
+ DIFile F, unsigned LineNo,
DIType Ty,
SmallVector<Value *, 9> &addr);
@@ -644,7 +664,7 @@ namespace llvm {
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent context.
DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name,
- DICompileUnit CU, unsigned LineNo);
+ DIFile F, unsigned LineNo);
/// CreateLocation - Creates a debug info location.
DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo,
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index 84acd7d..f0e97d7 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -179,6 +179,11 @@ namespace llvm {
void resetCachedCostInfo(Function* Caller) {
CachedFunctionInfo[Caller] = FunctionInfo();
}
+
+ /// growCachedCostInfo - update the cached cost info for Caller after Callee
+ /// has been inlined. If Callee is NULL it means a dead call has been
+ /// eliminated.
+ void growCachedCostInfo(Function* Caller, Function* Callee);
};
}
diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h
index 3681cc01..5552017 100644
--- a/include/llvm/Analysis/PostDominators.h
+++ b/include/llvm/Analysis/PostDominators.h
@@ -69,6 +69,10 @@ struct PostDominatorTree : public FunctionPass {
return DT->properlyDominates(A, B);
}
+ inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
+ return DT->findNearestCommonDominator(A, B);
+ }
+
virtual void releaseMemory() {
DT->releaseMemory();
}
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 8ade1bd..6187447 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -136,6 +136,7 @@ namespace llvm {
mutable const MachineInstr *LastMI;
mutable const Function *LastFn;
mutable unsigned Counter;
+ mutable unsigned SetCounter;
// Private state for processDebugLoc()
mutable const MDNode *PrevDLT;
@@ -275,6 +276,13 @@ namespace llvm {
/// EmitInt64 - Emit a long long directive and value.
///
void EmitInt64(uint64_t Value) const;
+
+
+ /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
+ /// in bytes of the directive is specified by Size and Hi/Lo specify the
+ /// labels. This implicitly uses .set if it is available.
+ void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) const;
//===------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h
index d59e22a..3c7f802 100644
--- a/include/llvm/CodeGen/DwarfWriter.h
+++ b/include/llvm/CodeGen/DwarfWriter.h
@@ -35,6 +35,7 @@ class Value;
class Module;
class MDNode;
class MCAsmInfo;
+class MCSymbol;
class raw_ostream;
class Instruction;
class DICompileUnit;
@@ -82,10 +83,10 @@ public:
///
void EndFunction(const MachineFunction *MF);
- /// RecordSourceLine - Register a source line with debug info. Returns a
- /// unique label ID used to generate a label and provide correspondence to
+ /// RecordSourceLine - Register a source line with debug info. Returns the
+ /// unique label that was emitted and which provides correspondence to
/// the source line list.
- unsigned RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
+ MCSymbol *RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
/// getRecordSourceLineCount - Count source lines.
unsigned getRecordSourceLineCount();
@@ -94,7 +95,7 @@ public:
/// be emitted.
bool ShouldEmitDwarfDebug() const;
- void BeginScope(const MachineInstr *MI, unsigned Label);
+ void BeginScope(const MachineInstr *MI, MCSymbol *Label);
void EndScope(const MachineInstr *MI);
};
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index 8eeac9f..fff8e83 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -217,26 +217,19 @@ public:
/// MachineModuleInfo, for example because the code was deleted.
void InvalidateLabel(unsigned LabelID) {
// Remap to zero to indicate deletion.
- RemapLabel(LabelID, 0);
- }
-
- /// RemapLabel - Indicate that a label has been merged into another.
- ///
- void RemapLabel(unsigned OldLabelID, unsigned NewLabelID) {
- assert(0 < OldLabelID && OldLabelID <= LabelIDList.size() &&
- "Old label ID out of range.");
- assert(NewLabelID <= LabelIDList.size() &&
- "New label ID out of range.");
- LabelIDList[OldLabelID - 1] = NewLabelID;
+ assert(0 < LabelID && LabelID <= LabelIDList.size() &&
+ "Old label ID out of range.");
+ LabelIDList[LabelID - 1] = 0;
}
- /// MappedLabel - Find out the label's final ID. Zero indicates deletion.
- /// ID != Mapped ID indicates that the label was folded into another label.
- unsigned MappedLabel(unsigned LabelID) const {
+ /// isLabelDeleted - Return true if the label was deleted.
+ /// FIXME: This should eventually be eliminated and use the 'is emitted' bit
+ /// on MCSymbol.
+ bool isLabelDeleted(unsigned LabelID) const {
assert(LabelID <= LabelIDList.size() && "Debug label ID out of range.");
- return LabelID ? LabelIDList[LabelID - 1] : 0;
+ return LabelID == 0 || LabelIDList[LabelID - 1] == 0;
}
-
+
/// getFrameMoves - Returns a reference to a list of moves done in the current
/// function's prologue. Used to construct frame maps for debug and exception
/// handling comsumers.
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 3effea4..7e0c8a5 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -247,18 +247,6 @@ namespace llvm {
/// encode inline subroutine information.
bool DwarfUsesInlineInfoSection; // Defaults to false.
- /// Is_EHSymbolPrivate - If set, the "_foo.eh" is made private so that it
- /// doesn't show up in the symbol table of the object file.
- bool Is_EHSymbolPrivate; // Defaults to true.
-
- /// GlobalEHDirective - This is the directive used to make exception frame
- /// tables globally visible.
- const char *GlobalEHDirective; // Defaults to NULL.
-
- /// SupportsWeakEmptyEHFrame - True if target assembler and linker will
- /// handle a weak_definition of constant 0 for an omitted EH frame.
- bool SupportsWeakOmittedEHFrame; // Defaults to true.
-
/// DwarfSectionOffsetDirective - Special section offset directive.
const char* DwarfSectionOffsetDirective; // Defaults to NULL
@@ -419,15 +407,6 @@ namespace llvm {
bool doesDwarfUsesInlineInfoSection() const {
return DwarfUsesInlineInfoSection;
}
- bool is_EHSymbolPrivate() const {
- return Is_EHSymbolPrivate;
- }
- const char *getGlobalEHDirective() const {
- return GlobalEHDirective;
- }
- bool getSupportsWeakOmittedEHFrame() const {
- return SupportsWeakOmittedEHFrame;
- }
const char *getDwarfSectionOffsetDirective() const {
return DwarfSectionOffsetDirective;
}
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index 74415e2..f2f1456 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -46,11 +46,6 @@ namespace llvm {
/// @name Symbol Managment
/// @{
- /// CreateSymbol - Create a new symbol with the specified @p Name.
- ///
- /// @param Name - The symbol name, which must be unique across all symbols.
- MCSymbol *CreateSymbol(StringRef Name);
-
/// GetOrCreateSymbol - Lookup the symbol inside with the specified
/// @p Name. If it exists, return it. If not, create a forward
/// reference and return it.
@@ -59,13 +54,15 @@ namespace llvm {
MCSymbol *GetOrCreateSymbol(StringRef Name);
MCSymbol *GetOrCreateSymbol(const Twine &Name);
- /// CreateTemporarySymbol - Create a new temporary symbol with the specified
- /// @p Name.
+ /// GetOrCreateTemporarySymbol - Create a new assembler temporary symbol
+ /// with the specified @p Name if it doesn't exist or return the existing
+ /// one if it does.
///
/// @param Name - The symbol name, for debugging purposes only, temporary
/// symbols do not surive assembly. If non-empty the name must be unique
/// across all symbols.
- MCSymbol *CreateTemporarySymbol(StringRef Name = "");
+ MCSymbol *GetOrCreateTemporarySymbol(StringRef Name = "");
+ MCSymbol *GetOrCreateTemporarySymbol(const Twine &Name);
/// LookupSymbol - Get the symbol for \p Name, or null.
MCSymbol *LookupSymbol(StringRef Name) const;
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index fce7602..3f17492 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -127,6 +127,10 @@ public:
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx);
static const MCSymbolRefExpr *Create(StringRef Name, MCContext &Ctx);
+
+ /// CreateTemp - Create a reference to an assembler temporary label with the
+ /// specified name.
+ static const MCSymbolRefExpr *CreateTemp(StringRef Name, MCContext &Ctx);
/// @}
/// @name Accessors
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 696d024..6359cce 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -191,6 +191,11 @@ namespace llvm {
/// EmitIntValue - Special case of EmitValue that avoids the client having
/// to pass in a MCExpr for constant integers.
virtual void EmitIntValue(uint64_t Value, unsigned Size,unsigned AddrSpace);
+
+ /// EmitSymbolValue - Special case of EmitValue that avoids the client
+ /// having to pass in a MCExpr for MCSymbols.
+ virtual void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
+ unsigned AddrSpace);
/// EmitGPRel32Value - Emit the expression @p Value into the output as a
/// gprel32 (32-bit GP relative) value.
diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h
index e536322..cf87989 100644
--- a/include/llvm/Metadata.h
+++ b/include/llvm/Metadata.h
@@ -43,8 +43,10 @@ protected:
public:
static MDString *get(LLVMContext &Context, StringRef Str);
- static MDString *get(LLVMContext &Context, const char *Str);
-
+ static MDString *get(LLVMContext &Context, const char *Str) {
+ return get(Context, Str ? StringRef(Str) : StringRef());
+ }
+
StringRef getString() const { return Str; }
unsigned getLength() const { return (unsigned)Str.size(); }
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index 5f591d4..31f4fd2 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -22,7 +22,8 @@ namespace llvm {
// Debug info constants.
enum {
- LLVMDebugVersion = (7 << 16), // Current version of debug information.
+ LLVMDebugVersion = (8 << 16), // Current version of debug information.
+ LLVMDebugVersion7 = (7 << 16), // Constant for version 7.
LLVMDebugVersion6 = (6 << 16), // Constant for version 6.
LLVMDebugVersion5 = (5 << 16), // Constant for version 5.
LLVMDebugVersion4 = (4 << 16), // Constant for version 4.
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 60b7ebd..5bc1c0e 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -664,12 +664,12 @@ public:
/// getOptimalMemOpType - Returns the target specific optimal type for load
/// and store operations as a result of memset, memcpy, and memmove lowering.
- /// It returns EVT::iAny if SelectionDAG should be responsible for
+ /// It returns EVT::Other if SelectionDAG should be responsible for
/// determining it.
virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align,
bool isSrcConst, bool isSrcStr,
SelectionDAG &DAG) const {
- return MVT::iAny;
+ return MVT::Other;
}
/// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 42d88a0..056efea 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -87,11 +87,23 @@ protected:
const MCSection *DwarfRangesSection;
const MCSection *DwarfMacroInfoSection;
+ /// SupportsWeakEmptyEHFrame - True if target object file supports a
+ /// weak_definition of constant 0 for an omitted EH frame.
+ bool SupportsWeakOmittedEHFrame;
+
+ /// IsFunctionEHSymbolGlobal - This flag is set to true if the ".eh" symbol
+ /// for a function should be marked .globl.
+ bool IsFunctionEHSymbolGlobal;
+
+ /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the
+ /// "EH_frame" symbol for EH information should be an assembler temporary (aka
+ /// private linkage, aka an L or .L label) or false if it should be a normal
+ /// non-.globl label. This defaults to true.
+ bool IsFunctionEHFrameSymbolPrivate;
public:
MCContext &getContext() const { return *Ctx; }
-
virtual ~TargetLoweringObjectFile();
/// Initialize - this method must be called before any actual lowering is
@@ -101,6 +113,15 @@ public:
Ctx = &ctx;
}
+ bool isFunctionEHSymbolGlobal() const {
+ return IsFunctionEHSymbolGlobal;
+ }
+ bool isFunctionEHFrameSymbolPrivate() const {
+ return IsFunctionEHFrameSymbolPrivate;
+ }
+ bool getSupportsWeakOmittedEHFrame() const {
+ return SupportsWeakOmittedEHFrame;
+ }
const MCSection *getTextSection() const { return TextSection; }
const MCSection *getDataSection() const { return DataSection; }
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 212cc93..c197445 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -682,8 +682,9 @@ public:
/// When -enable-frame-index-scavenging is enabled, the virtual register
/// allocated for this frame index is returned and its value is stored in
/// *Value.
+ typedef std::pair<unsigned, int> FrameIndexValue;
virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS=NULL) const = 0;
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h
index 30ece0e..c5be59a 100644
--- a/include/llvm/Transforms/IPO/InlinerPass.h
+++ b/include/llvm/Transforms/IPO/InlinerPass.h
@@ -75,6 +75,10 @@ struct Inliner : public CallGraphSCCPass {
///
virtual void resetCachedCostInfo(Function* Caller) = 0;
+ /// growCachedCostInfo - update the cached cost info for Caller after Callee
+ /// has been inlined.
+ virtual void growCachedCostInfo(Function* Caller, Function* Callee) = 0;
+
/// removeDeadFunctions - Remove dead functions that are not included in
/// DNR (Do Not Remove) list.
bool removeDeadFunctions(CallGraph &CG,
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index 5cfe666..fda69ac 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/lib/Analysis/DebugInfo.cpp
@@ -41,9 +41,9 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) {
DIDescriptor DI(N);
- // Check current version. Allow Version6 for now.
+ // Check current version. Allow Version7 for now.
unsigned Version = DI.getVersion();
- if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6)
+ if (Version != LLVMDebugVersion && Version != LLVMDebugVersion7)
return false;
switch (DI.getTag()) {
@@ -69,15 +69,6 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) {
return true;
}
-DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) {
- DbgNode = N;
-
- // If this is non-null, check to see if the Tag matches. If not, set to null.
- if (N && getTag() != RequiredTag) {
- DbgNode = 0;
- }
-}
-
StringRef
DIDescriptor::getStringField(unsigned Elt) const {
if (DbgNode == 0)
@@ -132,13 +123,12 @@ unsigned DIVariable::getNumAddrElements() const {
/// isBasicType - Return true if the specified tag is legal for
/// DIBasicType.
bool DIDescriptor::isBasicType() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_base_type;
+ return DbgNode && getTag() == dwarf::DW_TAG_base_type;
}
/// isDerivedType - Return true if the specified tag is legal for DIDerivedType.
bool DIDescriptor::isDerivedType() const {
- assert(!isNull() && "Invalid descriptor!");
+ if (!DbgNode) return false;
switch (getTag()) {
case dwarf::DW_TAG_typedef:
case dwarf::DW_TAG_pointer_type:
@@ -158,7 +148,7 @@ bool DIDescriptor::isDerivedType() const {
/// isCompositeType - Return true if the specified tag is legal for
/// DICompositeType.
bool DIDescriptor::isCompositeType() const {
- assert(!isNull() && "Invalid descriptor!");
+ if (!DbgNode) return false;
switch (getTag()) {
case dwarf::DW_TAG_array_type:
case dwarf::DW_TAG_structure_type:
@@ -175,7 +165,7 @@ bool DIDescriptor::isCompositeType() const {
/// isVariable - Return true if the specified tag is legal for DIVariable.
bool DIDescriptor::isVariable() const {
- assert(!isNull() && "Invalid descriptor!");
+ if (!DbgNode) return false;
switch (getTag()) {
case dwarf::DW_TAG_auto_variable:
case dwarf::DW_TAG_arg_variable:
@@ -194,15 +184,13 @@ bool DIDescriptor::isType() const {
/// isSubprogram - Return true if the specified tag is legal for
/// DISubprogram.
bool DIDescriptor::isSubprogram() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_subprogram;
+ return DbgNode && getTag() == dwarf::DW_TAG_subprogram;
}
/// isGlobalVariable - Return true if the specified tag is legal for
/// DIGlobalVariable.
bool DIDescriptor::isGlobalVariable() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_variable;
+ return DbgNode && getTag() == dwarf::DW_TAG_variable;
}
/// isGlobal - Return true if the specified tag is legal for DIGlobal.
@@ -213,7 +201,7 @@ bool DIDescriptor::isGlobal() const {
/// isScope - Return true if the specified tag is one of the scope
/// related tag.
bool DIDescriptor::isScope() const {
- assert(!isNull() && "Invalid descriptor!");
+ if (!DbgNode) return false;
switch (getTag()) {
case dwarf::DW_TAG_compile_unit:
case dwarf::DW_TAG_lexical_block:
@@ -228,39 +216,39 @@ bool DIDescriptor::isScope() const {
/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit.
bool DIDescriptor::isCompileUnit() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_compile_unit;
+ return DbgNode && getTag() == dwarf::DW_TAG_compile_unit;
+}
+
+/// isFile - Return true if the specified tag is DW_TAG_file_type.
+bool DIDescriptor::isFile() const {
+ return DbgNode && getTag() == dwarf::DW_TAG_file_type;
}
/// isNameSpace - Return true if the specified tag is DW_TAG_namespace.
bool DIDescriptor::isNameSpace() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_namespace;
+ return DbgNode && getTag() == dwarf::DW_TAG_namespace;
}
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
bool DIDescriptor::isLexicalBlock() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_lexical_block;
+ return DbgNode && getTag() == dwarf::DW_TAG_lexical_block;
}
/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type.
bool DIDescriptor::isSubrange() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_subrange_type;
+ return DbgNode && getTag() == dwarf::DW_TAG_subrange_type;
}
/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator.
bool DIDescriptor::isEnumerator() const {
- assert(!isNull() && "Invalid descriptor!");
- return getTag() == dwarf::DW_TAG_enumerator;
+ return DbgNode && getTag() == dwarf::DW_TAG_enumerator;
}
//===----------------------------------------------------------------------===//
// Simple Descriptor Constructors and other Methods
//===----------------------------------------------------------------------===//
-DIType::DIType(MDNode *N) : DIDescriptor(N) {
+DIType::DIType(MDNode *N) : DIScope(N) {
if (!N) return;
if (!isBasicType() && !isDerivedType() && !isCompositeType()) {
DbgNode = 0;
@@ -268,7 +256,8 @@ DIType::DIType(MDNode *N) : DIDescriptor(N) {
}
unsigned DIArray::getNumElements() const {
- assert(DbgNode && "Invalid DIArray");
+ if (!DbgNode)
+ return 0;
return DbgNode->getNumOperands();
}
@@ -276,11 +265,9 @@ unsigned DIArray::getNumElements() const {
/// this descriptor. After this completes, the current debug info value
/// is erased.
void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) {
- if (isNull())
+ if (!DbgNode)
return;
- assert(!D.isNull() && "Can not replace with null");
-
// Since we use a TrackingVH for the node, its easy for clients to manufacture
// legitimate situations where they want to replaceAllUsesWith() on something
// which, due to uniquing, has merged with the source. We shield clients from
@@ -295,7 +282,7 @@ void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) {
/// Verify - Verify that a compile unit is well formed.
bool DICompileUnit::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
StringRef N = getFilename();
if (N.empty())
@@ -306,36 +293,36 @@ bool DICompileUnit::Verify() const {
/// Verify - Verify that a type descriptor is well formed.
bool DIType::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
- if (getContext().isNull())
+ if (!getContext().Verify())
return false;
DICompileUnit CU = getCompileUnit();
- if (!CU.isNull() && !CU.Verify())
+ if (!CU.Verify())
return false;
return true;
}
/// Verify - Verify that a composite type descriptor is well formed.
bool DICompositeType::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
- if (getContext().isNull())
+ if (!getContext().Verify())
return false;
DICompileUnit CU = getCompileUnit();
- if (!CU.isNull() && !CU.Verify())
+ if (!CU.Verify())
return false;
return true;
}
/// Verify - Verify that a subprogram descriptor is well formed.
bool DISubprogram::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
- if (getContext().isNull())
+ if (!getContext().Verify())
return false;
DICompileUnit CU = getCompileUnit();
@@ -343,24 +330,24 @@ bool DISubprogram::Verify() const {
return false;
DICompositeType Ty = getType();
- if (!Ty.isNull() && !Ty.Verify())
+ if (!Ty.Verify())
return false;
return true;
}
/// Verify - Verify that a global variable descriptor is well formed.
bool DIGlobalVariable::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
if (getDisplayName().empty())
return false;
- if (getContext().isNull())
+ if (!getContext().Verify())
return false;
DICompileUnit CU = getCompileUnit();
- if (!CU.isNull() && !CU.Verify())
+ if (!CU.Verify())
return false;
DIType Ty = getType();
@@ -375,10 +362,10 @@ bool DIGlobalVariable::Verify() const {
/// Verify - Verify that a variable descriptor is well formed.
bool DIVariable::Verify() const {
- if (isNull())
+ if (!DbgNode)
return false;
- if (getContext().isNull())
+ if (!getContext().Verify())
return false;
DIType Ty = getType();
@@ -388,6 +375,14 @@ bool DIVariable::Verify() const {
return true;
}
+/// Verify - Verify that a location descriptor is well formed.
+bool DILocation::Verify() const {
+ if (!DbgNode)
+ return false;
+
+ return DbgNode->getNumOperands() == 4;
+}
+
/// getOriginalTypeSize - If this type is derived from a base type then
/// return base type size.
uint64_t DIDerivedType::getOriginalTypeSize() const {
@@ -398,7 +393,7 @@ uint64_t DIDerivedType::getOriginalTypeSize() const {
DIType BaseType = getTypeDerivedFrom();
// If this type is not derived from any type then take conservative
// approach.
- if (BaseType.isNull())
+ if (!BaseType.isValid())
return getSizeInBits();
if (BaseType.isDerivedType())
return DIDerivedType(BaseType.getNode()).getOriginalTypeSize();
@@ -422,6 +417,8 @@ bool DISubprogram::describes(const Function *F) {
}
StringRef DIScope::getFilename() const {
+ if (!DbgNode)
+ return StringRef();
if (isLexicalBlock())
return DILexicalBlock(DbgNode).getFilename();
if (isSubprogram())
@@ -430,11 +427,17 @@ StringRef DIScope::getFilename() const {
return DICompileUnit(DbgNode).getFilename();
if (isNameSpace())
return DINameSpace(DbgNode).getFilename();
+ if (isType())
+ return DIType(DbgNode).getFilename();
+ if (isFile())
+ return DIFile(DbgNode).getFilename();
assert(0 && "Invalid DIScope!");
return StringRef();
}
StringRef DIScope::getDirectory() const {
+ if (!DbgNode)
+ return StringRef();
if (isLexicalBlock())
return DILexicalBlock(DbgNode).getDirectory();
if (isSubprogram())
@@ -443,6 +446,10 @@ StringRef DIScope::getDirectory() const {
return DICompileUnit(DbgNode).getDirectory();
if (isNameSpace())
return DINameSpace(DbgNode).getDirectory();
+ if (isType())
+ return DIType(DbgNode).getDirectory();
+ if (isFile())
+ return DIFile(DbgNode).getDirectory();
assert(0 && "Invalid DIScope!");
return StringRef();
}
@@ -468,7 +475,7 @@ void DICompileUnit::dump() const {
/// dump - Print type.
void DIType::dump() const {
- if (isNull()) return;
+ if (!DbgNode) return;
StringRef Res = getName();
if (!Res.empty())
@@ -521,8 +528,6 @@ void DIDerivedType::dump() const {
/// dump - Print composite type.
void DICompositeType::dump() const {
DIArray A = getTypeArray();
- if (A.isNull())
- return;
dbgs() << " [" << A.getNumElements() << " elements]";
}
@@ -665,6 +670,20 @@ DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID,
return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10));
}
+/// CreateFile - Create a new descriptor for the specified file.
+DIFile DIFactory::CreateFile(StringRef Filename,
+ StringRef Directory,
+ DICompileUnit CU) {
+ Value *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_file_type),
+ MDString::get(VMContext, Filename),
+ MDString::get(VMContext, Directory),
+ CU.getNode()
+ };
+
+ return DIFile(MDNode::get(VMContext, &Elts[0], 4));
+}
+
/// CreateEnumerator - Create a single enumerator value.
DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){
Value *Elts[] = {
@@ -679,7 +698,7 @@ DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
@@ -689,7 +708,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
GetTagConstant(dwarf::DW_TAG_base_type),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
@@ -704,7 +723,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
@@ -714,7 +733,7 @@ DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context,
GetTagConstant(dwarf::DW_TAG_base_type),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
@@ -754,7 +773,7 @@ DIType DIFactory::CreateArtificialType(DIType Ty) {
DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
@@ -765,7 +784,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
@@ -782,7 +801,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
@@ -793,7 +812,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
@@ -809,7 +828,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
@@ -824,7 +843,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
@@ -843,7 +862,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag,
DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
@@ -857,7 +876,7 @@ DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag,
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
@@ -878,7 +897,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNo, DIType Ty,
bool isLocalToUnit,
bool isDefinition,
@@ -893,7 +912,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
@@ -938,7 +957,7 @@ DIGlobalVariable
DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNo, DIType Ty,bool isLocalToUnit,
bool isDefinition, llvm::GlobalVariable *Val) {
Value *Elts[] = {
@@ -948,7 +967,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
@@ -970,13 +989,14 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
/// CreateVariable - Create a new descriptor for the specified variable.
DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
StringRef Name,
- DICompileUnit CompileUnit, unsigned LineNo,
+ DIFile F,
+ unsigned LineNo,
DIType Ty) {
Value *Elts[] = {
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty.getNode(),
};
@@ -988,7 +1008,7 @@ DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
/// which has a complex address expression for its address.
DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
const std::string &Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNo,
DIType Ty,
SmallVector<Value *, 9> &addr) {
@@ -996,7 +1016,7 @@ DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
Elts.push_back(GetTagConstant(Tag));
Elts.push_back(Context.getNode());
Elts.push_back(MDString::get(VMContext, Name));
- Elts.push_back(CompileUnit.getNode());
+ Elts.push_back(F.getNode());
Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo));
Elts.push_back(Ty.getNode());
Elts.insert(Elts.end(), addr.begin(), addr.end());
@@ -1021,13 +1041,13 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context,
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent context.
DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name,
- DICompileUnit CompileUnit,
+ DIFile F,
unsigned LineNo) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_namespace),
Context.getNode(),
MDString::get(VMContext, Name),
- CompileUnit.getNode(),
+ F.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
};
return DINameSpace(MDNode::get(VMContext, &Elts[0], 5));
@@ -1155,9 +1175,8 @@ void DebugInfoFinder::processModule(Module &M) {
/// processLocation - Process DILocation.
void DebugInfoFinder::processLocation(DILocation Loc) {
- if (Loc.isNull()) return;
- DIScope S(Loc.getScope().getNode());
- if (S.isNull()) return;
+ if (!Loc.Verify()) return;
+ DIDescriptor S(Loc.getScope().getNode());
if (S.isCompileUnit())
addCompileUnit(DICompileUnit(S.getNode()));
else if (S.isSubprogram())
@@ -1177,26 +1196,21 @@ void DebugInfoFinder::processType(DIType DT) {
DICompositeType DCT(DT.getNode());
processType(DCT.getTypeDerivedFrom());
DIArray DA = DCT.getTypeArray();
- if (!DA.isNull())
- for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
- DIDescriptor D = DA.getElement(i);
- DIType TyE = DIType(D.getNode());
- if (!TyE.isNull())
- processType(TyE);
- else
- processSubprogram(DISubprogram(D.getNode()));
- }
+ for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
+ DIDescriptor D = DA.getElement(i);
+ if (D.isType())
+ processType(DIType(D.getNode()));
+ else if (D.isSubprogram())
+ processSubprogram(DISubprogram(D.getNode()));
+ }
} else if (DT.isDerivedType()) {
DIDerivedType DDT(DT.getNode());
- if (!DDT.isNull())
- processType(DDT.getTypeDerivedFrom());
+ processType(DDT.getTypeDerivedFrom());
}
}
/// processLexicalBlock
void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
- if (LB.isNull())
- return;
DIScope Context = LB.getContext();
if (Context.isLexicalBlock())
return processLexicalBlock(DILexicalBlock(Context.getNode()));
@@ -1206,8 +1220,6 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
/// processSubprogram - Process DISubprogram.
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
- if (SP.isNull())
- return;
if (!addSubprogram(SP))
return;
addCompileUnit(SP.getCompileUnit());
@@ -1216,20 +1228,23 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) {
/// processDeclare - Process DbgDeclareInst.
void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) {
- DIVariable DV(cast<MDNode>(DDI->getVariable()));
- if (DV.isNull())
+ MDNode *N = dyn_cast<MDNode>(DDI->getVariable());
+ if (!N) return;
+
+ DIDescriptor DV(N);
+ if (!DV.isVariable())
return;
if (!NodesSeen.insert(DV.getNode()))
return;
- addCompileUnit(DV.getCompileUnit());
- processType(DV.getType());
+ addCompileUnit(DIVariable(N).getCompileUnit());
+ processType(DIVariable(N).getType());
}
/// addType - Add type into Tys.
bool DebugInfoFinder::addType(DIType DT) {
- if (DT.isNull())
+ if (!DT.isValid())
return false;
if (!NodesSeen.insert(DT.getNode()))
@@ -1241,7 +1256,7 @@ bool DebugInfoFinder::addType(DIType DT) {
/// addCompileUnit - Add compile unit into CUs.
bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
- if (CU.isNull())
+ if (!CU.Verify())
return false;
if (!NodesSeen.insert(CU.getNode()))
@@ -1253,7 +1268,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
/// addGlobalVariable - Add global variable into GVs.
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
- if (DIG.isNull())
+ if (!DIDescriptor(DIG.getNode()).isGlobalVariable())
return false;
if (!NodesSeen.insert(DIG.getNode()))
@@ -1265,7 +1280,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
// addSubprogram - Add subprgoram into SPs.
bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
- if (SP.isNull())
+ if (!DIDescriptor(SP.getNode()).isSubprogram())
return false;
if (!NodesSeen.insert(SP.getNode()))
@@ -1283,10 +1298,10 @@ static Value *findDbgGlobalDeclare(GlobalVariable *V) {
return 0;
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- DIGlobalVariable DIG(cast_or_null<MDNode>(NMD->getOperand(i)));
- if (DIG.isNull())
+ DIDescriptor DIG(cast_or_null<MDNode>(NMD->getOperand(i)));
+ if (!DIG.isGlobalVariable())
continue;
- if (DIG.getGlobal() == V)
+ if (DIGlobalVariable(DIG.getNode()).getGlobal() == V)
return DIG.getNode();
}
return 0;
@@ -1378,12 +1393,6 @@ DebugLoc llvm::ExtractDebugLocation(DILocation &Loc,
/// getDISubprogram - Find subprogram that is enclosing this scope.
DISubprogram llvm::getDISubprogram(MDNode *Scope) {
DIDescriptor D(Scope);
- if (D.isNull())
- return DISubprogram();
-
- if (D.isCompileUnit())
- return DISubprogram();
-
if (D.isSubprogram())
return DISubprogram(Scope);
@@ -1395,9 +1404,6 @@ DISubprogram llvm::getDISubprogram(MDNode *Scope) {
/// getDICompositeType - Find underlying composite type.
DICompositeType llvm::getDICompositeType(DIType T) {
- if (T.isNull())
- return DICompositeType();
-
if (T.isCompositeType())
return DICompositeType(T.getNode());
diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index ca50a17..0f1f93b 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/lib/Analysis/InlineCost.cpp
@@ -352,11 +352,6 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
// Calls usually take a long time, so they make the inlining gain smaller.
InlineCost += CalleeFI.Metrics.NumCalls * InlineConstants::CallPenalty;
- // Don't inline into something too big, which would make it bigger.
- // "size" here is the number of basic blocks, not instructions.
- //
- InlineCost += Caller->size()/15;
-
// Look at the size of the callee. Each instruction counts as 5.
InlineCost += CalleeFI.Metrics.NumInsts*InlineConstants::InstrCost;
@@ -388,3 +383,45 @@ float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
Factor += 1.5f;
return Factor;
}
+
+/// growCachedCostInfo - update the cached cost info for Caller after Callee has
+/// been inlined.
+void
+InlineCostAnalyzer::growCachedCostInfo(Function* Caller, Function* Callee) {
+ FunctionInfo &CallerFI = CachedFunctionInfo[Caller];
+
+ // For small functions we prefer to recalculate the cost for better accuracy.
+ if (CallerFI.Metrics.NumBlocks < 10 || CallerFI.Metrics.NumInsts < 1000) {
+ resetCachedCostInfo(Caller);
+ return;
+ }
+
+ // For large functions, we can save a lot of computation time by skipping
+ // recalculations.
+ if (CallerFI.Metrics.NumCalls > 0)
+ --CallerFI.Metrics.NumCalls;
+
+ if (Callee) {
+ FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];
+ if (!CalleeFI.Metrics.NumBlocks) {
+ resetCachedCostInfo(Caller);
+ return;
+ }
+ CallerFI.Metrics.NeverInline |= CalleeFI.Metrics.NeverInline;
+ CallerFI.Metrics.usesDynamicAlloca |= CalleeFI.Metrics.usesDynamicAlloca;
+
+ CallerFI.Metrics.NumInsts += CalleeFI.Metrics.NumInsts;
+ CallerFI.Metrics.NumBlocks += CalleeFI.Metrics.NumBlocks;
+ CallerFI.Metrics.NumCalls += CalleeFI.Metrics.NumCalls;
+ CallerFI.Metrics.NumVectorInsts += CalleeFI.Metrics.NumVectorInsts;
+ CallerFI.Metrics.NumRets += CalleeFI.Metrics.NumRets;
+
+ // analyzeBasicBlock counts each function argument as an inst.
+ if (CallerFI.Metrics.NumInsts >= Callee->arg_size())
+ CallerFI.Metrics.NumInsts -= Callee->arg_size();
+ else
+ CallerFI.Metrics.NumInsts = 0;
+ }
+ // We are not updating the argumentweights. We have already determined that
+ // Caller is a fairly large function, so we accept the loss of precision.
+}
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index 453af5a..2139c29 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -264,6 +264,13 @@ unsigned Loop::getSmallConstantTripMultiple() const {
/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool Loop::isLCSSAForm() const {
+ // Collect all the reachable blocks in the function, for fast lookups.
+ SmallPtrSet<BasicBlock *, 32> ReachableBBs;
+ BasicBlock *EntryBB = getHeader()->getParent()->begin();
+ for (df_iterator<BasicBlock *> NI = df_begin(EntryBB),
+ NE = df_end(EntryBB); NI != NE; ++NI)
+ ReachableBBs.insert(*NI);
+
// Sort the blocks vector so that we can use binary search to do quick
// lookups.
SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());
@@ -277,9 +284,13 @@ bool Loop::isLCSSAForm() const {
if (PHINode *P = dyn_cast<PHINode>(*UI))
UserBB = P->getIncomingBlock(UI);
- // Check the current block, as a fast-path. Most values are used in
- // the same block they are defined in.
- if (UserBB != BB && !LoopBBs.count(UserBB))
+ // Check the current block, as a fast-path, before checking whether
+ // the use is anywhere in the loop. Most values are used in the same
+ // block they are defined in. Also, blocks not reachable from the
+ // entry are special; uses in them don't need to go through PHIs.
+ if (UserBB != BB &&
+ !LoopBBs.count(UserBB) &&
+ ReachableBBs.count(UserBB))
return false;
}
}
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index b979f33..15f072d 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -3101,9 +3101,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
return getUnknown(V);
unsigned Opcode = Instruction::UserOp1;
- if (Instruction *I = dyn_cast<Instruction>(V))
+ if (Instruction *I = dyn_cast<Instruction>(V)) {
Opcode = I->getOpcode();
- else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+
+ // Don't attempt to analyze instructions in blocks that aren't
+ // reachable. Such instructions don't matter, and they aren't required
+ // to obey basic rules for definitions dominating uses which this
+ // analysis depends on.
+ if (!DT->isReachableFromEntry(I->getParent()))
+ return getUnknown(V);
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
Opcode = CE->getOpcode();
else if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
return getConstant(CI);
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index e27da96..3c2cbfb 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -1286,6 +1286,8 @@ Value *SCEVExpander::expand(const SCEV *S) {
// there) so that it is guaranteed to dominate any user inside the loop.
if (L && S->hasComputableLoopEvolution(L) && L != PostIncLoop)
InsertPt = L->getHeader()->getFirstNonPHI();
+ while (isa<DbgInfoIntrinsic>(InsertPt))
+ InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
while (isInsertedInstruction(InsertPt))
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
break;
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index bd2b1b6..4978fba 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -61,7 +61,7 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
: MachineFunctionPass(&ID), O(o),
TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
OutContext(Ctx), OutStreamer(Streamer),
- LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
+ LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) {
DW = 0; MMI = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
@@ -335,7 +335,7 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
// Print source line info.
DIScope Scope = DLT.getScope();
// Omit the directory, because it's likely to be long and uninteresting.
- if (!Scope.isNull())
+ if (Scope.Verify())
CommentOS << Scope.getFilename();
else
CommentOS << "<unknown>";
@@ -893,6 +893,31 @@ void AsmPrinter::EmitInt64(uint64_t Value) const {
OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/);
}
+/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
+/// in bytes of the directive is specified by Size and Hi/Lo specify the
+/// labels. This implicitly uses .set if it is available.
+void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) const {
+ // Get the Hi-Lo expression.
+ const MCExpr *Diff =
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext),
+ MCSymbolRefExpr::Create(Lo, OutContext),
+ OutContext);
+
+ if (!MAI->hasSetDirective()) {
+ OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/);
+ return;
+ }
+
+ // Otherwise, emit with .set (aka assignment).
+ MCSymbol *SetLabel =
+ OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+ "set" + Twine(SetCounter++));
+ OutStreamer.EmitAssignment(SetLabel, Diff);
+ OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/);
+}
+
+
//===----------------------------------------------------------------------===//
// EmitAlignment - Emit an alignment directive to the specified power of
@@ -1287,18 +1312,16 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI,
if (DL.isUnknown())
return;
DILocation CurDLT = MF->getDILocation(DL);
- if (CurDLT.getScope().isNull())
+ if (!CurDLT.getScope().Verify())
return;
if (!BeforePrintingInsn) {
// After printing instruction
DW->EndScope(MI);
} else if (CurDLT.getNode() != PrevDLT) {
- unsigned L = DW->RecordSourceLine(CurDLT.getLineNumber(),
- CurDLT.getColumnNumber(),
- CurDLT.getScope().getNode());
- printLabel(L);
- O << '\n';
+ MCSymbol *L = DW->RecordSourceLine(CurDLT.getLineNumber(),
+ CurDLT.getColumnNumber(),
+ CurDLT.getScope().getNode());
DW->BeginScope(MI, L);
PrevDLT = CurDLT.getNode();
}
@@ -1529,12 +1552,17 @@ void AsmPrinter::printKill(const MachineInstr *MI) const {
/// printLabel - This method prints a local label used by debug and
/// exception handling tables.
void AsmPrinter::printLabelInst(const MachineInstr *MI) const {
- printLabel(MI->getOperand(0).getImm());
- OutStreamer.AddBlankLine();
+ MCSymbol *Sym =
+ OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+ "label" + Twine(MI->getOperand(0).getImm()));
+ OutStreamer.EmitLabel(Sym);
}
void AsmPrinter::printLabel(unsigned Id) const {
- O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':';
+ MCSymbol *Sym =
+ OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+ "label" + Twine(Id));
+ OutStreamer.EmitLabel(Sym);
}
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
@@ -1575,15 +1603,14 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
"_" + FnName.str() + "_" + BB->getName(),
Mangler::Private);
- return OutContext.GetOrCreateSymbol(NameResult.str());
+ return OutContext.GetOrCreateTemporarySymbol(NameResult.str());
}
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
- SmallString<60> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI"
- << getFunctionNumber() << '_' << CPID;
- return OutContext.GetOrCreateSymbol(Name.str());
+ return OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ + "_" + Twine(CPID));
}
/// GetJTISymbol - Return the symbol for the specified jump table entry.
@@ -1594,10 +1621,9 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
- SmallString<60> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << UID << "_set_" << MBBID;
- return OutContext.GetOrCreateSymbol(Name.str());
+ return OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
+ Twine(UID) + "_set_" + Twine(MBBID));
}
/// GetGlobalValueSymbol - Return the MCSymbol for the specified global
@@ -1605,7 +1631,10 @@ MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const {
SmallString<60> NameStr;
Mang->getNameWithPrefix(NameStr, GV, false);
- return OutContext.GetOrCreateSymbol(NameStr.str());
+
+ if (!GV->hasPrivateLinkage())
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+ return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
}
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
@@ -1617,7 +1646,9 @@ MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
SmallString<60> NameStr;
Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
NameStr.append(Suffix.begin(), Suffix.end());
- return OutContext.GetOrCreateSymbol(NameStr.str());
+ if (!GV->hasPrivateLinkage() && !ForcePrivate)
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+ return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
}
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 066aaab..7dc1fb5 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -3,7 +3,6 @@ add_llvm_library(LLVMAsmPrinter
DIE.cpp
DwarfDebug.cpp
DwarfException.cpp
- DwarfLabel.cpp
DwarfPrinter.cpp
DwarfWriter.cpp
OcamlGCPrinter.cpp
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 63360c0..e97754e 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -131,17 +131,15 @@ void DIE::print(raw_ostream &O, unsigned IncIndent) {
<< "Die: "
<< format("0x%lx", (long)(intptr_t)this)
<< ", Offset: " << Offset
- << ", Size: " << Size
- << "\n";
+ << ", Size: " << Size << "\n";
O << Indent
<< dwarf::TagString(Abbrev.getTag())
<< " "
- << dwarf::ChildrenString(Abbrev.getChildrenFlag());
+ << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n";
} else {
- O << "Size: " << Size;
+ O << "Size: " << Size << "\n";
}
- O << "\n";
const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();
@@ -254,51 +252,27 @@ void DIEString::print(raw_ostream &O) {
#endif
//===----------------------------------------------------------------------===//
-// DIEDwarfLabel Implementation
+// DIELabel Implementation
//===----------------------------------------------------------------------===//
/// EmitValue - Emit label value.
///
-void DIEDwarfLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
+void DIELabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
bool IsSmall = Form == dwarf::DW_FORM_data4;
- D->EmitReference(Label, false, IsSmall);
+ unsigned Size = IsSmall ? 4 : D->getTargetData()->getPointerSize();
+ D->getAsm()->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/);
}
/// SizeOf - Determine size of label value in bytes.
///
-unsigned DIEDwarfLabel::SizeOf(const TargetData *TD, unsigned Form) const {
+unsigned DIELabel::SizeOf(const TargetData *TD, unsigned Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
return TD->getPointerSize();
}
#ifndef NDEBUG
-void DIEDwarfLabel::print(raw_ostream &O) {
- O << "Lbl: ";
- Label.print(O);
-}
-#endif
-
-//===----------------------------------------------------------------------===//
-// DIEObjectLabel Implementation
-//===----------------------------------------------------------------------===//
-
-/// EmitValue - Emit label value.
-///
-void DIEObjectLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
- bool IsSmall = Form == dwarf::DW_FORM_data4;
- D->EmitReference(Sym, false, IsSmall);
-}
-
-/// SizeOf - Determine size of label value in bytes.
-///
-unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const {
- if (Form == dwarf::DW_FORM_data4) return 4;
- return TD->getPointerSize();
-}
-
-#ifndef NDEBUG
-void DIEObjectLabel::print(raw_ostream &O) {
- O << "Obj: " << Sym->getName();
+void DIELabel::print(raw_ostream &O) {
+ O << "Lbl: " << Label->getName();
}
#endif
@@ -310,10 +284,7 @@ void DIEObjectLabel::print(raw_ostream &O) {
///
void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const {
bool IsSmall = Form == dwarf::DW_FORM_data4;
- D->EmitSectionOffset(Label.getTag(), Section.getTag(),
- Label.getNumber(), Section.getNumber(),
- IsSmall, IsEH, UseSet);
- D->getAsm()->O << '\n'; // FIXME: Necesssary?
+ D->EmitSectionOffset(Label, Section, IsSmall, IsEH);
}
/// SizeOf - Determine size of delta value in bytes.
@@ -325,11 +296,8 @@ unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const {
#ifndef NDEBUG
void DIESectionOffset::print(raw_ostream &O) {
- O << "Off: ";
- Label.print(O);
- O << "-";
- Section.print(O);
- O << "-" << IsEH << "-" << UseSet;
+ O << "Off: " << Label->getName() << "-" << Section->getName()
+ << "-" << IsEH;
}
#endif
@@ -353,10 +321,7 @@ unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const {
#ifndef NDEBUG
void DIEDelta::print(raw_ostream &O) {
- O << "Del: ";
- LabelHi.print(O);
- O << "-";
- LabelLo.print(O);
+ O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
}
#endif
@@ -400,15 +365,13 @@ void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const {
case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
- case dwarf::DW_FORM_block: D->EmitULEB128(Size); break;
- default: llvm_unreachable("Improper form for block"); break;
+ case dwarf::DW_FORM_block: D->EmitULEB128(Size); break;
+ default: llvm_unreachable("Improper form for block"); break;
}
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
- for (unsigned i = 0, N = Values.size(); i < N; ++i) {
- Asm->O << '\n';
+ for (unsigned i = 0, N = Values.size(); i < N; ++i)
Values[i]->EmitValue(D, AbbrevData[i].getForm());
- }
}
/// SizeOf - Determine size of block data in bytes.
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index af90289..e08d748 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -14,7 +14,6 @@
#ifndef CODEGEN_ASMPRINTER_DIE_H__
#define CODEGEN_ASMPRINTER_DIE_H__
-#include "DwarfLabel.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
@@ -26,6 +25,7 @@ namespace llvm {
class DwarfPrinter;
class TargetData;
class MCSymbol;
+ class raw_ostream;
//===--------------------------------------------------------------------===//
/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
@@ -203,7 +203,6 @@ namespace llvm {
isInteger,
isString,
isLabel,
- isAsIsLabel,
isSectionOffset,
isDelta,
isEntry,
@@ -306,12 +305,12 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
- /// DIEDwarfLabel - A Dwarf internal label expression DIE.
+ /// DIELabel - A label expression DIE.
//
- class DIEDwarfLabel : public DIEValue {
- const DWLabel Label;
+ class DIELabel : public DIEValue {
+ const MCSymbol *Label;
public:
- explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
+ explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
/// EmitValue - Emit label value.
///
@@ -322,7 +321,7 @@ namespace llvm {
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
// Implement isa/cast/dyncast.
- static bool classof(const DIEDwarfLabel *) { return true; }
+ static bool classof(const DIELabel *) { return true; }
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
#ifndef NDEBUG
@@ -331,46 +330,17 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
- /// DIEObjectLabel - A label to an object in code or data.
- //
- class DIEObjectLabel : public DIEValue {
- const MCSymbol *Sym;
- public:
- explicit DIEObjectLabel(const MCSymbol *S)
- : DIEValue(isAsIsLabel), Sym(S) {}
-
- /// EmitValue - Emit label value.
- ///
- virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
-
- /// SizeOf - Determine size of label value in bytes.
- ///
- virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
-
- // Implement isa/cast/dyncast.
- static bool classof(const DIEObjectLabel *) { return true; }
- static bool classof(const DIEValue *L) {
- return L->getType() == isAsIsLabel;
- }
-
-#ifndef NDEBUG
- virtual void print(raw_ostream &O);
-#endif
- };
-
- //===--------------------------------------------------------------------===//
/// DIESectionOffset - A section offset DIE.
///
class DIESectionOffset : public DIEValue {
- const DWLabel Label;
- const DWLabel Section;
+ const MCSymbol *Label;
+ const MCSymbol *Section;
bool IsEH : 1;
- bool UseSet : 1;
public:
- DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec,
- bool isEH = false, bool useSet = true)
+ DIESectionOffset(const MCSymbol *Lab, const MCSymbol *Sec,
+ bool isEH = false)
: DIEValue(isSectionOffset), Label(Lab), Section(Sec),
- IsEH(isEH), UseSet(useSet) {}
+ IsEH(isEH) {}
/// EmitValue - Emit section offset.
///
@@ -395,10 +365,10 @@ namespace llvm {
/// DIEDelta - A simple label difference DIE.
///
class DIEDelta : public DIEValue {
- const DWLabel LabelHi;
- const DWLabel LabelLo;
+ const MCSymbol *LabelHi;
+ const MCSymbol *LabelLo;
public:
- DIEDelta(const DWLabel &Hi, const DWLabel &Lo)
+ DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
/// EmitValue - Emit delta value.
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 5ad1e5e..36be5b9 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -10,14 +10,16 @@
// This file contains support for writing dwarf debug info into asm files.
//
//===----------------------------------------------------------------------===//
+
#define DEBUG_TYPE "dwarfdebug"
#include "DwarfDebug.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
@@ -170,8 +172,8 @@ class DbgScope {
// Location at which this scope is inlined.
AssertingVH<MDNode> InlinedAtLocation;
bool AbstractScope; // Abstract Scope
- unsigned StartLabelID; // Label ID of the beginning of scope.
- unsigned EndLabelID; // Label ID of the end of scope.
+ MCSymbol *StartLabel; // Label ID of the beginning of scope.
+ MCSymbol *EndLabel; // Label ID of the end of scope.
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope.
@@ -182,7 +184,7 @@ class DbgScope {
public:
DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
- StartLabelID(0), EndLabelID(0),
+ StartLabel(0), EndLabel(0),
LastInsn(0), FirstInsn(0), IndentLevel(0) {}
virtual ~DbgScope();
@@ -194,12 +196,12 @@ public:
return InlinedAtLocation;
}
MDNode *getScopeNode() const { return Desc.getNode(); }
- unsigned getStartLabelID() const { return StartLabelID; }
- unsigned getEndLabelID() const { return EndLabelID; }
+ MCSymbol *getStartLabel() const { return StartLabel; }
+ MCSymbol *getEndLabel() const { return EndLabel; }
SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
SmallVector<DbgVariable *, 8> &getVariables() { return Variables; }
- void setStartLabelID(unsigned S) { StartLabelID = S; }
- void setEndLabelID(unsigned E) { EndLabelID = E; }
+ void setStartLabel(MCSymbol *S) { StartLabel = S; }
+ void setEndLabel(MCSymbol *E) { EndLabel = E; }
void setLastInsn(const MachineInstr *MI) { LastInsn = MI; }
const MachineInstr *getLastInsn() { return LastInsn; }
void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; }
@@ -263,7 +265,7 @@ void DbgScope::dump() const {
err.indent(IndentLevel);
MDNode *N = Desc.getNode();
N->dump();
- err << " [" << StartLabelID << ", " << EndLabelID << "]\n";
+ err << " [" << StartLabel << ", " << EndLabel << "]\n";
if (AbstractScope)
err << "Abstract Scope\n";
@@ -288,7 +290,7 @@ DbgScope::~DbgScope() {
} // end llvm namespace
DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
- : DwarfPrinter(OS, A, T, "dbg"), ModuleCU(0),
+ : DwarfPrinter(OS, A, T), ModuleCU(0),
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
DIEValues(), StringPool(),
SectionSourceLines(), didInitial(false), shouldEmit(false),
@@ -366,17 +368,8 @@ void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
/// addLabel - Add a Dwarf label attribute data and value.
///
void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label) {
- DIEValue *Value = new DIEDwarfLabel(Label);
- DIEValues.push_back(Value);
- Die->addValue(Attribute, Form, Value);
-}
-
-/// addObjectLabel - Add an non-Dwarf label attribute data and value.
-///
-void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const MCSymbol *Sym) {
- DIEValue *Value = new DIEObjectLabel(Sym);
+ const MCSymbol *Label) {
+ DIEValue *Value = new DIELabel(Label);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
}
@@ -384,9 +377,9 @@ void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
/// addSectionOffset - Add a section offset label attribute data and value.
///
void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label, const DWLabel &Section,
- bool isEH, bool useSet) {
- DIEValue *Value = new DIESectionOffset(Label, Section, isEH, useSet);
+ const MCSymbol *Label,const MCSymbol *Section,
+ bool isEH) {
+ DIEValue *Value = new DIESectionOffset(Label, Section, isEH);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
}
@@ -394,7 +387,7 @@ void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
/// addDelta - Add a label delta attribute data and value.
///
void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Hi, const DWLabel &Lo) {
+ const MCSymbol *Hi, const MCSymbol *Lo) {
DIEValue *Value = new DIEDelta(Hi, Lo);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
@@ -413,11 +406,12 @@ void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form,
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) {
// If there is no compile unit specified, don't add a line #.
- if (V->getCompileUnit().isNull())
+ if (!V->getCompileUnit().Verify())
return;
unsigned Line = V->getLineNumber();
- unsigned FileID = findCompileUnit(V->getCompileUnit())->getID();
+ unsigned FileID = GetOrCreateSourceID(V->getContext().getDirectory(),
+ V->getContext().getFilename());
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
@@ -427,11 +421,12 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) {
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) {
// If there is no compile unit specified, don't add a line #.
- if (G->getCompileUnit().isNull())
+ if (!G->getCompileUnit().Verify())
return;
unsigned Line = G->getLineNumber();
- unsigned FileID = findCompileUnit(G->getCompileUnit())->getID();
+ unsigned FileID = GetOrCreateSourceID(G->getContext().getDirectory(),
+ G->getContext().getFilename());
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
@@ -441,15 +436,17 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) {
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) {
// If there is no compile unit specified, don't add a line #.
- if (SP->getCompileUnit().isNull())
+ if (!SP->getCompileUnit().Verify())
return;
// If the line number is 0, don't add it.
if (SP->getLineNumber() == 0)
return;
-
unsigned Line = SP->getLineNumber();
- unsigned FileID = findCompileUnit(SP->getCompileUnit())->getID();
+ if (!SP->getContext().Verify())
+ return;
+ unsigned FileID = GetOrCreateSourceID(SP->getContext().getDirectory(),
+ SP->getContext().getFilename());
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
@@ -460,11 +457,14 @@ void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) {
void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
// If there is no compile unit specified, don't add a line #.
DICompileUnit CU = Ty->getCompileUnit();
- if (CU.isNull())
+ if (!CU.Verify())
return;
unsigned Line = Ty->getLineNumber();
- unsigned FileID = findCompileUnit(CU)->getID();
+ if (!Ty->getContext().Verify())
+ return;
+ unsigned FileID = GetOrCreateSourceID(Ty->getContext().getDirectory(),
+ Ty->getContext().getFilename());
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
@@ -474,7 +474,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) {
// If there is no compile unit specified, don't add a line #.
- if (NS->getCompileUnit().isNull())
+ if (!NS->getCompileUnit().Verify())
return;
unsigned Line = NS->getLineNumber();
@@ -526,12 +526,8 @@ DIType DwarfDebug::getBlockByrefType(DIType Ty, std::string Name) {
}
DICompositeType blockStruct = DICompositeType(subType.getNode());
-
DIArray Elements = blockStruct.getTypeArray();
- if (Elements.isNull())
- return Ty;
-
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
DIDerivedType DT = DIDerivedType(Element.getNode());
@@ -677,7 +673,6 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die,
DIDescriptor varField = DIDescriptor();
DIDescriptor forwardingField = DIDescriptor();
-
for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) {
DIDescriptor Element = Fields.getElement(i);
DIDerivedType DT = DIDerivedType(Element.getNode());
@@ -688,10 +683,6 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die,
varField = Element;
}
- assert(!varField.isNull() && "Can't find byref variable in Block struct");
- assert(!forwardingField.isNull()
- && "Can't find forwarding field in Block struct");
-
// Get the offsets for the forwarding field and the variable field.
unsigned int forwardingFieldOffset =
DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3;
@@ -781,9 +772,7 @@ void DwarfDebug::addAddress(DIE *Die, unsigned Attribute,
/// addToContextOwner - Add Die into the list of its context owner's children.
void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
- if (Context.isNull())
- ModuleCU->addDie(Die);
- else if (Context.isType()) {
+ if (Context.isType()) {
DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode()));
ContextDIE->addChild(Die);
} else if (Context.isNameSpace()) {
@@ -820,7 +809,7 @@ DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) {
/// addType - Add a new type attribute to the specified entity.
void DwarfDebug::addType(DIE *Entity, DIType Ty) {
- if (Ty.isNull())
+ if (!Ty.isValid())
return;
// Check for pre-existence.
@@ -906,9 +895,9 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
// Add enumerators to enumeration type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIE *ElemDie = NULL;
- DIEnumerator Enum(Elements.getElement(i).getNode());
- if (!Enum.isNull()) {
- ElemDie = constructEnumTypeDIE(&Enum);
+ DIDescriptor Enum(Elements.getElement(i).getNode());
+ if (Enum.isEnumerator()) {
+ ElemDie = constructEnumTypeDIE(DIEnumerator(Enum.getNode()));
Buffer.addChild(ElemDie);
}
}
@@ -939,18 +928,17 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
DIArray Elements = CTy.getTypeArray();
// A forward struct declared type may not have elements available.
- if (Elements.isNull())
+ unsigned N = Elements.getNumElements();
+ if (N == 0)
break;
// Add elements to structure type.
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
+ for (unsigned i = 0; i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
- if (Element.isNull())
- continue;
DIE *ElemDie = NULL;
- if (Element.getTag() == dwarf::DW_TAG_subprogram)
+ if (Element.isSubprogram())
ElemDie = createSubprogramDIE(DISubprogram(Element.getNode()));
- else if (Element.getTag() == dwarf::DW_TAG_auto_variable) {
+ else if (Element.isVariable()) {
DIVariable DV(Element.getNode());
ElemDie = new DIE(dwarf::DW_TAG_variable);
addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
@@ -959,8 +947,10 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
addSourceLine(ElemDie, &DV);
- } else
+ } else if (Element.isDerivedType())
ElemDie = createMemberDIE(DIDerivedType(Element.getNode()));
+ else
+ continue;
Buffer.addChild(ElemDie);
}
@@ -973,7 +963,7 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
dwarf::DW_FORM_data1, RLang);
DICompositeType ContainingType = CTy.getContainingType();
- if (!ContainingType.isNull())
+ if (DIDescriptor(ContainingType.getNode()).isCompositeType())
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
getOrCreateTypeDIE(DIType(ContainingType.getNode())));
break;
@@ -1051,11 +1041,11 @@ void DwarfDebug::constructArrayTypeDIE(DIE &Buffer,
}
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
-DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator *ETy) {
+DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator ETy) {
DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator);
- StringRef Name = ETy->getName();
+ StringRef Name = ETy.getName();
addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
- int64_t Value = ETy->getEnumValue();
+ int64_t Value = ETy.getEnumValue();
addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value);
return Enumerator;
}
@@ -1199,7 +1189,7 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
- if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
+ if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type)
addType(SPDie, SPTy);
else
addType(SPDie, DIType(Args.getElement(0).getNode()));
@@ -1243,16 +1233,6 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
return SPDie;
}
-/// findCompileUnit - Get the compile unit for the given descriptor.
-///
-CompileUnit *DwarfDebug::findCompileUnit(DICompileUnit Unit) {
- DenseMap<Value *, CompileUnit *>::const_iterator I =
- CompileUnitMap.find(Unit.getNode());
- if (I == CompileUnitMap.end())
- return constructCompileUnit(Unit.getNode());
- return I->second;
-}
-
/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
/// Initialize scope and update scope hierarchy.
DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
@@ -1282,11 +1262,9 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
Parent->addScope(NScope);
} else if (DIDescriptor(N).isLexicalBlock()) {
DILexicalBlock DB(N);
- if (!DB.getContext().isNull()) {
- Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt);
- NScope->setParent(Parent);
- Parent->addScope(NScope);
- }
+ Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt);
+ NScope->setParent(Parent);
+ Parent->addScope(NScope);
}
NScope->setFirstInsn(MI);
@@ -1318,8 +1296,7 @@ DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) {
if (Scope.isLexicalBlock()) {
DILexicalBlock DB(N);
DIDescriptor ParentDesc = DB.getContext();
- if (!ParentDesc.isNull())
- Parent = getOrCreateAbstractScope(ParentDesc.getNode());
+ Parent = getOrCreateAbstractScope(ParentDesc.getNode());
}
AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
@@ -1371,9 +1348,9 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
}
addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
+ getDWLabel("func_begin", SubprogramCount));
addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
+ getDWLabel("func_end", SubprogramCount));
MachineLocation Location(RI->getFrameRegister(*MF));
addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
@@ -1386,27 +1363,21 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
/// constructLexicalScope - Construct new DW_TAG_lexical_block
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
- unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
- unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
-
- // Ignore empty scopes.
- if (StartID == EndID && StartID != 0)
- return NULL;
+ MCSymbol *Start = Scope->getStartLabel();
+ MCSymbol *End = Scope->getEndLabel();
+ if (Start == 0) return 0;
+ assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
+ assert(End->isDefined() && "Invalid end label for an inlined scope!");
+
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- StartID ?
- DWLabel("label", StartID)
- : DWLabel("func_begin", SubprogramCount));
+ Start ? Start : getDWLabel("func_begin", SubprogramCount));
addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- EndID ?
- DWLabel("label", EndID)
- : DWLabel("func_end", SubprogramCount));
-
-
+ End ? End : getDWLabel("func_end", SubprogramCount));
return ScopeDIE;
}
@@ -1415,17 +1386,17 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
/// a function. Construct DIE to represent this concrete inlined copy
/// of the function.
DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
- unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
- unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
- assert (StartID && "Invalid starting label for an inlined scope!");
- assert (EndID && "Invalid end label for an inlined scope!");
- // Ignore empty scopes.
- if (StartID == EndID && StartID != 0)
+ MCSymbol *StartLabel = Scope->getStartLabel();
+ MCSymbol *EndLabel = Scope->getEndLabel();
+ if (StartLabel == 0) return 0;
+
+ assert(StartLabel->isDefined() &&
+ "Invalid starting label for an inlined scope!");
+ assert(EndLabel->isDefined() &&
+ "Invalid end label for an inlined scope!");
+ if (!Scope->getScopeNode())
return NULL;
-
DIScope DS(Scope->getScopeNode());
- if (DS.isNull())
- return NULL;
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
DISubprogram InlinedSP = getDISubprogram(DS.getNode());
@@ -1434,10 +1405,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, OriginDIE);
- addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("label", StartID));
- addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("label", EndID));
+ addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel);
+ addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel);
InlinedSubprogramDIEs.insert(OriginDIE);
@@ -1446,11 +1415,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
I = InlineInfo.find(InlinedSP.getNode());
if (I == InlineInfo.end()) {
- InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID,
+ InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartLabel,
ScopeDIE));
InlinedSPNodes.push_back(InlinedSP.getNode());
} else
- I->second.push_back(std::make_pair(StartID, ScopeDIE));
+ I->second.push_back(std::make_pair(StartLabel, ScopeDIE));
StringPool.insert(InlinedSP.getName());
StringPool.insert(getRealLinkageName(InlinedSP.getLinkageName()));
@@ -1547,15 +1516,12 @@ void DwarfDebug::addPubTypes(DISubprogram SP) {
return;
DIArray Args = SPTy.getTypeArray();
- if (Args.isNull())
- return;
-
for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) {
DIType ATy(Args.getElement(i).getNode());
- if (ATy.isNull())
+ if (!ATy.isValid())
continue;
DICompositeType CATy = getDICompositeType(ATy);
- if (!CATy.isNull() && !CATy.getName().empty()) {
+ if (DIDescriptor(CATy.getNode()).Verify() && !CATy.getName().empty()) {
if (DIEEntry *Entry = ModuleCU->getDIEEntry(CATy.getNode()))
ModuleCU->addGlobalType(CATy.getName(), Entry->getEntry());
}
@@ -1564,26 +1530,24 @@ void DwarfDebug::addPubTypes(DISubprogram SP) {
/// constructScopeDIE - Construct a DIE for this scope.
DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
- if (!Scope)
- return NULL;
- DIScope DS(Scope->getScopeNode());
- if (DS.isNull())
- return NULL;
-
- DIE *ScopeDIE = NULL;
- if (Scope->getInlinedAt())
- ScopeDIE = constructInlinedScopeDIE(Scope);
- else if (DS.isSubprogram()) {
- if (Scope->isAbstractScope())
- ScopeDIE = ModuleCU->getDIE(DS.getNode());
- else
- ScopeDIE = updateSubprogramScopeDIE(DS.getNode());
- }
- else {
- ScopeDIE = constructLexicalScopeDIE(Scope);
- if (!ScopeDIE) return NULL;
- }
-
+ if (!Scope || !Scope->getScopeNode())
+ return NULL;
+
+ DIScope DS(Scope->getScopeNode());
+ DIE *ScopeDIE = NULL;
+ if (Scope->getInlinedAt())
+ ScopeDIE = constructInlinedScopeDIE(Scope);
+ else if (DS.isSubprogram()) {
+ if (Scope->isAbstractScope())
+ ScopeDIE = ModuleCU->getDIE(DS.getNode());
+ else
+ ScopeDIE = updateSubprogramScopeDIE(DS.getNode());
+ }
+ else {
+ ScopeDIE = constructLexicalScopeDIE(Scope);
+ if (!ScopeDIE) return NULL;
+ }
+
// Add variables to scope.
SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
@@ -1665,8 +1629,9 @@ CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) {
unsigned ID = GetOrCreateSourceID(Dir, FN);
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+ // FIXME: Why getting the delta between two identical labels??
addSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
- DWLabel("section_line", 0), DWLabel("section_line", 0),
+ getTempLabel("section_line"), getTempLabel("section_line"),
false);
addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
DIUnit.getProducer());
@@ -1695,8 +1660,6 @@ CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) {
ModuleCU = Unit;
}
- CompileUnitMap[DIUnit.getNode()] = Unit;
- CompileUnits.push_back(Unit);
return Unit;
}
@@ -1730,16 +1693,16 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
dwarf::DW_FORM_ref4, VariableDie);
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
- addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
- Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
+ addLabel(Block, 0, dwarf::DW_FORM_udata,
+ Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
addUInt(VariableDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
ModuleCU->addDie(VariableSpecDIE);
} else {
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
- addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
- Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
+ addLabel(Block, 0, dwarf::DW_FORM_udata,
+ Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
addBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
}
addToContextOwner(VariableDie, GVContext);
@@ -1802,17 +1765,8 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
E = DbgFinder.compile_unit_end(); I != E; ++I)
constructCompileUnit(*I);
- if (CompileUnits.empty()) {
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return;
- }
-
- // If main compile unit for this module is not seen than randomly
- // select first compile unit.
if (!ModuleCU)
- ModuleCU = CompileUnits[0];
+ return;
// Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
@@ -1890,14 +1844,14 @@ void DwarfDebug::endModule() {
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
- EmitLabel("text_end", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("text_end"));
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
- EmitLabel("data_end", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("data_end"));
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->OutStreamer.SwitchSection(SectionMap[i]);
- EmitLabel("section_end", i);
+ Asm->OutStreamer.EmitLabel(getDWLabel("section_end", i));
}
// Emit common frame information.
@@ -1997,14 +1951,14 @@ void DwarfDebug::collectVariableInfo() {
}
/// beginScope - Process beginning of a scope starting at Label.
-void DwarfDebug::beginScope(const MachineInstr *MI, unsigned Label) {
+void DwarfDebug::beginScope(const MachineInstr *MI, MCSymbol *Label) {
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
ScopeVector &SD = I->second;
for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
- (*SDI)->setStartLabelID(Label);
+ (*SDI)->setStartLabel(Label);
}
/// endScope - Process end of a scope.
@@ -2013,14 +1967,13 @@ void DwarfDebug::endScope(const MachineInstr *MI) {
if (I == DbgScopeEndMap.end())
return;
- unsigned Label = MMI->NextLabelID();
- Asm->printLabel(Label);
- O << '\n';
+ MCSymbol *Label = getDWLabel("label", MMI->NextLabelID());
+ Asm->OutStreamer.EmitLabel(Label);
- SmallVector<DbgScope *, 2> &SD = I->second;
+ SmallVector<DbgScope*, 2> &SD = I->second;
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
- (*SDI)->setEndLabelID(Label);
+ (*SDI)->setEndLabel(Label);
return;
}
@@ -2069,7 +2022,6 @@ bool DwarfDebug::extractScopeInformation() {
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
- if (DLTScope.isNull()) continue;
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
@@ -2089,7 +2041,6 @@ bool DwarfDebug::extractScopeInformation() {
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
- if (DLTScope.isNull()) continue;
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
@@ -2159,24 +2110,24 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
collectVariableInfo();
// Assumes in correct section after the entry point.
- EmitLabel("func_begin", ++SubprogramCount);
+ Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount));
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
DILocation DLT = MF->getDILocation(FDL);
- unsigned LabelID = 0;
DISubprogram SP = getDISubprogram(DLT.getScope().getNode());
- if (!SP.isNull())
- LabelID = recordSourceLine(SP.getLineNumber(), 0,
- DLT.getScope().getNode());
- else
- LabelID = recordSourceLine(DLT.getLineNumber(),
- DLT.getColumnNumber(),
- DLT.getScope().getNode());
- Asm->printLabel(LabelID);
- O << '\n';
+ unsigned Line, Col;
+ if (SP.Verify()) {
+ Line = SP.getLineNumber();
+ Col = 0;
+ } else {
+ Line = DLT.getLineNumber();
+ Col = DLT.getColumnNumber();
+ }
+
+ recordSourceLine(Line, Col, DLT.getScope().getNode());
}
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
@@ -2195,7 +2146,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
if (CurrentFnDbgScope) {
// Define end label for subprogram.
- EmitLabel("func_end", SubprogramCount);
+ Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount));
// Get function line info.
if (!Lines.empty()) {
@@ -2232,11 +2183,10 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
DebugTimer->stopTimer();
}
-/// recordSourceLine - Records location information and associates it with a
-/// label. Returns a unique label ID used to generate a label and provide
-/// correspondence to the source line list.
-unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col,
- MDNode *S) {
+/// recordSourceLine - Register a source line with debug info. Returns the
+/// unique label that was emitted and which provides correspondence to
+/// the source line list.
+MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
if (!MMI)
return 0;
@@ -2269,7 +2219,9 @@ unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col,
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
- return ID;
+ MCSymbol *Label = getDWLabel("label", ID);
+ Asm->OutStreamer.EmitLabel(Label);
+ return Label;
}
/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
@@ -2367,38 +2319,38 @@ void DwarfDebug::emitInitial() {
// Dwarf sections base addresses.
if (MAI->doesDwarfRequireFrameSection()) {
Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection());
- EmitLabel("section_debug_frame", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame"));
}
Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
- EmitLabel("section_info", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_info"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
- EmitLabel("section_abbrev", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
- EmitLabel("section_aranges", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges"));
if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
Asm->OutStreamer.SwitchSection(LineInfoDirective);
- EmitLabel("section_macinfo", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo"));
}
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
- EmitLabel("section_line", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_line"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
- EmitLabel("section_loc", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_loc"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
- EmitLabel("section_pubnames", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection());
- EmitLabel("section_pubtypes", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
- EmitLabel("section_str", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_str"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
- EmitLabel("section_ranges", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges"));
Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
- EmitLabel("text_begin", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("text_begin"));
Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
- EmitLabel("data_begin", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("data_begin"));
}
/// emitDIE - Recusively Emits a debug information entry.
@@ -2408,8 +2360,6 @@ void DwarfDebug::emitDIE(DIE *Die) {
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
- Asm->O << '\n';
-
// Emit the code (index) for the abbreviation.
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
@@ -2444,7 +2394,6 @@ void DwarfDebug::emitDIE(DIE *Die) {
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(this, Form);
- O << "\n"; // REMOVE This once all EmitValue impls emit their own newline.
break;
}
}
@@ -2456,7 +2405,9 @@ void DwarfDebug::emitDIE(DIE *Die) {
for (unsigned j = 0, M = Children.size(); j < M; ++j)
emitDIE(Children[j]);
- Asm->EmitInt8(0); EOL("End Of Children Mark");
+ if (Asm->VerboseAsm)
+ Asm->OutStreamer.AddComment("End Of Children Mark");
+ Asm->EmitInt8(0);
}
}
@@ -2469,7 +2420,7 @@ void DwarfDebug::emitDebugInfo() {
DIE *Die = ModuleCU->getCUDie();
// Emit the compile units header.
- EmitLabel("info_begin", ModuleCU->getID());
+ Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->getID()));
// Emit size of content not including length itself
unsigned ContentSize = Die->getSize() +
@@ -2478,20 +2429,24 @@ void DwarfDebug::emitDebugInfo() {
sizeof(int8_t) + // Pointer Size (in bytes)
sizeof(int32_t); // FIXME - extra pad for gdb bug.
- Asm->EmitInt32(ContentSize); EOL("Length of Compilation Unit Info");
- Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
- EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false);
- EOL("Offset Into Abbrev. Section");
- Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
+ Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
+ Asm->EmitInt32(ContentSize);
+ Asm->OutStreamer.AddComment("DWARF version number");
+ Asm->EmitInt16(dwarf::DWARF_VERSION);
+ Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
+ EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
+ true, false);
+ Asm->OutStreamer.AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(TD->getPointerSize());
emitDIE(Die);
// FIXME - extra padding for gdb bug.
- Asm->EmitInt8(0); EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); EOL("Extra Pad For GDB");
- EmitLabel("info_end", ModuleCU->getID());
- Asm->O << '\n';
+ Asm->OutStreamer.AddComment("4 extra padding bytes for GDB");
+ Asm->EmitInt8(0);
+ Asm->EmitInt8(0);
+ Asm->EmitInt8(0);
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID()));
}
/// emitAbbreviations - Emit the abbreviation section.
@@ -2503,7 +2458,7 @@ void DwarfDebug::emitAbbreviations() const {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAbbrevSection());
- EmitLabel("abbrev_begin", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin"));
// For each abbrevation.
for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
@@ -2515,14 +2470,12 @@ void DwarfDebug::emitAbbreviations() const {
// Emit the abbreviations data.
Abbrev->Emit(this);
- Asm->O << '\n';
}
// Mark end of abbreviations.
EmitULEB128(0, "EOM(3)");
- EmitLabel("abbrev_end", 0);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end"));
}
}
@@ -2531,13 +2484,22 @@ void DwarfDebug::emitAbbreviations() const {
///
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
// Define last address of section.
- Asm->EmitInt8(0); EOL("Extended Op");
- Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
- Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
- EmitReference("section_end", SectionEnd); EOL("Section end label");
+ Asm->OutStreamer.AddComment("Extended Op");
+ Asm->EmitInt8(0);
+
+ Asm->OutStreamer.AddComment("Op size");
+ Asm->EmitInt8(TD->getPointerSize() + 1);
+ Asm->OutStreamer.AddComment("DW_LNE_set_address");
+ Asm->EmitInt8(dwarf::DW_LNE_set_address);
+
+ Asm->OutStreamer.AddComment("Section end label");
+
+ Asm->OutStreamer.EmitSymbolValue(getDWLabel("section_end", SectionEnd),
+ TD->getPointerSize(), 0/*AddrSpace*/);
// Mark end of matrix.
- Asm->EmitInt8(0); EOL("DW_LNE_end_sequence");
+ Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
+ Asm->EmitInt8(0);
Asm->EmitInt8(1);
Asm->EmitInt8(1);
}
@@ -2560,32 +2522,48 @@ void DwarfDebug::emitDebugLines() {
Asm->getObjFileLowering().getDwarfLineSection());
// Construct the section header.
- EmitDifference("line_end", 0, "line_begin", 0, true);
- EOL("Length of Source Line Info");
- EmitLabel("line_begin", 0);
+ Asm->OutStreamer.AddComment("Length of Source Line Info");
+ EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true);
+ Asm->OutStreamer.EmitLabel(getTempLabel("line_begin"));
- Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
+ Asm->OutStreamer.AddComment("DWARF version number");
+ Asm->EmitInt16(dwarf::DWARF_VERSION);
- EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
- EOL("Prolog Length");
- EmitLabel("line_prolog_begin", 0);
+ Asm->OutStreamer.AddComment("Prolog Length");
+ EmitDifference(getTempLabel("line_prolog_end"),
+ getTempLabel("line_prolog_begin"), true);
+ Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin"));
- Asm->EmitInt8(1); EOL("Minimum Instruction Length");
- Asm->EmitInt8(1); EOL("Default is_stmt_start flag");
- Asm->EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)");
- Asm->EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)");
- Asm->EmitInt8(-MinLineDelta); EOL("Special Opcode Base");
+ Asm->OutStreamer.AddComment("Minimum Instruction Length");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("Default is_stmt_start flag");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("Line Base Value (Special Opcodes)");
+ Asm->EmitInt8(MinLineDelta);
+ Asm->OutStreamer.AddComment("Line Range Value (Special Opcodes)");
+ Asm->EmitInt8(MaxLineDelta);
+ Asm->OutStreamer.AddComment("Special Opcode Base");
+ Asm->EmitInt8(-MinLineDelta);
// Line number standard opcode encodings argument count
- Asm->EmitInt8(0); EOL("DW_LNS_copy arg count");
- Asm->EmitInt8(1); EOL("DW_LNS_advance_pc arg count");
- Asm->EmitInt8(1); EOL("DW_LNS_advance_line arg count");
- Asm->EmitInt8(1); EOL("DW_LNS_set_file arg count");
- Asm->EmitInt8(1); EOL("DW_LNS_set_column arg count");
- Asm->EmitInt8(0); EOL("DW_LNS_negate_stmt arg count");
- Asm->EmitInt8(0); EOL("DW_LNS_set_basic_block arg count");
- Asm->EmitInt8(0); EOL("DW_LNS_const_add_pc arg count");
- Asm->EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count");
+ Asm->OutStreamer.AddComment("DW_LNS_copy arg count");
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.AddComment("DW_LNS_advance_pc arg count");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("DW_LNS_advance_line arg count");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("DW_LNS_set_file arg count");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("DW_LNS_set_column arg count");
+ Asm->EmitInt8(1);
+ Asm->OutStreamer.AddComment("DW_LNS_negate_stmt arg count");
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.AddComment("DW_LNS_set_basic_block arg count");
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.AddComment("DW_LNS_const_add_pc arg count");
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.AddComment("DW_LNS_fixed_advance_pc arg count");
+ Asm->EmitInt8(1);
// Emit directories.
for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
@@ -2594,7 +2572,8 @@ void DwarfDebug::emitDebugLines() {
Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
}
- Asm->EmitInt8(0); EOL("End of directories");
+ Asm->OutStreamer.AddComment("End of directories");
+ Asm->EmitInt8(0);
// Emit files.
for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
@@ -2609,9 +2588,10 @@ void DwarfDebug::emitDebugLines() {
EmitULEB128(0, "File size");
}
- Asm->EmitInt8(0); EOL("End of files");
+ Asm->OutStreamer.AddComment("End of files");
+ Asm->EmitInt8(0);
- EmitLabel("line_prolog_end", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end"));
// A sequence for each text section.
unsigned SecSrcLinesSize = SectionSourceLines.size();
@@ -2620,13 +2600,6 @@ void DwarfDebug::emitDebugLines() {
// Isolate current sections line info.
const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
- /*if (Asm->isVerbose()) {
- const MCSection *S = SectionMap[j + 1];
- O << '\t' << MAI->getCommentString() << " Section"
- << S->getName() << '\n';
- }*/
- Asm->O << '\n';
-
// Dwarf assumes we start with first line of first source file.
unsigned Source = 1;
unsigned Line = 1;
@@ -2634,32 +2607,38 @@ void DwarfDebug::emitDebugLines() {
// Construct rows of the address, source, line, column matrix.
for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
const SrcLineInfo &LineInfo = LineInfos[i];
- unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
- if (!LabelID) continue;
+ unsigned LabelID = LineInfo.getLabelID();
+ if (MMI->isLabelDeleted(LabelID)) continue;
if (LineInfo.getLine() == 0) continue;
- if (!Asm->isVerbose())
- Asm->O << '\n';
- else {
- std::pair<unsigned, unsigned> SourceID =
+ if (Asm->isVerbose()) {
+ std::pair<unsigned, unsigned> SrcID =
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
- O << '\t' << MAI->getCommentString() << ' '
- << getSourceDirectoryName(SourceID.first) << '/'
- << getSourceFileName(SourceID.second)
- << ':' << utostr_32(LineInfo.getLine()) << '\n';
+ Asm->OutStreamer.AddComment(Twine(getSourceDirectoryName(SrcID.first)) +
+ "/" +
+ Twine(getSourceFileName(SrcID.second)) +
+ ":" + Twine(LineInfo.getLine()));
}
// Define the line address.
- Asm->EmitInt8(0); EOL("Extended Op");
- Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
- Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
- EmitReference("label", LabelID); EOL("Location label");
-
+ Asm->OutStreamer.AddComment("Extended Op");
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.AddComment("Op size");
+ Asm->EmitInt8(TD->getPointerSize() + 1);
+
+ Asm->OutStreamer.AddComment("DW_LNE_set_address");
+ Asm->EmitInt8(dwarf::DW_LNE_set_address);
+
+ Asm->OutStreamer.AddComment("Location label");
+ Asm->OutStreamer.EmitSymbolValue(getDWLabel("label", LabelID),
+ TD->getPointerSize(), 0/*AddrSpace*/);
+
// If change of source, then switch to the new source.
if (Source != LineInfo.getSourceID()) {
Source = LineInfo.getSourceID();
- Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file");
+ Asm->OutStreamer.AddComment("DW_LNS_set_file");
+ Asm->EmitInt8(dwarf::DW_LNS_set_file);
EmitULEB128(Source, "New Source");
}
@@ -2675,17 +2654,20 @@ void DwarfDebug::emitDebugLines() {
// If delta is small enough and in range...
if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
// ... then use fast opcode.
- Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
+ Asm->OutStreamer.AddComment("Line Delta");
+ Asm->EmitInt8(Delta - MinLineDelta);
} else {
// ... otherwise use long hand.
+ Asm->OutStreamer.AddComment("DW_LNS_advance_line");
Asm->EmitInt8(dwarf::DW_LNS_advance_line);
- EOL("DW_LNS_advance_line");
EmitSLEB128(Offset, "Line Offset");
- Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
+ Asm->OutStreamer.AddComment("DW_LNS_copy");
+ Asm->EmitInt8(dwarf::DW_LNS_copy);
}
} else {
// Copy the previous row (different address or source)
- Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
+ Asm->OutStreamer.AddComment("DW_LNS_copy");
+ Asm->EmitInt8(dwarf::DW_LNS_copy);
}
}
@@ -2698,8 +2680,7 @@ void DwarfDebug::emitDebugLines() {
// put into it, emit an empty table.
emitEndOfLineMatrix(1);
- EmitLabel("line_end", 0);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getTempLabel("line_end"));
}
/// emitCommonDebugFrame - Emit common frame info into a debug frame section.
@@ -2717,22 +2698,22 @@ void DwarfDebug::emitCommonDebugFrame() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
- EmitLabel("debug_frame_common", 0);
- EmitDifference("debug_frame_common_end", 0,
- "debug_frame_common_begin", 0, true);
- EOL("Length of Common Information Entry");
+ Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common"));
+ Asm->OutStreamer.AddComment("Length of Common Information Entry");
+ EmitDifference(getTempLabel("debug_frame_common_end"),
+ getTempLabel("debug_frame_common_begin"), true);
- EmitLabel("debug_frame_common_begin", 0);
+ Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin"));
+ Asm->OutStreamer.AddComment("CIE Identifier Tag");
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
- EOL("CIE Identifier Tag");
+ Asm->OutStreamer.AddComment("CIE Version");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
- EOL("CIE Version");
+ Asm->OutStreamer.AddComment("CIE Augmentation");
Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
- EOL("CIE Augmentation");
EmitULEB128(1, "CIE Code Alignment Factor");
EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
+ Asm->OutStreamer.AddComment("CIE RA Column");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
- EOL("CIE RA Column");
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
@@ -2740,8 +2721,7 @@ void DwarfDebug::emitCommonDebugFrame() {
EmitFrameMoves(NULL, 0, Moves, false);
Asm->EmitAlignment(2, 0, 0, false);
- EmitLabel("debug_frame_common_end", 0);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end"));
}
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
@@ -2755,28 +2735,34 @@ DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
- EmitDifference("debug_frame_end", DebugFrameInfo.Number,
- "debug_frame_begin", DebugFrameInfo.Number, true);
- EOL("Length of Frame Information Entry");
+ Asm->OutStreamer.AddComment("Length of Frame Information Entry");
+ EmitDifference(getDWLabel("debug_frame_end", DebugFrameInfo.Number),
+ getDWLabel("debug_frame_begin", DebugFrameInfo.Number), true);
- EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
+ Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_begin",
+ DebugFrameInfo.Number));
- EmitSectionOffset("debug_frame_common", "section_debug_frame",
- 0, 0, true, false);
- EOL("FDE CIE offset");
+ Asm->OutStreamer.AddComment("FDE CIE offset");
+ EmitSectionOffset(getTempLabel("debug_frame_common"),
+ getTempLabel("section_debug_frame"), true, false);
- EmitReference("func_begin", DebugFrameInfo.Number);
- EOL("FDE initial location");
- EmitDifference("func_end", DebugFrameInfo.Number,
- "func_begin", DebugFrameInfo.Number);
- EOL("FDE address range");
+ Asm->OutStreamer.AddComment("FDE initial location");
+ Asm->OutStreamer.EmitSymbolValue(getDWLabel("func_begin",
+ DebugFrameInfo.Number),
+ TD->getPointerSize(), 0/*AddrSpace*/);
+
+
+
+ Asm->OutStreamer.AddComment("FDE address range");
+ EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number),
+ getDWLabel("func_begin", DebugFrameInfo.Number));
EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
false);
Asm->EmitAlignment(2, 0, 0, false);
- EmitLabel("debug_frame_end", DebugFrameInfo.Number);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_end",
+ DebugFrameInfo.Number));
}
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
@@ -2786,60 +2772,65 @@ void DwarfDebug::emitDebugPubNames() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubNamesSection());
- EmitDifference("pubnames_end", ModuleCU->getID(),
- "pubnames_begin", ModuleCU->getID(), true);
- EOL("Length of Public Names Info");
+ Asm->OutStreamer.AddComment("Length of Public Names Info");
+ EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()),
+ getDWLabel("pubnames_begin", ModuleCU->getID()), true);
- EmitLabel("pubnames_begin", ModuleCU->getID());
+ Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID()));
- Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version");
+ Asm->OutStreamer.AddComment("DWARF Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION);
- EmitSectionOffset("info_begin", "section_info",
- ModuleCU->getID(), 0, true, false);
- EOL("Offset of Compilation Unit Info");
+ Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
+ EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
+ getTempLabel("section_info"),
+ true, false);
- EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
+ Asm->OutStreamer.AddComment("Compilation Unit Length");
+ EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
+ getDWLabel("info_begin", ModuleCU->getID()),
true);
- EOL("Compilation Unit Length");
const StringMap<DIE*> &Globals = ModuleCU->getGlobals();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
- DIE * Entity = GI->second;
+ DIE *Entity = GI->second;
- Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset");
+ Asm->OutStreamer.AddComment("DIE offset");
+ Asm->EmitInt32(Entity->getOffset());
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
}
- Asm->EmitInt32(0); EOL("End Mark");
- EmitLabel("pubnames_end", ModuleCU->getID());
- Asm->O << '\n';
+ Asm->OutStreamer.AddComment("End Mark");
+ Asm->EmitInt32(0);
+ Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID()));
}
void DwarfDebug::emitDebugPubTypes() {
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubTypesSection());
- EmitDifference("pubtypes_end", ModuleCU->getID(),
- "pubtypes_begin", ModuleCU->getID(), true);
- EOL("Length of Public Types Info");
+ Asm->OutStreamer.AddComment("Length of Public Types Info");
+ EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()),
+ getDWLabel("pubtypes_begin", ModuleCU->getID()), true);
- EmitLabel("pubtypes_begin", ModuleCU->getID());
+ Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID()));
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
- EmitSectionOffset("info_begin", "section_info",
- ModuleCU->getID(), 0, true, false);
- EOL("Offset of Compilation ModuleCU Info");
+ Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info");
+ EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
+ getTempLabel("section_info"), true, false);
- EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
+ Asm->OutStreamer.AddComment("Compilation ModuleCU Length");
+ EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
+ getDWLabel("info_begin", ModuleCU->getID()),
true);
- EOL("Compilation ModuleCU Length");
const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes();
for (StringMap<DIE*>::const_iterator
@@ -2854,32 +2845,29 @@ void DwarfDebug::emitDebugPubTypes() {
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
}
- Asm->EmitInt32(0); EOL("End Mark");
- EmitLabel("pubtypes_end", ModuleCU->getID());
- Asm->O << '\n';
+ Asm->OutStreamer.AddComment("End Mark");
+ Asm->EmitInt32(0);
+ Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID()));
}
/// emitDebugStr - Emit visible names into a debug str section.
///
void DwarfDebug::emitDebugStr() {
// Check to see if it is worth the effort.
- if (!StringPool.empty()) {
- // Start the dwarf str section.
- Asm->OutStreamer.SwitchSection(
+ if (StringPool.empty()) return;
+
+ // Start the dwarf str section.
+ Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfStrSection());
- // For each of strings in the string pool.
- for (unsigned StringID = 1, N = StringPool.size();
- StringID <= N; ++StringID) {
- // Emit a label for reference from debug information entries.
- EmitLabel("string", StringID);
-
- // Emit the string itself.
- const std::string &String = StringPool[StringID];
- Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0);
- }
-
- Asm->O << '\n';
+ // For each of strings in the string pool.
+ for (unsigned StringID = 1, N = StringPool.size(); StringID <= N; ++StringID){
+ // Emit a label for reference from debug information entries.
+ Asm->OutStreamer.EmitLabel(getDWLabel("string", StringID));
+
+ // Emit the string itself.
+ const std::string &String = StringPool[StringID];
+ Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0);
}
}
@@ -2897,33 +2885,6 @@ void DwarfDebug::EmitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
-
- // FIXME - Mock up
-#if 0
- CompileUnit *Unit = GetBaseCompileUnit();
-
- // Don't include size of length
- Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info");
-
- Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
-
- EmitReference("info_begin", Unit->getID());
- EOL("Offset of Compilation Unit Info");
-
- Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address");
-
- Asm->EmitInt8(0); EOL("Size of Segment Descriptor");
-
- Asm->EmitInt16(0); EOL("Pad (1)");
- Asm->EmitInt16(0); EOL("Pad (2)");
-
- // Range 1
- EmitReference("text_begin", 0); EOL("Address");
- EmitDifference("text_end", 0, "text_begin", 0, true); EOL("Length");
-
- Asm->EmitInt32(0); EOL("EOM (1)");
- Asm->EmitInt32(0); EOL("EOM (2)");
-#endif
}
/// emitDebugRanges - Emit visible names into a debug ranges section.
@@ -2972,14 +2933,16 @@ void DwarfDebug::emitDebugInlineInfo() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
- EmitDifference("debug_inlined_end", 1,
- "debug_inlined_begin", 1, true);
- EOL("Length of Debug Inlined Information Entry");
+ Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry");
+ EmitDifference(getDWLabel("debug_inlined_end", 1),
+ getDWLabel("debug_inlined_begin", 1), true);
- EmitLabel("debug_inlined_begin", 1);
+ Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1));
- Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
- Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
+ Asm->OutStreamer.AddComment("Dwarf Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION);
+ Asm->OutStreamer.AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(TD->getPointerSize());
for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
@@ -2992,33 +2955,29 @@ void DwarfDebug::emitDebugInlineInfo() {
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
+ Asm->OutStreamer.AddComment("MIPS linkage name");
if (LName.empty()) {
Asm->OutStreamer.EmitBytes(Name, 0);
Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator.
} else
- EmitSectionOffset("string", "section_str",
- StringPool.idFor(getRealLinkageName(LName)), false, true);
+ EmitSectionOffset(getDWLabel("string",
+ StringPool.idFor(getRealLinkageName(LName))),
+ getTempLabel("section_str"), true);
- EOL("MIPS linkage name");
- EmitSectionOffset("string", "section_str",
- StringPool.idFor(Name), false, true);
- EOL("Function name");
+ Asm->OutStreamer.AddComment("Function name");
+ EmitSectionOffset(getDWLabel("string", StringPool.idFor(Name)),
+ getTempLabel("section_str"), false, true);
EmitULEB128(Labels.size(), "Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
- DIE *SP = LI->second;
- Asm->EmitInt32(SP->getOffset()); EOL("DIE offset");
-
- if (TD->getPointerSize() == sizeof(int32_t))
- O << MAI->getData32bitsDirective();
- else
- O << MAI->getData64bitsDirective();
+ if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset");
+ Asm->EmitInt32(LI->second->getOffset());
- PrintLabelName("label", LI->first); EOL("low_pc");
+ if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("low_pc");
+ Asm->OutStreamer.EmitSymbolValue(LI->first, TD->getPointerSize(), 0);
}
}
- EmitLabel("debug_inlined_end", 1);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1));
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 55baa92..40d1d64 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -62,14 +62,6 @@ class DwarfDebug : public DwarfPrinter {
// Attributes used to construct specific Dwarf sections.
//
- /// CompileUnitMap - A map of global variables representing compile units to
- /// compile units.
- DenseMap<Value *, CompileUnit *> CompileUnitMap;
-
- /// CompileUnits - All the compile units in this module.
- ///
- SmallVector<CompileUnit *, 8> CompileUnits;
-
/// ModuleCU - All DIEs are inserted in ModuleCU.
CompileUnit *ModuleCU;
@@ -175,8 +167,8 @@ class DwarfDebug : public DwarfPrinter {
/// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section.
- typedef std::pair<unsigned, DIE *> InlineInfoLabels;
- DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
+ typedef std::pair<MCSymbol*, DIE *> InlineInfoLabels;
+ DenseMap<MDNode*, SmallVector<InlineInfoLabels, 4> > InlineInfo;
SmallVector<MDNode *, 4> InlinedSPNodes;
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
@@ -251,23 +243,18 @@ class DwarfDebug : public DwarfPrinter {
/// addLabel - Add a Dwarf label attribute data and value.
///
void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label);
-
- /// addObjectLabel - Add an non-Dwarf label attribute data and value.
- ///
- void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const MCSymbol *Sym);
+ const MCSymbol *Label);
/// addSectionOffset - Add a section offset label attribute data and value.
///
void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label, const DWLabel &Section,
- bool isEH = false, bool useSet = true);
+ const MCSymbol *Label, const MCSymbol *Section,
+ bool isEH = false);
/// addDelta - Add a label delta attribute data and value.
///
void addDelta(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Hi, const DWLabel &Lo);
+ const MCSymbol *Hi, const MCSymbol *Lo);
/// addDIEEntry - Add a DIE attribute data and value.
///
@@ -346,7 +333,7 @@ class DwarfDebug : public DwarfPrinter {
DICompositeType *CTy);
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
- DIE *constructEnumTypeDIE(DIEnumerator *ETy);
+ DIE *constructEnumTypeDIE(DIEnumerator ETy);
/// createGlobalVariableDIE - Create new DIE using GV.
DIE *createGlobalVariableDIE(const DIGlobalVariable &GV);
@@ -357,10 +344,6 @@ class DwarfDebug : public DwarfPrinter {
/// createSubprogramDIE - Create new DIE using SP.
DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false);
- /// findCompileUnit - Get the compile unit for the given descriptor.
- ///
- CompileUnit *findCompileUnit(DICompileUnit Unit);
-
/// getUpdatedDbgScope - Find or create DbgScope assicated with
/// the instruction. Initialize scope and update scope hierarchy.
DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
@@ -529,10 +512,10 @@ public:
///
void endFunction(const MachineFunction *MF);
- /// recordSourceLine - Records location information and associates it with a
- /// label. Returns a unique label ID used to generate a label and provide
- /// correspondence to the source line list.
- unsigned recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
+ /// recordSourceLine - Register a source line with debug info. Returns the
+ /// unique label that was emitted and which provides correspondence to
+ /// the source line list.
+ MCSymbol *recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
/// getSourceLineCount - Return the number of source lines in the debug
/// info.
@@ -556,7 +539,7 @@ public:
void collectVariableInfo();
/// beginScope - Process beginning of a scope starting at Label.
- void beginScope(const MachineInstr *MI, unsigned Label);
+ void beginScope(const MachineInstr *MI, MCSymbol *Label);
/// endScope - Prcess end of a scope.
void endScope(const MachineInstr *MI);
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 2b08ba4..11a01fe 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -39,7 +39,7 @@ using namespace llvm;
DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A,
const MCAsmInfo *T)
- : DwarfPrinter(OS, A, T, "eh"), shouldEmitTable(false),shouldEmitMoves(false),
+ : DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false),
shouldEmitTableModule(false), shouldEmitMovesModule(false),
ExceptionTimer(0) {
if (TimePassesIsEnabled)
@@ -60,7 +60,7 @@ const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef,
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
<< LabelName << Asm->getFunctionNumber()
<< "_" << Index;
- MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
+ MCSymbol *DotSym = Asm->OutContext.GetOrCreateTemporarySymbol(Name.str());
Asm->OutStreamer.EmitLabel(DotSym);
return MCBinaryExpr::CreateSub(ExprRef,
@@ -84,25 +84,29 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// Begin eh frame section.
Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection());
- if (MAI->is_EHSymbolPrivate())
- O << MAI->getPrivateGlobalPrefix();
- O << "EH_frame" << Index << ":\n";
+ MCSymbol *EHFrameSym;
+ if (TLOF.isFunctionEHFrameSymbolPrivate())
+ EHFrameSym = getDWLabel("EH_frame", Index);
+ else
+ EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") +
+ Twine(Index));
+ Asm->OutStreamer.EmitLabel(EHFrameSym);
- EmitLabel("section_eh_frame", Index);
+ Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index));
// Define base labels.
- EmitLabel("eh_frame_common", Index);
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index));
// Define the eh frame length.
- EmitDifference("eh_frame_common_end", Index,
- "eh_frame_common_begin", Index, true);
- EOL("Length of Common Information Entry");
+ Asm->OutStreamer.AddComment("Length of Common Information Entry");
+ EmitDifference(getDWLabel("eh_frame_common_end", Index),
+ getDWLabel("eh_frame_common_begin", Index), true);
// EH frame header.
- EmitLabel("eh_frame_common_begin", Index);
- if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("CIE Identifier Tag");
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index));
+ Asm->OutStreamer.AddComment("CIE Identifier Tag");
Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
- if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DW_CIE_VERSION");
+ Asm->OutStreamer.AddComment("DW_CIE_VERSION");
Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/);
// The personality presence indicates that language specific information will
@@ -138,14 +142,14 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
if (APtr != Augmentation + 1)
Augmentation[0] = 'z';
+ Asm->OutStreamer.AddComment("CIE Augmentation");
Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0);
- EOL("CIE Augmentation");
// Round out reader.
EmitULEB128(1, "CIE Code Alignment Factor");
EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
+ Asm->OutStreamer.AddComment("CIE Return Address Column");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
- EOL("CIE Return Address Column");
if (Augmentation[0]) {
EmitULEB128(AugmentationSize, "Augmentation Size");
@@ -153,8 +157,8 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// If there is a personality, we need to indicate the function's location.
if (PersonalityFn) {
EmitEncodingByte(PerEncoding, "Personality");
+ Asm->OutStreamer.AddComment("Personality");
EmitReference(PersonalityFn, PerEncoding);
- EOL("Personality");
}
if (UsesLSDA[Index])
EmitEncodingByte(LSDAEncoding, "LSDA");
@@ -171,8 +175,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// be 8-byte on 64-bit targets to match what gcc does. Otherwise you get
// holes which confuse readers of eh_frame.
Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false);
- EmitLabel("eh_frame_common_end", Index);
- Asm->O << '\n';
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_end", Index));
}
/// EmitFDE - Emit the Frame Description Entry (FDE) for the function.
@@ -190,13 +193,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
// Externally visible entry into the functions eh frame info. If the
// corresponding function is static, this should not be externally visible.
- if (!TheFunc->hasLocalLinkage())
- if (const char *GlobalEHDirective = MAI->getGlobalEHDirective())
- O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n';
+ if (!TheFunc->hasLocalLinkage() && TLOF.isFunctionEHSymbolGlobal())
+ Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global);
// If corresponding function is weak definition, this should be too.
if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective())
- O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n';
+ Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
+ MCSA_WeakDefinition);
// If corresponding function is hidden, this should be too.
if (TheFunc->hasHiddenVisibility())
@@ -211,8 +214,9 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory &&
(!TheFunc->isWeakForLinker() ||
!MAI->getWeakDefDirective() ||
- MAI->getSupportsWeakOmittedEHFrame())) {
- O << *EHFrameInfo.FunctionEHSym << " = 0\n";
+ TLOF.getSupportsWeakOmittedEHFrame())) {
+ Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym,
+ MCConstantExpr::Create(0, Asm->OutContext));
// This name has no connection to the function, so it might get
// dead-stripped when the function is not, erroneously. Prohibit
// dead-stripping unconditionally.
@@ -220,28 +224,29 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
MCSA_NoDeadStrip);
} else {
- O << *EHFrameInfo.FunctionEHSym << ":\n";
+ Asm->OutStreamer.EmitLabel(EHFrameInfo.FunctionEHSym);
// EH frame header.
- EmitDifference("eh_frame_end", EHFrameInfo.Number,
- "eh_frame_begin", EHFrameInfo.Number,
+ Asm->OutStreamer.AddComment("Length of Frame Information Entry");
+ EmitDifference(getDWLabel("eh_frame_end", EHFrameInfo.Number),
+ getDWLabel("eh_frame_begin", EHFrameInfo.Number),
true);
- EOL("Length of Frame Information Entry");
- EmitLabel("eh_frame_begin", EHFrameInfo.Number);
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_begin",EHFrameInfo.Number));
- EmitSectionOffset("eh_frame_begin", "eh_frame_common",
- EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
- true, true, false);
+ Asm->OutStreamer.AddComment("FDE CIE offset");
+ EmitSectionOffset(getDWLabel("eh_frame_begin", EHFrameInfo.Number),
+ getDWLabel("eh_frame_common",
+ EHFrameInfo.PersonalityIndex),
+ true, true);
- EOL("FDE CIE offset");
- EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding);
- EOL("FDE initial location");
- EmitDifference("eh_func_end", EHFrameInfo.Number,
- "eh_func_begin", EHFrameInfo.Number,
+ Asm->OutStreamer.AddComment("FDE initial location");
+ EmitReference(getDWLabel("eh_func_begin", EHFrameInfo.Number), FDEEncoding);
+ Asm->OutStreamer.AddComment("FDE address range");
+ EmitDifference(getDWLabel("eh_func_end", EHFrameInfo.Number),
+ getDWLabel("eh_func_begin", EHFrameInfo.Number),
SizeOfEncodedValue(FDEEncoding) == 4);
- EOL("FDE address range");
// If there is a personality and landing pads then point to the language
// specific data area in the exception table.
@@ -249,12 +254,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
unsigned Size = SizeOfEncodedValue(LSDAEncoding);
EmitULEB128(Size, "Augmentation size");
+ Asm->OutStreamer.AddComment("Language Specific Data Area");
if (EHFrameInfo.hasLandingPads)
- EmitReference("exception", EHFrameInfo.Number, LSDAEncoding);
+ EmitReference(getDWLabel("exception", EHFrameInfo.Number),LSDAEncoding);
else
Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/);
- EOL("Language Specific Data Area");
} else {
EmitULEB128(0, "Augmentation size");
}
@@ -268,7 +273,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
// get holes which confuse readers of eh_frame.
Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3,
0, 0, false);
- EmitLabel("eh_frame_end", EHFrameInfo.Number);
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_end", EHFrameInfo.Number));
// If the function is marked used, this table should be also. We cannot
// make the mark unconditional in this case, since retaining the table also
@@ -280,7 +285,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
MCSA_NoDeadStrip);
}
- Asm->O << '\n';
+ Asm->OutStreamer.AddBlankLine();
}
/// SharedTypeIds - How many leading type ids two landing pads have in common.
@@ -699,15 +704,14 @@ void DwarfException::EmitExceptionTable() {
Asm->EmitAlignment(2, 0, 0, false);
// Emit the LSDA.
- O << "GCC_except_table" << SubprogramCount << ":\n";
- EmitLabel("exception", SubprogramCount);
+ MCSymbol *GCCETSym =
+ Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+
+ Twine(SubprogramCount));
+ Asm->OutStreamer.EmitLabel(GCCETSym);
+ Asm->OutStreamer.EmitLabel(getDWLabel("exception", SubprogramCount));
- if (IsSJLJ) {
- SmallString<16> LSDAName;
- raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() <<
- "_LSDA_" << Asm->getFunctionNumber();
- O << LSDAName.str() << ":\n";
- }
+ if (IsSJLJ)
+ Asm->OutStreamer.EmitLabel(getDWLabel("_LSDA_", Asm->getFunctionNumber()));
// Emit the LSDA header.
EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
@@ -819,27 +823,30 @@ void DwarfException::EmitExceptionTable() {
// Offset of the call site relative to the previous call site, counted in
// number of 16-byte bundles. The first call site is counted relative to
// the start of the procedure fragment.
- EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
+ Asm->OutStreamer.AddComment("Region start");
+ EmitSectionOffset(getDWLabel(BeginTag, BeginNumber),
+ getDWLabel("eh_func_begin", SubprogramCount),
true, true);
- EOL("Region start");
+ Asm->OutStreamer.AddComment("Region length");
if (!S.EndLabel)
- EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
+ EmitDifference(getDWLabel("eh_func_end", SubprogramCount),
+ getDWLabel(BeginTag, BeginNumber),
true);
else
- EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
+ EmitDifference(getDWLabel("label", S.EndLabel),
+ getDWLabel(BeginTag, BeginNumber), true);
- EOL("Region length");
// Offset of the landing pad, counted in 16-byte bundles relative to the
// @LPStart address.
+ Asm->OutStreamer.AddComment("Landing pad");
if (!S.PadLabel) {
- Asm->OutStreamer.AddComment("Landing pad");
Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
} else {
- EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
+ EmitSectionOffset(getDWLabel("label", S.PadLabel),
+ getDWLabel("eh_func_begin", SubprogramCount),
true, true);
- EOL("Landing pad");
}
// Offset of the first associated action record, relative to the start of
@@ -850,11 +857,16 @@ void DwarfException::EmitExceptionTable() {
}
// Emit the Action Table.
- if (Actions.size() != 0) EOL("-- Action Record Table --");
+ if (Actions.size() != 0) {
+ Asm->OutStreamer.AddComment("-- Action Record Table --");
+ Asm->OutStreamer.AddBlankLine();
+ }
+
for (SmallVectorImpl<ActionEntry>::const_iterator
I = Actions.begin(), E = Actions.end(); I != E; ++I) {
const ActionEntry &Action = *I;
- EOL("Action Record:");
+ Asm->OutStreamer.AddComment("Action Record");
+ Asm->OutStreamer.AddBlankLine();
// Type Filter
//
@@ -870,23 +882,26 @@ void DwarfException::EmitExceptionTable() {
}
// Emit the Catch TypeInfos.
- if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --");
+ if (!TypeInfos.empty()) {
+ Asm->OutStreamer.AddComment("-- Catch TypeInfos --");
+ Asm->OutStreamer.AddBlankLine();
+ }
for (std::vector<GlobalVariable *>::const_reverse_iterator
I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
const GlobalVariable *GV = *I;
- if (GV) {
+ Asm->OutStreamer.AddComment("TypeInfo");
+ if (GV)
EmitReference(GV, TTypeEncoding);
- EOL("TypeInfo");
- } else {
- PrintRelDirective(TTypeEncoding);
- O << "0x0";
- EOL("");
- }
+ else
+ Asm->OutStreamer.EmitIntValue(0, SizeOfEncodedValue(TTypeEncoding), 0);
}
// Emit the Exception Specifications.
- if (!FilterIds.empty()) EOL("-- Filter IDs --");
+ if (!FilterIds.empty()) {
+ Asm->OutStreamer.AddComment("-- Filter IDs --");
+ Asm->OutStreamer.AddBlankLine();
+ }
for (std::vector<unsigned>::const_iterator
I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
unsigned TypeID = *I;
@@ -945,7 +960,7 @@ void DwarfException::BeginFunction(const MachineFunction *MF) {
if (shouldEmitMoves || shouldEmitTable)
// Assumes in correct section after the entry point.
- EmitLabel("eh_func_begin", ++SubprogramCount);
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_begin", ++SubprogramCount));
shouldEmitTableModule |= shouldEmitTable;
shouldEmitMovesModule |= shouldEmitMoves;
@@ -962,12 +977,13 @@ void DwarfException::EndFunction() {
if (TimePassesIsEnabled)
ExceptionTimer->startTimer();
- EmitLabel("eh_func_end", SubprogramCount);
+ Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount));
EmitExceptionTable();
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
MCSymbol *FunctionEHSym =
Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh",
- Asm->MAI->is_EHSymbolPrivate());
+ TLOF.isFunctionEHFrameSymbolPrivate());
// Save EH frame information
EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount,
diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp b/lib/CodeGen/AsmPrinter/DwarfLabel.cpp
deleted file mode 100644
index 6e9293a..0000000
--- a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===--- lib/CodeGen/DwarfLabel.cpp - Dwarf Label -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// DWARF Labels
-//
-//===----------------------------------------------------------------------===//
-
-#include "DwarfLabel.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-/// Profile - Used to gather unique data for the folding set.
-///
-void DWLabel::Profile(FoldingSetNodeID &ID) const {
- ID.AddString(Tag);
- ID.AddInteger(Number);
-}
-
-#ifndef NDEBUG
-void DWLabel::print(raw_ostream &O) const {
- O << "." << Tag;
- if (Number) O << Number;
-}
-#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.h b/lib/CodeGen/AsmPrinter/DwarfLabel.h
deleted file mode 100644
index 0c0cc4b..0000000
--- a/lib/CodeGen/AsmPrinter/DwarfLabel.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===--- lib/CodeGen/DwarfLabel.h - Dwarf Label -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// DWARF Labels.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CODEGEN_ASMPRINTER_DWARFLABEL_H__
-#define CODEGEN_ASMPRINTER_DWARFLABEL_H__
-
-namespace llvm {
- class FoldingSetNodeID;
- class raw_ostream;
-
- //===--------------------------------------------------------------------===//
- /// DWLabel - Labels are used to track locations in the assembler file.
- /// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim,
- /// where the tag is a category of label (Ex. location) and number is a value
- /// unique in that category.
- class DWLabel {
- /// Tag - Label category tag. Should always be a statically declared C
- /// string.
- ///
- const char *Tag;
-
- /// Number - Value to make label unique.
- ///
- unsigned Number;
- public:
- DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
-
- // Accessors.
- const char *getTag() const { return Tag; }
- unsigned getNumber() const { return Number; }
-
- /// Profile - Used to gather unique data for the folding set.
- ///
- void Profile(FoldingSetNodeID &ID) const;
-
-#ifndef NDEBUG
- void print(raw_ostream &O) const;
-#endif
- };
-} // end llvm namespace
-
-#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
index 28ff0eb..7890e5c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
@@ -31,11 +31,31 @@
#include "llvm/ADT/SmallString.h"
using namespace llvm;
-DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
- const char *flavor)
+DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()),
RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
- SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
+ SubprogramCount(0) {}
+
+
+/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary
+/// label with the specified stem and unique ID.
+MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const {
+ // FIXME: REMOVE this. However, there is stuff in EH that passes counters in
+ // here that can be zero.
+
+ //assert(ID && "Should use getTempLabel if no ID");
+ if (ID == 0) return getTempLabel(Name);
+ return Asm->OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + Twine(Name) + Twine(ID));
+}
+
+/// getTempLabel - Return the MCSymbol corresponding to the assembler temporary
+/// label with the specified name.
+MCSymbol *DwarfPrinter::getTempLabel(const char *Name) const {
+ return Asm->OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + Name);
+}
+
/// SizeOfEncodedValue - Return the size of the encoding in bytes.
unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
@@ -57,33 +77,6 @@ unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
return 0;
}
-void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
- if (isInSection && MAI->getDwarfSectionOffsetDirective())
- O << MAI->getDwarfSectionOffsetDirective();
- else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
- O << MAI->getData32bitsDirective();
- else
- O << MAI->getData64bitsDirective();
-}
-
-void DwarfPrinter::PrintRelDirective(unsigned Encoding) const {
- unsigned Size = SizeOfEncodedValue(Encoding);
- assert((Size == 4 || Size == 8) && "Do not support other types or rels!");
-
- O << (Size == 4 ?
- MAI->getData32bitsDirective() : MAI->getData64bitsDirective());
-}
-
-/// EOL - Print a newline character to asm stream. If a comment is present
-/// then it will be printed first. Comments should not contain '\n'.
-void DwarfPrinter::EOL(const Twine &Comment) const {
- if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) {
- Asm->O.PadToColumn(MAI->getCommentColumn());
- Asm->O << Asm->MAI->getCommentString() << ' ' << Comment;
- }
- Asm->O << '\n';
-}
-
static const char *DecodeDWARFEncoding(unsigned Encoding) {
switch (Encoding) {
case dwarf::DW_EH_PE_absptr: return "absptr";
@@ -145,6 +138,7 @@ void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const {
Asm->OutStreamer.AddComment(Desc);
if (MAI->hasLEB128()) {
+ // FIXME: MCize.
O << "\t.sleb128\t" << Value;
Asm->OutStreamer.AddBlankLine();
return;
@@ -170,6 +164,7 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc,
Asm->OutStreamer.AddComment(Desc);
if (MAI->hasLEB128() && PadTo == 0) {
+ // FIXME: MCize.
O << "\t.uleb128\t" << Value;
Asm->OutStreamer.AddBlankLine();
return;
@@ -191,134 +186,48 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc,
}
-/// PrintLabelName - Print label name in form used by Dwarf writer.
-///
-void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
- O << MAI->getPrivateGlobalPrefix() << Tag;
- if (Number) O << Number;
-}
-void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
- const char *Suffix) const {
- O << MAI->getPrivateGlobalPrefix() << Tag;
- if (Number) O << Number;
- O << Suffix;
-}
-
-/// EmitLabel - Emit location label for internal use by Dwarf.
-///
-void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
- PrintLabelName(Tag, Number);
- O << ":\n";
-}
-
-/// EmitReference - Emit a reference to a label.
-///
-void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
- bool IsPCRelative, bool Force32Bit) const {
- PrintRelDirective(Force32Bit);
- PrintLabelName(Tag, Number);
- if (IsPCRelative) O << "-" << MAI->getPCSymbol();
-}
-void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
- bool Force32Bit) const {
- PrintRelDirective(Force32Bit);
- O << Name;
- if (IsPCRelative) O << "-" << MAI->getPCSymbol();
-}
-
-void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
- bool Force32Bit) const {
- PrintRelDirective(Force32Bit);
- O << *Sym;
- if (IsPCRelative) O << "-" << MAI->getPCSymbol();
-}
-
-void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
- unsigned Encoding) const {
- SmallString<64> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
- << Tag << Number;
-
- MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str());
- EmitReference(Sym, Encoding);
-}
-
void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- PrintRelDirective(Encoding);
- O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);;
+ const MCExpr *Exp = TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);
+ Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
}
-void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const {
+void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- PrintRelDirective(Encoding);
- O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang,
- Asm->MMI, Encoding);;
+ const MCExpr *Exp =
+ TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding);
+ Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
}
/// EmitDifference - Emit the difference between two labels. If this assembler
/// supports .set, we emit a .set of a temporary and then use it in the .word.
-void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
- const char *TagLo, unsigned NumberLo,
+void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo,
bool IsSmall) {
- if (MAI->hasSetDirective()) {
- // FIXME: switch to OutStreamer.EmitAssignment.
- O << "\t.set\t";
- PrintLabelName("set", SetCounter, Flavor);
- O << ",";
- PrintLabelName(TagHi, NumberHi);
- O << "-";
- PrintLabelName(TagLo, NumberLo);
- O << "\n";
-
- PrintRelDirective(IsSmall);
- PrintLabelName("set", SetCounter, Flavor);
- ++SetCounter;
- } else {
- PrintRelDirective(IsSmall);
- PrintLabelName(TagHi, NumberHi);
- O << "-";
- PrintLabelName(TagLo, NumberLo);
- }
+ unsigned Size = IsSmall ? 4 : TD->getPointerSize();
+ Asm->EmitLabelDifference(TagHi, TagLo, Size);
}
-void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
- unsigned LabelNumber,
- unsigned SectionNumber,
- bool IsSmall, bool isEH,
- bool useSet) {
- bool printAbsolute = false;
+void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label,
+ const MCSymbol *Section,
+ bool IsSmall, bool isEH) {
+ bool isAbsolute;
if (isEH)
- printAbsolute = MAI->isAbsoluteEHSectionOffsets();
+ isAbsolute = MAI->isAbsoluteEHSectionOffsets();
else
- printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
-
- if (MAI->hasSetDirective() && useSet) {
- // FIXME: switch to OutStreamer.EmitAssignment.
- O << "\t.set\t";
- PrintLabelName("set", SetCounter, Flavor);
- O << ",";
- PrintLabelName(Label, LabelNumber);
-
- if (!printAbsolute) {
- O << "-";
- PrintLabelName(Section, SectionNumber);
- }
+ isAbsolute = MAI->isAbsoluteDebugSectionOffsets();
- O << "\n";
- PrintRelDirective(IsSmall);
- PrintLabelName("set", SetCounter, Flavor);
- ++SetCounter;
- } else {
- PrintRelDirective(IsSmall, true);
- PrintLabelName(Label, LabelNumber);
-
- if (!printAbsolute) {
- O << "-";
- PrintLabelName(Section, SectionNumber);
- }
+ if (!isAbsolute)
+ return EmitDifference(Label, Section, IsSmall);
+
+ // On COFF targets, we have to emit the weird .secrel32 directive.
+ if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective())
+ // FIXME: MCize.
+ Asm->O << SecOffDir << Label->getName();
+ else {
+ unsigned Size = IsSmall ? 4 : TD->getPointerSize();
+ Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/);
}
}
@@ -337,12 +246,9 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
const MachineMove &Move = Moves[i];
unsigned LabelID = Move.getLabelID();
- if (LabelID) {
- LabelID = MMI->MappedLabel(LabelID);
-
- // Throw out move if the label is invalid.
- if (!LabelID) continue;
- }
+ // Throw out move if the label is invalid.
+ if (LabelID && MMI->isLabelDeleted(LabelID))
+ continue;
const MachineLocation &Dst = Move.getDestination();
const MachineLocation &Src = Move.getSource();
@@ -350,9 +256,8 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
// Advance row if new location.
if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
EmitCFAByte(dwarf::DW_CFA_advance_loc4);
- EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
- Asm->O << '\n';
-
+ EmitDifference(getDWLabel("label", LabelID),
+ getDWLabel(BaseLabel, BaseLabelID), true);
BaseLabelID = LabelID;
BaseLabel = "label";
IsLocal = true;
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
index bd715f2..5e2d806 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
@@ -14,7 +14,6 @@
#ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__
#define CODEGEN_ASMPRINTER_DWARFPRINTER_H__
-#include "DwarfLabel.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormattedStream.h"
@@ -67,15 +66,7 @@ protected:
/// SubprogramCount - The running count of functions being compiled.
unsigned SubprogramCount;
- /// Flavor - A unique string indicating what dwarf producer this is, used to
- /// unique labels.
- const char * const Flavor;
-
- /// SetCounter - A unique number for each '.set' directive.
- unsigned SetCounter;
-
- DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
- const char *flavor);
+ DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T);
public:
//===------------------------------------------------------------------===//
@@ -86,17 +77,17 @@ public:
const MCAsmInfo *getMCAsmInfo() const { return MAI; }
const TargetData *getTargetData() const { return TD; }
+ /// getDWLabel - Return the MCSymbol corresponding to the assembler temporary
+ /// label with the specified stem and unique ID.
+ MCSymbol *getDWLabel(const char *Name, unsigned ID) const;
+
+ /// getTempLabel - Return an assembler temporary label with the specified
+ /// name.
+ MCSymbol *getTempLabel(const char *Name) const;
+
/// SizeOfEncodedValue - Return the size of the encoding in bytes.
unsigned SizeOfEncodedValue(unsigned Encoding) const;
- void PrintRelDirective(unsigned Encoding) const;
- void PrintRelDirective(bool Force32Bit = false,
- bool isInSection = false) const;
-
- /// EOL - Print a newline character to asm stream. If a comment is present
- /// then it will be printed first. Comments should not contain '\n'.
- void EOL(const Twine &Comment) const;
-
/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
/// encoding. If verbose assembly output is enabled, we output comments
/// describing the encoding. Desc is a string saying what the encoding is
@@ -115,57 +106,20 @@ public:
unsigned PadTo = 0) const;
- /// PrintLabelName - Print label name in form used by Dwarf writer.
- ///
- void PrintLabelName(const DWLabel &Label) const {
- PrintLabelName(Label.getTag(), Label.getNumber());
- }
- void PrintLabelName(const char *Tag, unsigned Number) const;
- void PrintLabelName(const char *Tag, unsigned Number,
- const char *Suffix) const;
-
- /// EmitLabel - Emit location label for internal use by Dwarf.
- ///
- void EmitLabel(const DWLabel &Label) const {
- EmitLabel(Label.getTag(), Label.getNumber());
- }
- void EmitLabel(const char *Tag, unsigned Number) const;
-
/// EmitReference - Emit a reference to a label.
///
- void EmitReference(const DWLabel &Label, bool IsPCRelative = false,
- bool Force32Bit = false) const {
- EmitReference(Label.getTag(), Label.getNumber(),
- IsPCRelative, Force32Bit);
- }
- void EmitReference(const char *Tag, unsigned Number,
- bool IsPCRelative = false,
- bool Force32Bit = false) const;
- void EmitReference(const std::string &Name, bool IsPCRelative = false,
- bool Force32Bit = false) const;
- void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false,
- bool Force32Bit = false) const;
-
- void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const;
void EmitReference(const MCSymbol *Sym, unsigned Encoding) const;
void EmitReference(const GlobalValue *GV, unsigned Encoding) const;
/// EmitDifference - Emit the difference between two labels.
- void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo,
- bool IsSmall = false) {
- EmitDifference(LabelHi.getTag(), LabelHi.getNumber(),
- LabelLo.getTag(), LabelLo.getNumber(),
- IsSmall);
- }
- void EmitDifference(const char *TagHi, unsigned NumberHi,
- const char *TagLo, unsigned NumberLo,
+ void EmitDifference(const MCSymbol *LabelHi, const MCSymbol *LabelLo,
bool IsSmall = false);
- void EmitSectionOffset(const char* Label, const char* Section,
- unsigned LabelNumber, unsigned SectionNumber,
- bool IsSmall = false, bool isEH = false,
- bool useSet = true);
-
+ /// EmitSectionOffset - Emit Label-Section or use a special purpose directive
+ /// to emit a section offset if the target has one.
+ void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *Section,
+ bool IsSmall = false, bool isEH = false);
+
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index 08e1bbc..9fd4c44 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -73,11 +73,11 @@ void DwarfWriter::EndFunction(const MachineFunction *MF) {
MMI->EndFunction();
}
-/// RecordSourceLine - Records location information and associates it with a
-/// label. Returns a unique label ID used to generate a label and provide
-/// correspondence to the source line list.
-unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col,
- MDNode *Scope) {
+/// RecordSourceLine - Register a source line with debug info. Returns the
+/// unique label that was emitted and which provides correspondence to
+/// the source line list.
+MCSymbol *DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col,
+ MDNode *Scope) {
return DD->recordSourceLine(Line, Col, Scope);
}
@@ -92,7 +92,7 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const {
return DD && DD->ShouldEmitDwarfDebug();
}
-void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
+void DwarfWriter::BeginScope(const MachineInstr *MI, MCSymbol *L) {
DD->beginScope(MI, L);
}
void DwarfWriter::EndScope(const MachineInstr *MI) {
diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp
index d94729a..889763a 100644
--- a/lib/CodeGen/BranchFolding.cpp
+++ b/lib/CodeGen/BranchFolding.cpp
@@ -310,12 +310,23 @@ static unsigned HashEndOfMBB(const MachineBasicBlock *MBB,
return 0; // Empty MBB.
--I;
+ // Skip debug info so it will not affect codegen.
+ while (I->isDebugValue()) {
+ if (I==MBB->begin())
+ return 0; // MBB empty except for debug info.
+ --I;
+ }
unsigned Hash = HashMachineInstr(I);
if (I == MBB->begin() || minCommonTailLength == 1)
return Hash; // Single instr MBB.
--I;
+ while (I->isDebugValue()) {
+ if (I==MBB->begin())
+ return Hash; // MBB with single non-debug instr.
+ --I;
+ }
// Hash in the second-to-last instruction.
Hash ^= HashMachineInstr(I) << 2;
return Hash;
@@ -334,9 +345,32 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
unsigned TailLen = 0;
while (I1 != MBB1->begin() && I2 != MBB2->begin()) {
--I1; --I2;
- // Don't merge debugging pseudos.
- if (I1->isDebugValue() || I2->isDebugValue() ||
- !I1->isIdenticalTo(I2) ||
+ // Skip debugging pseudos; necessary to avoid changing the code.
+ while (I1->isDebugValue()) {
+ if (I1==MBB1->begin()) {
+ while (I2->isDebugValue()) {
+ if (I2==MBB2->begin())
+ // I1==DBG at begin; I2==DBG at begin
+ return TailLen;
+ --I2;
+ }
+ ++I2;
+ // I1==DBG at begin; I2==non-DBG, or first of DBGs not at begin
+ return TailLen;
+ }
+ --I1;
+ }
+ // I1==first (untested) non-DBG preceding known match
+ while (I2->isDebugValue()) {
+ if (I2==MBB2->begin()) {
+ ++I1;
+ // I1==non-DBG, or first of DBGs not at begin; I2==DBG at begin
+ return TailLen;
+ }
+ --I2;
+ }
+ // I1, I2==first (untested) non-DBGs preceding known match
+ if (!I1->isIdenticalTo(I2) ||
// FIXME: This check is dubious. It's used to get around a problem where
// people incorrectly expect inline asm directives to remain in the same
// relative order. This is untenable because normal compiler
@@ -348,6 +382,29 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
}
++TailLen;
}
+ // Back past possible debugging pseudos at beginning of block. This matters
+ // when one block differs from the other only by whether debugging pseudos
+ // are present at the beginning. (This way, the various checks later for
+ // I1==MBB1->begin() work as expected.)
+ if (I1 == MBB1->begin() && I2 != MBB2->begin()) {
+ --I2;
+ while (I2->isDebugValue()) {
+ if (I2 == MBB2->begin()) {
+ return TailLen;
+ }
+ --I2;
+ }
+ ++I2;
+ }
+ if (I2 == MBB2->begin() && I1 != MBB1->begin()) {
+ --I1;
+ while (I1->isDebugValue()) {
+ if (I1 == MBB1->begin())
+ return TailLen;
+ --I1;
+ }
+ ++I1;
+ }
return TailLen;
}
@@ -643,6 +700,8 @@ unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
SameTails[commonTailIndex].getTailStartPos();
MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock();
+ // If the common tail includes any debug info we will take it pretty
+ // randomly from one of the inputs. Might be better to remove it?
DEBUG(dbgs() << "\nSplitting BB#" << MBB->getNumber() << ", size "
<< maxCommonTailLength);
@@ -912,6 +971,18 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
return MadeChange;
}
+// Blocks should be considered empty if they contain only debug info;
+// else the debug info would affect codegen.
+static bool IsEmptyBlock(MachineBasicBlock *MBB) {
+ if (MBB->empty())
+ return true;
+ for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end();
+ MBBI!=MBBE; ++MBBI) {
+ if (!MBBI->isDebugValue())
+ return false;
+ }
+ return true;
+}
/// IsBetterFallthrough - Return true if it would be clearly better to
/// fall-through to MBB1 than to fall through into MBB2. This has to return
@@ -949,7 +1020,7 @@ ReoptimizeBlock:
// explicitly. Landing pads should not do this since the landing-pad table
// points to this block. Blocks with their addresses taken shouldn't be
// optimized away.
- if (MBB->empty() && !MBB->isLandingPad() && !MBB->hasAddressTaken()) {
+ if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) {
// Dead block? Leave for cleanup later.
if (MBB->pred_empty()) return MadeChange;
@@ -1141,7 +1212,23 @@ ReoptimizeBlock:
// be 'non-branch terminators' in the block, try removing the branch and
// then seeing if the block is empty.
TII->RemoveBranch(*MBB);
-
+ // If the only things remaining in the block are debug info, remove these
+ // as well, so this will behave the same as an empty block in non-debug
+ // mode.
+ if (!MBB->empty()) {
+ bool NonDebugInfoFound = false;
+ for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
+ I != E; ++I) {
+ if (!I->isDebugValue()) {
+ NonDebugInfoFound = true;
+ break;
+ }
+ }
+ if (!NonDebugInfoFound)
+ // Make the block empty, losing the debug info (we could probably
+ // improve this in some cases.)
+ MBB->erase(MBB->begin(), MBB->end());
+ }
// If this block is just an unconditional branch to CurTBB, we can
// usually completely eliminate the block. The only case we cannot
// completely eliminate the block is when the block before this one
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 5e88865..9bc0b71 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -67,9 +67,6 @@ static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden,
cl::desc("Verify generated machine code"),
cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL));
-static cl::opt<bool> EnableMachineCSE("enable-machine-cse", cl::Hidden,
- cl::desc("Enable Machine CSE"));
-
static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
cl::init(cl::BOU_UNSET));
@@ -328,11 +325,10 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
PM.add(createOptimizeExtsPass());
if (!DisableMachineLICM)
PM.add(createMachineLICMPass());
- if (EnableMachineCSE)
- PM.add(createMachineCSEPass());
+ PM.add(createMachineCSEPass());
if (!DisableMachineSink)
PM.add(createMachineSinkingPass());
- printAndVerify(PM, "After MachineLICM and MachineSinking",
+ printAndVerify(PM, "After Machine LICM, CSE and Sinking passes",
/* allowDoubleDefs= */ true);
}
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index ccda66f..f8b1707 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -593,13 +593,10 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
MachineBasicBlock::iterator E = MBB->end();
while (mi != E) {
- if (mi->isDebugValue()) {
+ while (mi != E && mi->isDebugValue())
++mi;
- if (mi != E && !mi->isDebugValue()) {
- baseIndex = indexes_->getNextNonNullIndex(baseIndex);
- }
- continue;
- }
+ if (mi == E)
+ break;
if (mi->killsRegister(interval.reg, tri_)) {
DEBUG(dbgs() << " killed");
end = baseIndex.getDefIndex();
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp
index 64134ce..32b1a7d 100644
--- a/lib/CodeGen/MachineBasicBlock.cpp
+++ b/lib/CodeGen/MachineBasicBlock.cpp
@@ -42,12 +42,11 @@ MachineBasicBlock::~MachineBasicBlock() {
/// getSymbol - Return the MCSymbol for this basic block.
///
MCSymbol *MachineBasicBlock::getSymbol(MCContext &Ctx) const {
- SmallString<60> Name;
const MachineFunction *MF = getParent();
- raw_svector_ostream(Name)
- << MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix() << "BB"
- << MF->getFunctionNumber() << '_' << getNumber();
- return Ctx.GetOrCreateSymbol(Name.str());
+ const char *Prefix = MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix();
+ return Ctx.GetOrCreateTemporarySymbol(Twine(Prefix) + "BB" +
+ Twine(MF->getFunctionNumber()) + "_" +
+ Twine(getNumber()));
}
diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp
index b376e3d..ce95d8d 100644
--- a/lib/CodeGen/MachineCSE.cpp
+++ b/lib/CodeGen/MachineCSE.cpp
@@ -33,9 +33,9 @@ namespace {
class MachineCSE : public MachineFunctionPass {
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
- MachineRegisterInfo *MRI;
- MachineDominatorTree *DT;
AliasAnalysis *AA;
+ MachineDominatorTree *DT;
+ MachineRegisterInfo *MRI;
public:
static char ID; // Pass identification
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
@@ -61,6 +61,8 @@ namespace {
MachineBasicBlock::const_iterator E);
bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB);
bool isCSECandidate(MachineInstr *MI);
+ bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
+ MachineInstr *CSMI, MachineInstr *MI);
bool ProcessBlock(MachineDomTreeNode *Node);
};
} // end anonymous namespace
@@ -92,7 +94,16 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
TargetRegisterInfo::isVirtualRegister(SrcReg) &&
!SrcSubIdx && !DstSubIdx) {
+ const TargetRegisterClass *SRC = MRI->getRegClass(SrcReg);
+ const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+ const TargetRegisterClass *NewRC = getCommonSubClass(RC, SRC);
+ if (!NewRC)
+ continue;
+ DEBUG(dbgs() << "Coalescing: " << *DefMI);
+ DEBUG(dbgs() << "*** to: " << *MI);
MO.setReg(SrcReg);
+ if (NewRC != SRC)
+ MRI->setRegClass(SrcReg, NewRC);
DefMI->eraseFromParent();
++NumCoalesces;
Changed = true;
@@ -133,6 +144,8 @@ bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
return false;
}
+/// hasLivePhysRegDefUse - Return true if the specified instruction read / write
+/// physical registers (except for dead defs of physical registers).
bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){
unsigned PhysDef = 0;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
@@ -167,12 +180,19 @@ bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){
return false;
}
-bool MachineCSE::isCSECandidate(MachineInstr *MI) {
- // Ignore copies or instructions that read / write physical registers
- // (except for dead defs of physical registers).
+static bool isCopy(const MachineInstr *MI, const TargetInstrInfo *TII) {
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
- if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
- MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
+ return TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
+ MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg();
+}
+
+bool MachineCSE::isCSECandidate(MachineInstr *MI) {
+ if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() ||
+ MI->isKill() || MI->isInlineAsm())
+ return false;
+
+ // Ignore copies.
+ if (isCopy(MI, TII))
return false;
// Ignore stuff that we obviously can't move.
@@ -194,9 +214,69 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) {
return true;
}
+/// isProfitableToCSE - Return true if it's profitable to eliminate MI with a
+/// common expression that defines Reg.
+bool MachineCSE::isProfitableToCSE(unsigned CSReg, unsigned Reg,
+ MachineInstr *CSMI, MachineInstr *MI) {
+ // FIXME: Heuristics that works around the lack the live range splitting.
+
+ // Heuristics #1: Don't cse "cheap" computating if the def is not local or in an
+ // immediate predecessor. We don't want to increase register pressure and end up
+ // causing other computation to be spilled.
+ if (MI->getDesc().isAsCheapAsAMove()) {
+ MachineBasicBlock *CSBB = CSMI->getParent();
+ MachineBasicBlock *BB = MI->getParent();
+ if (CSBB != BB &&
+ find(CSBB->succ_begin(), CSBB->succ_end(), BB) == CSBB->succ_end())
+ return false;
+ }
+
+ // Heuristics #2: If the expression doesn't not use a vr and the only use
+ // of the redundant computation are copies, do not cse.
+ bool HasVRegUse = false;
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ if (MO.isReg() && MO.isUse() && MO.getReg() &&
+ TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
+ HasVRegUse = true;
+ break;
+ }
+ }
+ if (!HasVRegUse) {
+ bool HasNonCopyUse = false;
+ for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg),
+ E = MRI->use_nodbg_end(); I != E; ++I) {
+ MachineInstr *Use = &*I;
+ // Ignore copies.
+ if (!isCopy(Use, TII)) {
+ HasNonCopyUse = true;
+ break;
+ }
+ }
+ if (!HasNonCopyUse)
+ return false;
+ }
+
+ // Heuristics #3: If the common subexpression is used by PHIs, do not reuse
+ // it unless the defined value is already used in the BB of the new use.
+ bool HasPHI = false;
+ SmallPtrSet<MachineBasicBlock*, 4> CSBBs;
+ for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(CSReg),
+ E = MRI->use_nodbg_end(); I != E; ++I) {
+ MachineInstr *Use = &*I;
+ HasPHI |= Use->isPHI();
+ CSBBs.insert(Use->getParent());
+ }
+
+ if (!HasPHI)
+ return true;
+ return CSBBs.count(MI->getParent());
+}
+
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
bool Changed = false;
+ SmallVector<std::pair<unsigned, unsigned>, 8> CSEPairs;
ScopedHashTableScope<MachineInstr*, unsigned,
MachineInstrExpressionTrait> VNTS(VNT);
MachineBasicBlock *MBB = Node->getBlock();
@@ -231,6 +311,9 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
MachineInstr *CSMI = Exps[CSVN];
DEBUG(dbgs() << "Examining: " << *MI);
DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI);
+
+ // Check if it's profitable to perform this CSE.
+ bool DoCSE = true;
unsigned NumDefs = MI->getDesc().getNumDefs();
for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
@@ -243,11 +326,26 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
assert(TargetRegisterInfo::isVirtualRegister(OldReg) &&
TargetRegisterInfo::isVirtualRegister(NewReg) &&
"Do not CSE physical register defs!");
- MRI->replaceRegWith(OldReg, NewReg);
+ if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) {
+ DoCSE = false;
+ break;
+ }
+ CSEPairs.push_back(std::make_pair(OldReg, NewReg));
--NumDefs;
}
- MI->eraseFromParent();
- ++NumCSEs;
+
+ // Actually perform the elimination.
+ if (DoCSE) {
+ for (unsigned i = 0, e = CSEPairs.size(); i != e; ++i)
+ MRI->replaceRegWith(CSEPairs[i].first, CSEPairs[i].second);
+ MI->eraseFromParent();
+ ++NumCSEs;
+ } else {
+ DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n");
+ VNT.insert(MI, CurrVN++);
+ Exps.push_back(MI);
+ }
+ CSEPairs.clear();
}
// Recursively call ProcessBlock with childred.
@@ -262,7 +360,7 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
TII = MF.getTarget().getInstrInfo();
TRI = MF.getTarget().getRegisterInfo();
MRI = &MF.getRegInfo();
- DT = &getAnalysis<MachineDominatorTree>();
AA = &getAnalysis<AliasAnalysis>();
+ DT = &getAnalysis<MachineDominatorTree>();
return ProcessBlock(DT->getRootNode());
}
diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index 4377d5b..1e3cb1e 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -464,7 +464,9 @@ MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx,
SmallString<60> Name;
raw_svector_ostream(Name)
<< Prefix << "JTI" << getFunctionNumber() << '_' << JTI;
- return Ctx.GetOrCreateSymbol(Name.str());
+ if (isLinkerPrivate)
+ return Ctx.GetOrCreateSymbol(Name.str());
+ return Ctx.GetOrCreateTemporarySymbol(Name.str());
}
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index e23670d..4c7cb8f 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -1219,7 +1219,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
DIScope Scope = DLT.getScope();
OS << " dbg:";
// Omit the directory, since it's usually long and uninteresting.
- if (!Scope.isNull())
+ if (Scope.Verify())
OS << Scope.getFilename();
else
OS << "<unknown>";
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index 5052af7..72fb9fd 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -185,7 +185,8 @@ void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) {
void MachineModuleInfo::TidyLandingPads() {
for (unsigned i = 0; i != LandingPads.size(); ) {
LandingPadInfo &LandingPad = LandingPads[i];
- LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel);
+ if (isLabelDeleted(LandingPad.LandingPadLabel))
+ LandingPad.LandingPadLabel = 0;
// Special case: we *should* emit LPs with null LP MBB. This indicates
// "nounwind" case.
@@ -195,17 +196,14 @@ void MachineModuleInfo::TidyLandingPads() {
}
for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) {
- unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]);
- unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]);
-
- if (!BeginLabel || !EndLabel) {
+ unsigned BeginLabel = LandingPad.BeginLabels[j];
+ unsigned EndLabel = LandingPad.EndLabels[j];
+ if (isLabelDeleted(BeginLabel) || isLabelDeleted(EndLabel)) {
LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
continue;
}
- LandingPad.BeginLabels[j] = BeginLabel;
- LandingPad.EndLabels[j] = EndLabel;
++j;
}
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index 138e711..2d54cd4 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -57,6 +57,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL;
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
+ FrameConstantRegMap.clear();
// Get MachineModuleInfo so that we can track the construction of the
// frame.
@@ -685,7 +686,7 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) {
// If this instruction has a FrameIndex operand, we need to
// use that target machine register info object to eliminate
// it.
- int Value;
+ TargetRegisterInfo::FrameIndexValue Value;
unsigned VReg =
TRI.eliminateFrameIndex(MI, SPAdj, &Value,
FrameIndexVirtualScavenging ? NULL : RS);
@@ -764,12 +765,12 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
unsigned CurrentVirtReg = 0;
unsigned CurrentScratchReg = 0;
bool havePrevValue = false;
- int PrevValue = 0;
+ TargetRegisterInfo::FrameIndexValue PrevValue(0,0);
+ TargetRegisterInfo::FrameIndexValue Value(0,0);
MachineInstr *PrevLastUseMI = NULL;
unsigned PrevLastUseOp = 0;
bool trackingCurrentValue = false;
int SPAdj = 0;
- int Value = 0;
// The instruction stream may change in the loop, so check BB->end()
// directly.
@@ -826,8 +827,11 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
if (trackingCurrentValue) {
SPAdj = (*Entry).second.second;
Value = (*Entry).second.first;
- } else
- SPAdj = Value = 0;
+ } else {
+ SPAdj = 0;
+ Value.first = 0;
+ Value.second = 0;
+ }
// If the scratch register from the last allocation is still
// available, see if the value matches. If it does, just re-use it.
diff --git a/lib/CodeGen/PrologEpilogInserter.h b/lib/CodeGen/PrologEpilogInserter.h
index 931f1eb..aa95773 100644
--- a/lib/CodeGen/PrologEpilogInserter.h
+++ b/lib/CodeGen/PrologEpilogInserter.h
@@ -102,7 +102,8 @@ namespace llvm {
// When using the scavenger post-pass to resolve frame reference
// materialization registers, maintain a map of the registers to
// the constant value and SP adjustment associated with it.
- typedef std::pair<int, int> FrameConstantEntry;
+ typedef std::pair<TargetRegisterInfo::FrameIndexValue, int>
+ FrameConstantEntry;
DenseMap<unsigned, FrameConstantEntry> FrameConstantRegMap;
#ifndef NDEBUG
diff --git a/lib/CodeGen/SelectionDAG/SDDbgValue.h b/lib/CodeGen/SelectionDAG/SDDbgValue.h
index 9e15fc9..d43a044 100644
--- a/lib/CodeGen/SelectionDAG/SDDbgValue.h
+++ b/lib/CodeGen/SelectionDAG/SDDbgValue.h
@@ -34,14 +34,16 @@ class SDDbgValue {
MDNode *mdPtr;
uint64_t Offset;
DebugLoc DL;
+ unsigned Order;
public:
// Constructor for non-constants.
- SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl) :
- Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl) {}
+ SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl,
+ unsigned O) :
+ Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
// Constructor for constants.
- SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl) : Node(0),
- ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl) {}
+ SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl, unsigned O) :
+ Node(0), ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
// Returns the MDNode pointer.
MDNode *getMDPtr() { return mdPtr; }
@@ -60,6 +62,10 @@ public:
// Returns the DebugLoc.
DebugLoc getDebugLoc() { return DL; }
+
+ // Returns the SDNodeOrder. This is the order of the preceding node in the
+ // input.
+ unsigned getOrder() { return Order; }
};
} // end llvm namespace
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 023e486..746d4e2 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -3208,7 +3208,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
bool isSrcConst = isa<ConstantSDNode>(Src);
EVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG);
bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(VT);
- if (VT != MVT::iAny) {
+ if (VT != MVT::Other) {
const Type *Ty = VT.getTypeForEVT(*DAG.getContext());
unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty);
// If source is a string constant, this will require an unaligned load.
@@ -3216,14 +3216,14 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
if (Dst.getOpcode() != ISD::FrameIndex) {
// Can't change destination alignment. It requires a unaligned store.
if (AllowUnalign)
- VT = MVT::iAny;
+ VT = MVT::Other;
} else {
int FI = cast<FrameIndexSDNode>(Dst)->getIndex();
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
if (MFI->isFixedObjectIndex(FI)) {
// Can't change destination alignment. It requires a unaligned store.
if (AllowUnalign)
- VT = MVT::iAny;
+ VT = MVT::Other;
} else {
// Give the stack frame object a larger alignment if needed.
if (MFI->getObjectAlignment(FI) < NewAlign)
@@ -3234,7 +3234,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
}
}
- if (VT == MVT::iAny) {
+ if (VT == MVT::Other) {
if (TLI.allowsUnalignedMemoryAccesses(MVT::i64)) {
VT = MVT::i64;
} else {
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 05f9f1f..a82f0f7 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2141,6 +2141,9 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
while (1) {
assert(MatcherIndex < TableSize && "Invalid index");
+#ifndef NDEBUG
+ unsigned CurrentOpcodeIndex = MatcherIndex;
+#endif
BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++];
switch (Opcode) {
case OPC_Scope: {
@@ -2666,6 +2669,7 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
// If the code reached this point, then the match failed. See if there is
// another child to try in the current 'Scope', otherwise pop it until we
// find a case to check.
+ DEBUG(errs() << " Match failed at index " << CurrentOpcodeIndex << "\n");
while (1) {
if (MatchScopes.empty()) {
CannotYetSelect(NodeToMatch);
@@ -2680,13 +2684,12 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end());
N = NodeStack.back();
- DEBUG(errs() << " Match failed at index " << MatcherIndex
- << " continuing at " << LastScope.FailIndex << "\n");
-
if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size())
MatchedMemRefs.resize(LastScope.NumMatchedMemRefs);
MatcherIndex = LastScope.FailIndex;
+ DEBUG(errs() << " Continuing at " << MatcherIndex << "\n");
+
InputChain = LastScope.InputChain;
InputFlag = LastScope.InputFlag;
if (!LastScope.HasChainNodesMatched)
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index ce72b2f..d25df1d 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -1671,8 +1671,20 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// density, do not join them, instead mark the physical register as its
// allocation preference.
LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt;
+ LiveInterval &JoinPInt = SrcIsPhys ? SrcInt : DstInt;
unsigned JoinVReg = SrcIsPhys ? DstReg : SrcReg;
unsigned JoinPReg = SrcIsPhys ? SrcReg : DstReg;
+
+ // Don't join with physregs that have a ridiculous number of live
+ // ranges. The data structure performance is really bad when that
+ // happens.
+ if (JoinPInt.ranges.size() > 1000) {
+ mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg);
+ ++numAborts;
+ DEBUG(dbgs() << "\tPhysical register too complicated, abort!\n");
+ return false;
+ }
+
const TargetRegisterClass *RC = mri_->getRegClass(JoinVReg);
unsigned Threshold = allocatableRCRegs_[RC].count() * 2;
unsigned Length = li_->getApproximateInstructionCount(JoinVInt);
diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 3b3be5d..2014b42 100644
--- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -403,12 +403,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
// Add information about the stub reference to ELFMMI so that the stub
// gets emitted by the asmprinter.
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());
+ MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str());
MCSymbol *&StubSym = ELFMMI.getGVStubEntry(Sym);
if (StubSym == 0) {
Name.clear();
Mang->getNameWithPrefix(Name, GV, false);
- StubSym = getContext().GetOrCreateSymbol(Name.str());
+ if (GV->hasPrivateLinkage())
+ StubSym = getContext().GetOrCreateTemporarySymbol(Name.str());
+ else
+ StubSym = getContext().GetOrCreateSymbol(Name.str());
}
return TargetLoweringObjectFile::
@@ -463,6 +466,14 @@ getMachOSection(StringRef Segment, StringRef Section,
void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
+ // _foo.eh symbols are currently always exported so that the linker knows
+ // about them. This is not necessary on 10.6 and later, but it
+ // doesn't hurt anything.
+ // FIXME: I need to get this from Triple.
+ IsFunctionEHSymbolGlobal = true;
+ IsFunctionEHFrameSymbolPrivate = false;
+ SupportsWeakOmittedEHFrame = false;
+
if (UniquingMap != 0)
((MachOUniqueMapTy*)UniquingMap)->clear();
TargetLoweringObjectFile::Initialize(Ctx, TM);
@@ -651,16 +662,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
}
// FIXME: Alignment check should be handled by section classifier.
- if (Kind.isMergeable1ByteCString() ||
- (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage())) {
- if (TM.getTargetData()->getPreferredAlignment(
- cast<GlobalVariable>(GV)) < 32) {
- if (Kind.isMergeable1ByteCString())
- return CStringSection;
- assert(Kind.isMergeable2ByteCString());
- return UStringSection;
- }
- }
+ if (Kind.isMergeable1ByteCString() &&
+ TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
+ return CStringSection;
+
+ // Do not put 16-bit arrays in the UString section if they have an
+ // externally visible label, this runs into issues with certain linker
+ // versions.
+ if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() &&
+ TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
+ return UStringSection;
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
@@ -749,12 +760,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
// Add information about the stub reference to MachOMMI so that the stub
// gets emitted by the asmprinter.
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());
+ MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str());
MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym);
if (StubSym == 0) {
Name.clear();
Mang->getNameWithPrefix(Name, GV, false);
- StubSym = getContext().GetOrCreateSymbol(Name.str());
+ if (GV->hasPrivateLinkage())
+ StubSym = getContext().GetOrCreateTemporarySymbol(Name.str());
+ else
+ StubSym = getContext().GetOrCreateSymbol(Name.str());
}
return TargetLoweringObjectFile::
diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
index 946351b..da5435a 100644
--- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
@@ -75,10 +75,9 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
unsigned LabelID = Move.getLabelID();
if (LabelID) {
- LabelID = MMI->MappedLabel(LabelID);
-
// Throw out move if the label is invalid.
- if (!LabelID) continue;
+ if (MMI->isLabelDeleted(LabelID))
+ continue;
}
intptr_t LabelPtr = 0;
@@ -722,10 +721,9 @@ JITDwarfEmitter::GetFrameMovesSizeInBytes(intptr_t BaseLabelPtr,
unsigned LabelID = Move.getLabelID();
if (LabelID) {
- LabelID = MMI->MappedLabel(LabelID);
-
// Throw out move if the label is invalid.
- if (!LabelID) continue;
+ if (MMI->isLabelDeleted(LabelID))
+ continue;
}
intptr_t LabelPtr = 0;
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index f3f063f..bda700b 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -68,9 +68,6 @@ MCAsmInfo::MCAsmInfo() {
ExceptionsType = ExceptionHandling::None;
DwarfRequiresFrameSection = true;
DwarfUsesInlineInfoSection = false;
- Is_EHSymbolPrivate = true;
- GlobalEHDirective = 0;
- SupportsWeakOmittedEHFrame = true;
DwarfSectionOffsetDirective = 0;
AsmTransCBE = 0;
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index da865ad..3c31caa 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -40,19 +40,8 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
HiddenVisibilityAttr = MCSA_PrivateExtern;
// Doesn't support protected visibility.
ProtectedVisibilityAttr = MCSA_Global;
-
HasDotTypeDotSizeDirective = false;
HasNoDeadStrip = true;
- // Note: Even though darwin has the .lcomm directive, it is just a synonym for
- // zerofill, so we prefer to use .zerofill.
-
- // _foo.eh symbols are currently always exported so that the linker knows
- // about them. This is not necessary on 10.6 and later, but it
- // doesn't hurt anything.
- // FIXME: I need to get this from Triple.
- Is_EHSymbolPrivate = false;
- GlobalEHDirective = "\t.globl\t";
- SupportsWeakOmittedEHFrame = false;
}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 96227db..00b02e0 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -440,29 +440,49 @@ public:
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
std::vector<MachRelocationEntry> &Relocs) {
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
- unsigned IsPCRel = 0;
+ unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
unsigned Type = RIT_Vanilla;
// See <reloc.h>.
const MCSymbol *A = Target.getSymA();
- MCSymbolData *SD = SymbolMap.lookup(A);
- uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
+ MCSymbolData *A_SD = SymbolMap.lookup(A);
+
+ if (!A_SD->getFragment())
+ llvm_report_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = A_SD->getFragment()->getAddress() + A_SD->getOffset();
uint32_t Value2 = 0;
if (const MCSymbol *B = Target.getSymB()) {
- Type = RIT_LocalDifference;
+ MCSymbolData *B_SD = SymbolMap.lookup(B);
+
+ if (!B_SD->getFragment())
+ llvm_report_error("symbol '" + B->getName() +
+ "' can not be undefined in a subtraction expression");
- MCSymbolData *SD = SymbolMap.lookup(B);
- Value2 = SD->getFragment()->getAddress() + SD->getOffset();
+ // Select the appropriate difference relocation type.
+ //
+ // Note that there is no longer any semantic difference between these two
+ // relocation types from the linkers point of view, this is done solely
+ // for pedantic compatibility with 'as'.
+ Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference;
+ Value2 = B_SD->getFragment()->getAddress() + B_SD->getOffset();
}
// The value which goes in the fixup is current value of the expression.
Fixup.FixedValue = Value - Value2 + Target.getConstant();
- if (isFixupKindPCRel(Fixup.Kind)) {
+ if (IsPCRel)
Fixup.FixedValue -= Address;
- IsPCRel = 1;
- }
+
+ // If this fixup is a vanilla PC relative relocation for a local label, we
+ // don't need a relocation.
+ //
+ // FIXME: Implement proper atom support.
+ if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary() &&
+ !Target.getSymB())
+ return;
MachRelocationEntry MRE;
MRE.Word0 = ((Address << 0) |
@@ -473,14 +493,12 @@ public:
MRE.Word1 = Value;
Relocs.push_back(MRE);
- if (Type == RIT_LocalDifference) {
- Type = RIT_Pair;
-
+ if (Type == RIT_Difference || Type == RIT_LocalDifference) {
MachRelocationEntry MRE;
MRE.Word0 = ((0 << 0) |
- (Type << 24) |
+ (RIT_Pair << 24) |
(Log2Size << 28) |
- (0 << 30) |
+ (IsPCRel << 30) |
RF_Scattered);
MRE.Word1 = Value2;
Relocs.push_back(MRE);
@@ -491,15 +509,21 @@ public:
MCAsmFixup &Fixup,
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
std::vector<MachRelocationEntry> &Relocs) {
+ unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
+
MCValue Target;
if (!Fixup.Value->EvaluateAsRelocatable(Target))
llvm_report_error("expected relocatable expression");
- // If this is a difference or a local symbol plus an offset, then we need a
- // scattered relocation entry.
+ // If this is a difference or a defined symbol plus an offset, then we need
+ // a scattered relocation entry.
+ uint32_t Offset = Target.getConstant();
+ if (IsPCRel)
+ Offset += 1 << Log2Size;
if (Target.getSymB() ||
(Target.getSymA() && !Target.getSymA()->isUndefined() &&
- Target.getConstant()))
+ Offset))
return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target,
SymbolMap, Relocs);
@@ -507,8 +531,6 @@ public:
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
uint32_t Value = 0;
unsigned Index = 0;
- unsigned IsPCRel = 0;
- unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
unsigned IsExtern = 0;
unsigned Type = 0;
@@ -545,11 +567,15 @@ public:
// The value which goes in the fixup is current value of the expression.
Fixup.FixedValue = Value + Target.getConstant();
-
- if (isFixupKindPCRel(Fixup.Kind)) {
+ if (IsPCRel)
Fixup.FixedValue -= Address;
- IsPCRel = 1;
- }
+
+ // If this fixup is a vanilla PC relative relocation for a local label, we
+ // don't need a relocation.
+ //
+ // FIXME: Implement proper atom support.
+ if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary())
+ return;
// struct relocation_info (8 bytes)
MachRelocationEntry MRE;
@@ -1040,8 +1066,8 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
// Align the fragment offset; it is safe to adjust the offset freely since
// this is only in virtual sections.
- uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment());
- F.setOffset(Aligned - SD.getAddress());
+ Address = RoundUpToAlignment(Address, ZFF.getAlignment());
+ F.setOffset(Address - SD.getAddress());
// FIXME: This is misnamed.
F.setFileSize(ZFF.getSize());
@@ -1270,9 +1296,15 @@ void MCAssembler::Finish() {
if (!isVirtualSection(SD.getSection()))
continue;
+ // Align this section if necessary by adding padding bytes to the previous
+ // section.
+ if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment()))
+ Address += Pad;
+
SD.setAddress(Address);
LayoutSection(SD);
Address += SD.getSize();
+
}
DEBUG_WITH_TYPE("mc-dump", {
@@ -1336,7 +1368,7 @@ void MCDataFragment::dump() {
OS << ",\n ";
OS << " Fixups:[";
for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) {
- if (it != fixup_begin()) OS << ",\n ";
+ if (it != fixup_begin()) OS << ",\n ";
OS << *it;
}
OS << "]";
@@ -1379,7 +1411,7 @@ void MCSectionData::dump() {
OS << "<MCSectionData";
OS << " Alignment:" << getAlignment() << " Address:" << Address
<< " Size:" << Size << " FileSize:" << FileSize
- << " Fragments:[";
+ << " Fragments:[\n ";
for (iterator it = begin(), ie = end(); it != ie; ++it) {
if (it != begin()) OS << ",\n ";
it->dump();
@@ -1407,7 +1439,7 @@ void MCAssembler::dump() {
raw_ostream &OS = llvm::errs();
OS << "<MCAssembler\n";
- OS << " Sections:[";
+ OS << " Sections:[\n ";
for (iterator it = begin(), ie = end(); it != ie; ++it) {
if (it != begin()) OS << ",\n ";
it->dump();
@@ -1416,7 +1448,7 @@ void MCAssembler::dump() {
OS << " Symbols:[";
for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
- if (it != symbol_begin()) OS << ",\n ";
+ if (it != symbol_begin()) OS << ",\n ";
it->dump();
}
OS << "]>\n";
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 45d2c02..63264f6 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -23,16 +23,8 @@ MCContext::~MCContext() {
// we don't need to free them here.
}
-MCSymbol *MCContext::CreateSymbol(StringRef Name) {
- assert(Name[0] != '\0' && "Normal symbols cannot be unnamed!");
-
- // Create and bind the symbol, and ensure that names are unique.
- MCSymbol *&Entry = Symbols[Name];
- assert(!Entry && "Duplicate symbol definition!");
- return Entry = new (*this) MCSymbol(Name, false);
-}
-
MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) {
+ assert(!Name.empty() && "Normal symbols cannot be unnamed!");
MCSymbol *&Entry = Symbols[Name];
if (Entry) return Entry;
@@ -46,17 +38,24 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
}
-MCSymbol *MCContext::CreateTemporarySymbol(StringRef Name) {
+MCSymbol *MCContext::GetOrCreateTemporarySymbol(StringRef Name) {
// If unnamed, just create a symbol.
if (Name.empty())
new (*this) MCSymbol("", true);
// Otherwise create as usual.
MCSymbol *&Entry = Symbols[Name];
- assert(!Entry && "Duplicate symbol definition!");
+ if (Entry) return Entry;
return Entry = new (*this) MCSymbol(Name, true);
}
+MCSymbol *MCContext::GetOrCreateTemporarySymbol(const Twine &Name) {
+ SmallString<128> NameSV;
+ Name.toVector(NameSV);
+ return GetOrCreateTemporarySymbol(NameSV.str());
+}
+
+
MCSymbol *MCContext::LookupSymbol(StringRef Name) const {
return Symbols.lookup(Name);
}
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index e419043..4439eba 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -133,6 +133,11 @@ const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) {
return Create(Ctx.GetOrCreateSymbol(Name), Ctx);
}
+const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name,
+ MCContext &Ctx) {
+ return Create(Ctx.GetOrCreateTemporarySymbol(Name), Ctx);
+}
+
void MCTargetExpr::Anchor() {}
/* *** */
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index ab61799..5f0c64a 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -29,7 +29,11 @@ namespace {
CurSection = Section;
}
- virtual void EmitLabel(MCSymbol *Symbol) {}
+ virtual void EmitLabel(MCSymbol *Symbol) {
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+ assert(CurSection && "Cannot emit before setting section!");
+ Symbol->setSection(*CurSection);
+ }
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 6185c30..fc8d549 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -240,14 +240,10 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
MCSymbol *AsmParser::CreateSymbol(StringRef Name) {
- if (MCSymbol *S = Ctx.LookupSymbol(Name))
- return S;
-
// If the label starts with L it is an assembler temporary label.
if (Name.startswith("L"))
- return Ctx.CreateTemporarySymbol(Name);
-
- return Ctx.CreateSymbol(Name);
+ return Ctx.GetOrCreateTemporarySymbol(Name);
+ return Ctx.GetOrCreateSymbol(Name);
}
/// ParsePrimaryExpr - Parse a primary expression and return it.
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 15b3079..703acc4 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -31,6 +31,11 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
}
+void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
+ unsigned AddrSpace) {
+ EmitValue(MCSymbolRefExpr::Create(Sym, getContext()), Size, AddrSpace);
+}
+
/// EmitFill - Emit NumBytes bytes worth of the value specified by
/// FillValue. This implements directives such as '.space'.
void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 619f061..8f860a6 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -3366,7 +3366,7 @@ namespace {
void APFloat::toString(SmallVectorImpl<char> &Str,
unsigned FormatPrecision,
- unsigned FormatMaxPadding) {
+ unsigned FormatMaxPadding) const {
switch (category) {
case fcInfinity:
if (isNegative())
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h
index e095acc..0194231 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) {
static inline
bool isIndirectBranchOpcode(int Opc) {
- return Opc == ARM::BRIND || Opc == ARM::tBRIND;
+ return Opc == ARM::BRIND || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND;
}
/// getInstrPredicate - If instruction is predicated, returns its predicate
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 577c363..d9b8323 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -40,7 +40,7 @@
#include "llvm/Support/CommandLine.h"
using namespace llvm;
-static cl::opt<bool>
+cl::opt<bool>
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true),
cl::desc("Reuse repeated frame index values"));
@@ -1153,7 +1153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
unsigned i = 0;
MachineInstr &MI = *II;
@@ -1205,7 +1205,10 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(i).ChangeToRegister(FrameReg, false, false, false);
else {
ScratchReg = MF.getRegInfo().createVirtualRegister(ARM::GPRRegisterClass);
- if (Value) *Value = Offset;
+ if (Value) {
+ Value->first = FrameReg; // use the frame register as a kind indicator
+ Value->second = Offset;
+ }
if (!AFI->isThumbFunction())
emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
Offset, Pred, PredReg, TII);
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h
index 64f6ff1..456c392 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.h
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.h
@@ -145,7 +145,7 @@ public:
MachineBasicBlock::iterator I) const;
virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
virtual void emitPrologue(MachineFunction &MF) const;
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index bd703f4..108a244 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -1138,7 +1138,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
- if (TID.Opcode == ARM::BX_RET)
+ if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR)
// The return register is LR.
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
else
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 6a2c6bb..3dd0313 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -37,9 +37,9 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/VectorExtras.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -130,7 +130,8 @@ void ARMTargetLowering::addQRTypeForNEON(EVT VT) {
static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) {
if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin())
- return new TargetLoweringObjectFileMachO();
+ return new ARMMachOTargetObjectFile();
+
return new ARMElfTargetObjectFile();
}
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 87c6f6e..af82a5f 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -21,7 +21,7 @@ def SDT_ARMCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>;
def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>;
-def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
+def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
def SDT_ARMCMov : SDTypeProfile<1, 3,
[SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
@@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
+def HasV4T : Predicate<"Subtarget->hasV4TOps()">;
+def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
@@ -851,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst),
// Control Flow Instructions.
//
-let isReturn = 1, isTerminator = 1, isBarrier = 1 in
+let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
+ // ARMV4T and above
def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
- "bx", "\tlr", [(ARMretflag)]> {
- let Inst{3-0} = 0b1110;
- let Inst{7-4} = 0b0001;
- let Inst{19-8} = 0b111111111111;
- let Inst{27-20} = 0b00010010;
+ "bx", "\tlr", [(ARMretflag)]>,
+ Requires<[IsARM, HasV4T]> {
+ let Inst{3-0} = 0b1110;
+ let Inst{7-4} = 0b0001;
+ let Inst{19-8} = 0b111111111111;
+ let Inst{27-20} = 0b00010010;
+ }
+
+ // ARMV4 only
+ def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br,
+ "mov", "\tpc, lr", [(ARMretflag)]>,
+ Requires<[IsARM, NoV4T]> {
+ let Inst{11-0} = 0b000000001110;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
// Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
+ // ARMV4T and above
def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst",
- [(brind GPR:$dst)]> {
+ [(brind GPR:$dst)]>,
+ Requires<[IsARM, HasV4T]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
let Inst{31-28} = 0b1110;
}
+
+ // ARMV4 only
+ def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst",
+ [(brind GPR:$dst)]>,
+ Requires<[IsARM, NoV4T]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ let Inst{31-28} = 0b1110;
+ }
}
// FIXME: remove when we have a way to marking a MI with these properties.
@@ -913,11 +941,22 @@ let isCall = 1,
def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$func)]>,
- Requires<[IsARM, IsNotDarwin]> {
+ Requires<[IsARM, HasV4T, IsNotDarwin]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
}
+
+ // ARMv4
+ def BMOVPCRX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
+ IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
+ [(ARMcall_nolink tGPR:$func)]>,
+ Requires<[IsARM, NoV4T, IsNotDarwin]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
// On Darwin R9 is call-clobbered.
@@ -950,11 +989,23 @@ let isCall = 1,
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
- [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsDarwin]> {
+ [(ARMcall_nolink tGPR:$func)]>,
+ Requires<[IsARM, HasV4T, IsDarwin]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
}
+
+ // ARMv4
+ def BMOVPCRXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
+ IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
+ [(ARMcall_nolink tGPR:$func)]>,
+ Requires<[IsARM, NoV4T, IsDarwin]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
let isBranch = 1, isTerminator = 1 in {
@@ -2793,29 +2844,29 @@ def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr",
let Inst{7-4} = 0b0000;
}
-// FIXME: mask is ignored for the time being.
-def MSR : ABI<0b0001,(outs),(ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
+def MSR : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
+ "\tcpsr${mask:msr}, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
}
-// FIXME: mask is ignored for the time being.
-def MSRi : ABI<0b0011,(outs),(ins so_imm:$a), NoItinerary, "msr", "\tcpsr, $a",
+def MSRi : ABI<0b0011, (outs), (ins so_imm:$a, i32imm:$mask), NoItinerary,"msr",
+ "\tcpsr${mask:msr}, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
}
-// FIXME: mask is ignored for the time being.
-def MSRsys : ABI<0b0001,(outs),(ins GPR:$src),NoItinerary,"msr","\tspsr, $src",
+def MSRsys : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask),NoItinerary,"msr",
+ "\tspsr${mask:msr}, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
}
-// FIXME: mask is ignored for the time being.
-def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a),NoItinerary,"msr","\tspsr, $a",
+def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a, i32imm:$mask),NoItinerary,"msr",
+ "\tspsr${mask:msr}, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 3aa0810..7c44a2f 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -2707,21 +2707,21 @@ def VSETLNi32 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, 0b00, (outs DPR:$dst),
}
def : Pat<(vector_insert (v16i8 QPR:$src1), GPR:$src2, imm:$lane),
(v16i8 (INSERT_SUBREG QPR:$src1,
- (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1,
+ (v8i8 (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1,
(DSubReg_i8_reg imm:$lane))),
- GPR:$src2, (SubReg_i8_lane imm:$lane)),
+ GPR:$src2, (SubReg_i8_lane imm:$lane))),
(DSubReg_i8_reg imm:$lane)))>;
def : Pat<(vector_insert (v8i16 QPR:$src1), GPR:$src2, imm:$lane),
(v8i16 (INSERT_SUBREG QPR:$src1,
- (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1,
+ (v4i16 (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1,
(DSubReg_i16_reg imm:$lane))),
- GPR:$src2, (SubReg_i16_lane imm:$lane)),
+ GPR:$src2, (SubReg_i16_lane imm:$lane))),
(DSubReg_i16_reg imm:$lane)))>;
def : Pat<(insertelt (v4i32 QPR:$src1), GPR:$src2, imm:$lane),
(v4i32 (INSERT_SUBREG QPR:$src1,
- (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1,
+ (v2i32 (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1,
(DSubReg_i32_reg imm:$lane))),
- GPR:$src2, (SubReg_i32_lane imm:$lane)),
+ GPR:$src2, (SubReg_i32_lane imm:$lane))),
(DSubReg_i32_reg imm:$lane)))>;
def : Pat<(v2f32 (insertelt DPR:$src1, SPR:$src2, imm:$src3)),
@@ -3093,16 +3093,17 @@ def VTBX4
class N2VSPat<SDNode OpNode, ValueType ResTy, ValueType OpTy, NeonI Inst>
: NEONFPPat<(ResTy (OpNode SPR:$a)),
- (EXTRACT_SUBREG (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)),
- SPR:$a, arm_ssubreg_0)),
+ (EXTRACT_SUBREG (OpTy (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)),
+ SPR:$a, arm_ssubreg_0))),
arm_ssubreg_0)>;
class N3VSPat<SDNode OpNode, NeonI Inst>
: NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)),
- (EXTRACT_SUBREG (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
- SPR:$a, arm_ssubreg_0),
- (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
- SPR:$b, arm_ssubreg_0)),
+ (EXTRACT_SUBREG (v2f32
+ (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
+ SPR:$a, arm_ssubreg_0),
+ (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
+ SPR:$b, arm_ssubreg_0))),
arm_ssubreg_0)>;
class N3VSMulOpPat<SDNode MulNode, SDNode OpNode, NeonI Inst>
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 6241766..2fc7d2f 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -331,9 +331,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
let Inst{15} = 0;
}
// 12-bit imm
- def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
- !strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
- [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> {
+ def ri12 : T2I<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
+ !strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> {
let Inst{31-27} = 0b11110;
let Inst{25} = 1;
let Inst{24} = 0;
@@ -2637,9 +2637,9 @@ def t2MRSsys : T2I<(outs GPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, spsr",
let Inst{12} = 0;
}
-// FIXME: mask is ignored for the time being.
// Rn = Inst{19-16}
-def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
+def t2MSR : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
+ "\tcpsr${mask:msr}, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-27} = 0b11110;
let Inst{26} = 0;
@@ -2649,9 +2649,9 @@ def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
let Inst{12} = 0;
}
-// FIXME: mask is ignored for the time being.
// Rn = Inst{19-16}
-def t2MSRsys : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tspsr, $src",
+def t2MSRsys : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
+ "\tspsr${mask:msr}, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-27} = 0b11110;
let Inst{26} = 0;
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index 7c117ed..cad24c4 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -57,7 +57,7 @@ def vfp_f64imm : Operand<f64>,
let canFoldAsLoad = 1, isReMaterializable = 1 in {
def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr),
IIC_fpLoad64, "vldr", ".64\t$dst, $addr",
- [(set DPR:$dst, (load addrmode5:$addr))]>;
+ [(set DPR:$dst, (f64 (load addrmode5:$addr)))]>;
def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
IIC_fpLoad32, "vldr", ".32\t$dst, $addr",
@@ -66,7 +66,7 @@ def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr),
IIC_fpStore64, "vstr", ".64\t$src, $addr",
- [(store DPR:$src, addrmode5:$addr)]>;
+ [(store (f64 DPR:$src), addrmode5:$addr)]>;
def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr),
IIC_fpStore32, "vstr", ".32\t$src, $addr",
@@ -116,7 +116,7 @@ def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb,
def VADDD : ADbI<0b11100, 0b11, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
IIC_fpALU64, "vadd", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>;
+ [(set DPR:$dst, (fadd DPR:$a, (f64 DPR:$b)))]>;
def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
IIC_fpALU32, "vadd", ".f32\t$dst, $a, $b",
@@ -126,7 +126,7 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
let Defs = [FPSCR] in {
def VCMPED : ADuI<0b11101, 0b11, 0b0100, 0b11, 0, (outs), (ins DPR:$a, DPR:$b),
IIC_fpCMP64, "vcmpe", ".f64\t$a, $b",
- [(arm_cmpfp DPR:$a, DPR:$b)]>;
+ [(arm_cmpfp DPR:$a, (f64 DPR:$b))]>;
def VCMPD : ADuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins DPR:$a, DPR:$b),
IIC_fpCMP64, "vcmp", ".f64\t$a, $b",
@@ -143,7 +143,7 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins SPR:$a, SPR:$b),
def VDIVD : ADbI<0b11101, 0b00, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
IIC_fpDIV64, "vdiv", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>;
+ [(set DPR:$dst, (fdiv DPR:$a, (f64 DPR:$b)))]>;
def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
IIC_fpDIV32, "vdiv", ".f32\t$dst, $a, $b",
@@ -151,7 +151,7 @@ def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
def VMULD : ADbI<0b11100, 0b10, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
IIC_fpMUL64, "vmul", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>;
+ [(set DPR:$dst, (fmul DPR:$a, (f64 DPR:$b)))]>;
def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
IIC_fpMUL32, "vmul", ".f32\t$dst, $a, $b",
@@ -159,14 +159,14 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
def VNMULD : ADbI<0b11100, 0b10, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
IIC_fpMUL64, "vnmul", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>;
+ [(set DPR:$dst, (fneg (fmul DPR:$a, (f64 DPR:$b))))]>;
def VNMULS : ASbI<0b11100, 0b10, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
IIC_fpMUL32, "vnmul", ".f32\t$dst, $a, $b",
[(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>;
// Match reassociated forms only if not sign dependent rounding.
-def : Pat<(fmul (fneg DPR:$a), DPR:$b),
+def : Pat<(fmul (fneg DPR:$a), (f64 DPR:$b)),
(VNMULD DPR:$a, DPR:$b)>, Requires<[NoHonorSignDependentRounding]>;
def : Pat<(fmul (fneg SPR:$a), SPR:$b),
(VNMULS SPR:$a, SPR:$b)>, Requires<[NoHonorSignDependentRounding]>;
@@ -174,7 +174,7 @@ def : Pat<(fmul (fneg SPR:$a), SPR:$b),
def VSUBD : ADbI<0b11100, 0b11, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
IIC_fpALU64, "vsub", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>;
+ [(set DPR:$dst, (fsub DPR:$a, (f64 DPR:$b)))]>;
def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
IIC_fpALU32, "vsub", ".f32\t$dst, $a, $b",
@@ -186,7 +186,7 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
def VABSD : ADuI<0b11101, 0b11, 0b0000, 0b11, 0, (outs DPR:$dst), (ins DPR:$a),
IIC_fpUNA64, "vabs", ".f64\t$dst, $a",
- [(set DPR:$dst, (fabs DPR:$a))]>;
+ [(set DPR:$dst, (fabs (f64 DPR:$a)))]>;
def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a),
IIC_fpUNA32, "vabs", ".f32\t$dst, $a",
@@ -195,7 +195,7 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a),
let Defs = [FPSCR] in {
def VCMPEZD : ADuI<0b11101, 0b11, 0b0101, 0b11, 0, (outs), (ins DPR:$a),
IIC_fpCMP64, "vcmpe", ".f64\t$a, #0",
- [(arm_cmpfp0 DPR:$a)]>;
+ [(arm_cmpfp0 (f64 DPR:$a))]>;
def VCMPZD : ADuI<0b11101, 0b11, 0b0101, 0b01, 0, (outs), (ins DPR:$a),
IIC_fpCMP64, "vcmp", ".f64\t$a, #0",
@@ -253,7 +253,7 @@ def VMOVS: ASuI<0b11101, 0b11, 0b0000, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
def VNEGD : ADuI<0b11101, 0b11, 0b0001, 0b01, 0, (outs DPR:$dst), (ins DPR:$a),
IIC_fpUNA64, "vneg", ".f64\t$dst, $a",
- [(set DPR:$dst, (fneg DPR:$a))]>;
+ [(set DPR:$dst, (fneg (f64 DPR:$a)))]>;
def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a),
IIC_fpUNA32, "vneg", ".f32\t$dst, $a",
@@ -261,7 +261,7 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a),
def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs DPR:$dst), (ins DPR:$a),
IIC_fpSQRT64, "vsqrt", ".f64\t$dst, $a",
- [(set DPR:$dst, (fsqrt DPR:$a))]>;
+ [(set DPR:$dst, (fsqrt (f64 DPR:$a)))]>;
def VSQRTS : ASuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs SPR:$dst), (ins SPR:$a),
IIC_fpSQRT32, "vsqrt", ".f32\t$dst, $a",
@@ -325,7 +325,7 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010,
def VSITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011,
(outs DPR:$dst), (ins SPR:$a),
IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a",
- [(set DPR:$dst, (arm_sitof SPR:$a))]> {
+ [(set DPR:$dst, (f64 (arm_sitof SPR:$a)))]> {
let Inst{7} = 1; // s32
}
@@ -339,7 +339,7 @@ def VSITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010,
def VUITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011,
(outs DPR:$dst), (ins SPR:$a),
IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a",
- [(set DPR:$dst, (arm_uitof SPR:$a))]> {
+ [(set DPR:$dst, (f64 (arm_uitof SPR:$a)))]> {
let Inst{7} = 0; // u32
}
@@ -356,7 +356,7 @@ def VUITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010,
def VTOSIZD : AVConv1I<0b11101, 0b11, 0b1101, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a",
- [(set SPR:$dst, (arm_ftosi DPR:$a))]> {
+ [(set SPR:$dst, (arm_ftosi (f64 DPR:$a)))]> {
let Inst{7} = 1; // Z bit
}
@@ -370,7 +370,7 @@ def VTOSIZS : AVConv1In<0b11101, 0b11, 0b1101, 0b1010,
def VTOUIZD : AVConv1I<0b11101, 0b11, 0b1100, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a",
- [(set SPR:$dst, (arm_ftoui DPR:$a))]> {
+ [(set SPR:$dst, (arm_ftoui (f64 DPR:$a)))]> {
let Inst{7} = 1; // Z bit
}
@@ -514,7 +514,8 @@ def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1,
def VMLAD : ADbI<0b11100, 0b00, 0, 0,
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
IIC_fpMAC64, "vmla", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
+ [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b),
+ (f64 DPR:$dstin)))]>,
RegConstraint<"$dstin = $dst">;
def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
@@ -526,7 +527,8 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
def VNMLSD : ADbI<0b11100, 0b01, 0, 0,
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
IIC_fpMAC64, "vnmls", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
+ [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b),
+ (f64 DPR:$dstin)))]>,
RegConstraint<"$dstin = $dst">;
def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
@@ -538,7 +540,8 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
def VMLSD : ADbI<0b11100, 0b00, 1, 0,
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
IIC_fpMAC64, "vmls", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
+ [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)),
+ (f64 DPR:$dstin)))]>,
RegConstraint<"$dstin = $dst">;
def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
@@ -547,7 +550,7 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
[(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
RegConstraint<"$dstin = $dst">;
-def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, DPR:$b)),
+def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, (f64 DPR:$b))),
(VMLSD DPR:$dstin, DPR:$a, DPR:$b)>, Requires<[DontUseNEONForFP]>;
def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)),
(VMLSS SPR:$dstin, SPR:$a, SPR:$b)>, Requires<[DontUseNEONForFP]>;
@@ -555,7 +558,8 @@ def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)),
def VNMLAD : ADbI<0b11100, 0b01, 1, 0,
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
IIC_fpMAC64, "vnmla", ".f64\t$dst, $a, $b",
- [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
+ [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)),
+ (f64 DPR:$dstin)))]>,
RegConstraint<"$dstin = $dst">;
def VNMLAS : ASbI<0b11100, 0b01, 1, 0,
diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/ARMMCAsmInfo.cpp
index ccd6add..20197e4 100644
--- a/lib/Target/ARM/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/ARMMCAsmInfo.cpp
@@ -48,7 +48,6 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() {
// Exceptions handling
ExceptionsType = ExceptionHandling::SjLj;
- AbsoluteEHSectionOffsets = false;
}
ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp
index 426862c..622034b 100644
--- a/lib/Target/ARM/ARMSubtarget.cpp
+++ b/lib/Target/ARM/ARMSubtarget.cpp
@@ -33,7 +33,7 @@ UseMOVT("arm-use-movt",
ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
bool isT)
- : ARMArchVersion(V4T)
+ : ARMArchVersion(V4)
, ARMFPUType(None)
, UseNEONForSinglePrecisionFP(UseNEONFP)
, IsThumb(isT)
@@ -54,6 +54,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
// Parse features string.
CPUString = ParseSubtargetFeatures(FS, CPUString);
+ // When no arch is specified either by CPU or by attributes, make the default
+ // ARMv4T.
+ if (CPUString == "generic" && (FS.empty() || FS == "generic"))
+ ARMArchVersion = V4T;
+
// Set the boolean corresponding to the current target triple, or the default
// if one cannot be determined, to true.
unsigned Len = TT.length();
@@ -68,25 +73,28 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
}
if (Idx) {
unsigned SubVer = TT[Idx];
- if (SubVer > '4' && SubVer <= '9') {
- if (SubVer >= '7') {
- ARMArchVersion = V7A;
- } else if (SubVer == '6') {
- ARMArchVersion = V6;
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
- ARMArchVersion = V6T2;
- } else if (SubVer == '5') {
- ARMArchVersion = V5T;
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
- ARMArchVersion = V5TE;
- }
- if (ARMArchVersion >= V6T2)
- ThumbMode = Thumb2;
+ if (SubVer >= '7' && SubVer <= '9') {
+ ARMArchVersion = V7A;
+ } else if (SubVer == '6') {
+ ARMArchVersion = V6;
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
+ ARMArchVersion = V6T2;
+ } else if (SubVer == '5') {
+ ARMArchVersion = V5T;
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
+ ARMArchVersion = V5TE;
+ } else if (SubVer == '4') {
+ if (Len >= Idx+2 && TT[Idx+1] == 't')
+ ARMArchVersion = V4T;
+ else
+ ARMArchVersion = V4;
}
}
// Thumb2 implies at least V6T2.
- if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2)
+ if (ARMArchVersion >= V6T2)
+ ThumbMode = Thumb2;
+ else if (ThumbMode >= Thumb2)
ARMArchVersion = V6T2;
if (Len >= 10) {
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index 3f06b7b..6980851 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -26,7 +26,7 @@ class GlobalValue;
class ARMSubtarget : public TargetSubtarget {
protected:
enum ARMArchEnum {
- V4T, V5T, V5TE, V6, V6T2, V7A
+ V4, V4T, V5T, V5TE, V6, V6T2, V7A
};
enum ARMFPEnum {
@@ -38,7 +38,7 @@ protected:
Thumb2
};
- /// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE,
+ /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
/// V6, V6T2, V7A.
ARMArchEnum ARMArchVersion;
diff --git a/lib/Target/ARM/ARMTargetObjectFile.cpp b/lib/Target/ARM/ARMTargetObjectFile.cpp
new file mode 100644
index 0000000..7463e30
--- /dev/null
+++ b/lib/Target/ARM/ARMTargetObjectFile.cpp
@@ -0,0 +1,54 @@
+//===-- llvm/Target/ARMTargetObjectFile.cpp - ARM Object Info Impl --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMTargetObjectFile.h"
+#include "ARMSubtarget.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Target/TargetMachine.h"
+using namespace llvm;
+using namespace dwarf;
+
+//===----------------------------------------------------------------------===//
+// ELF Target
+//===----------------------------------------------------------------------===//
+
+void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
+ const TargetMachine &TM) {
+ TargetLoweringObjectFileELF::Initialize(Ctx, TM);
+
+ if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) {
+ StaticCtorSection =
+ getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY,
+ MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
+ SectionKind::getDataRel());
+ StaticDtorSection =
+ getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY,
+ MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
+ SectionKind::getDataRel());
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Mach-O Target
+//===----------------------------------------------------------------------===//
+
+void ARMMachOTargetObjectFile::Initialize(MCContext &Ctx,
+ const TargetMachine &TM) {
+ TargetLoweringObjectFileMachO::Initialize(Ctx, TM);
+
+ // Exception Handling.
+ LSDASection = getMachOSection("__TEXT", "__gcc_except_tab", 0,
+ SectionKind::getReadOnlyWithRel());
+}
+
+unsigned ARMMachOTargetObjectFile::getTTypeEncoding() const {
+ return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+}
diff --git a/lib/Target/ARM/ARMTargetObjectFile.h b/lib/Target/ARM/ARMTargetObjectFile.h
index a488c0a..481d7ab 100644
--- a/lib/Target/ARM/ARMTargetObjectFile.h
+++ b/lib/Target/ARM/ARMTargetObjectFile.h
@@ -11,29 +11,31 @@
#define LLVM_TARGET_ARM_TARGETOBJECTFILE_H
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
-#include "llvm/MC/MCSectionELF.h"
namespace llvm {
- class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
- public:
- ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {}
-
- void Initialize(MCContext &Ctx, const TargetMachine &TM) {
- TargetLoweringObjectFileELF::Initialize(Ctx, TM);
-
- if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) {
- StaticCtorSection =
- getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY,
- MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
- SectionKind::getDataRel());
- StaticDtorSection =
- getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY,
- MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
- SectionKind::getDataRel());
- }
- }
- };
+class MCContext;
+class TargetMachine;
+
+class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
+public:
+ ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {}
+
+ virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
+};
+
+// FIXME: This subclass isn't 100% necessary. It will become obsolete once we
+// can place all LSDAs into the TEXT section. See
+// <rdar://problem/6804645>.
+class ARMMachOTargetObjectFile : public TargetLoweringObjectFileMachO {
+public:
+ ARMMachOTargetObjectFile() : TargetLoweringObjectFileMachO() {}
+
+ virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
+
+ virtual unsigned getTTypeEncoding() const;
+};
+
} // end namespace llvm
#endif
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
index d6d595c..314114c 100644
--- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
@@ -33,6 +33,7 @@
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -848,7 +849,7 @@ GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << '_' << uid2
<< "_set_" << MBB->getNumber();
- return OutContext.GetOrCreateSymbol(Name.str());
+ return OutContext.GetOrCreateTemporarySymbol(Name.str());
}
MCSymbol *ARMAsmPrinter::
@@ -856,7 +857,7 @@ GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
SmallString<60> Name;
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
<< getFunctionNumber() << '_' << uid << '_' << uid2;
- return OutContext.GetOrCreateSymbol(Name.str());
+ return OutContext.GetOrCreateTemporarySymbol(Name.str());
}
void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
@@ -1128,17 +1129,40 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
EmitAlignment(2);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- O << *Stubs[i].first << ":\n\t.indirect_symbol ";
- O << *Stubs[i].second << "\n\t.long\t0\n";
+ // L_foo$stub:
+ OutStreamer.EmitLabel(Stubs[i].first);
+ // .indirect_symbol _foo
+ MCSymbol *MCSym = Stubs[i].second;
+ OutStreamer.EmitSymbolAttribute(MCSym, MCSA_IndirectSymbol);
+
+ if (MCSym->isUndefined())
+ // External to current translation unit.
+ OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
+ else
+ // Internal to current translation unit.
+ OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym, OutContext),
+ 4/*size*/, 0/*addrspace*/);
}
+
+ Stubs.clear();
+ OutStreamer.AddBlankLine();
}
Stubs = MMIMacho.GetHiddenGVStubList();
if (!Stubs.empty()) {
OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
EmitAlignment(2);
- for (unsigned i = 0, e = Stubs.size(); i != e; ++i)
- O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n";
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ // L_foo$stub:
+ OutStreamer.EmitLabel(Stubs[i].first);
+ // .long _foo
+ OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second,
+ OutContext),
+ 4/*size*/, 0/*addrspace*/);
+ }
+
+ Stubs.clear();
+ OutStreamer.AddBlankLine();
}
// Funny Darwin hack: This flag tells the linker that no global symbols
@@ -1168,7 +1192,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
// FIXME: MOVE TO SHARED PLACE.
unsigned Id = (unsigned)MI->getOperand(2).getImm();
const char *Prefix = MAI->getPrivateGlobalPrefix();
- MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix)
+ MCSymbol *Label =OutContext.GetOrCreateTemporarySymbol(Twine(Prefix)
+ "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id));
OutStreamer.EmitLabel(Label);
diff --git a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
index 1b2dd48..5f8705e 100644
--- a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
@@ -74,7 +74,7 @@ GetJumpTableSymbol(const MachineOperand &MO) const {
#endif
// Create a symbol for the name.
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Ctx.GetOrCreateTemporarySymbol(Name.str());
}
MCSymbol *ARMMCInstLower::
@@ -90,7 +90,7 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
#endif
// Create a symbol for the name.
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Ctx.GetOrCreateTemporarySymbol(Name.str());
}
MCOperand ARMMCInstLower::
diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt
index 964551f..bbc0095 100644
--- a/lib/Target/ARM/CMakeLists.txt
+++ b/lib/Target/ARM/CMakeLists.txt
@@ -27,6 +27,7 @@ add_llvm_target(ARMCodeGen
ARMRegisterInfo.cpp
ARMSubtarget.cpp
ARMTargetMachine.cpp
+ ARMTargetObjectFile.cpp
NEONMoveFix.cpp
NEONPreAllocPass.cpp
Thumb1InstrInfo.cpp
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp
index 163d1e9..6215d2f 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.cpp
+++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp
@@ -33,10 +33,13 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+extern cl::opt<bool> ReuseFrameIndexVals;
+
Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii,
const ARMSubtarget &sti)
: ARMBaseRegisterInfo(tii, sti) {
@@ -426,7 +429,7 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
unsigned
Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const{
unsigned VReg = 0;
unsigned i = 0;
@@ -638,8 +641,10 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
} else if (Desc.mayStore()) {
VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
assert (Value && "Frame index virtual allocated, but Value arg is NULL!");
- *Value = Offset;
bool UseRR = false;
+ bool TrackVReg = true;
+ Value->first = FrameReg; // use the frame register as a kind indicator
+ Value->second = Offset;
if (Opcode == ARM::tSpill) {
if (FrameReg == ARM::SP)
@@ -648,6 +653,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
else {
emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
UseRR = true;
+ TrackVReg = false;
}
} else
emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII,
@@ -658,6 +664,8 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
else // tSTR has an extra register operand.
MI.addOperand(MachineOperand::CreateReg(0, false));
+ if (!ReuseFrameIndexVals || !TrackVReg)
+ VReg = 0;
} else
assert(false && "Unexpected opcode!");
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.h b/lib/Target/ARM/Thumb1RegisterInfo.h
index 37ad388..4eca367 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.h
+++ b/lib/Target/ARM/Thumb1RegisterInfo.h
@@ -59,7 +59,7 @@ public:
const TargetRegisterClass *RC,
unsigned Reg) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void emitPrologue(MachineFunction &MF) const;
diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp
index 20f13f1..e4abcdb 100644
--- a/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -164,6 +164,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
continue;
}
+ bool HasCCOut = true;
if (BaseReg == ARM::SP) {
// sub sp, sp, #imm7
if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) {
@@ -195,6 +196,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
NumBytes = 0;
} else if (ThisVal < 4096) {
Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
+ HasCCOut = false;
NumBytes = 0;
} else {
// FIXME: Move this to ARMAddressingModes.h?
@@ -207,9 +209,12 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
}
// Build the new ADD / SUB.
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
- .addReg(BaseReg, RegState::Kill)
- .addImm(ThisVal)));
+ MachineInstrBuilder MIB =
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
+ .addReg(BaseReg, RegState::Kill)
+ .addImm(ThisVal));
+ if (HasCCOut)
+ AddDefaultCC(MIB);
BaseReg = DestReg;
}
@@ -328,7 +333,6 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
Offset += MI.getOperand(FrameRegIdx+1).getImm();
- bool isSP = FrameReg == ARM::SP;
unsigned PredReg;
if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
// Turn it into a move.
@@ -342,6 +346,9 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
return true;
}
+ bool isSP = FrameReg == ARM::SP;
+ bool HasCCOut = Opcode != ARM::t2ADDri12;
+
if (Offset < 0) {
Offset = -Offset;
isSub = true;
@@ -354,17 +361,24 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
if (ARM_AM::getT2SOImmVal(Offset) != -1) {
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
+ // Add cc_out operand if the original instruction did not have one.
+ if (!HasCCOut)
+ MI.addOperand(MachineOperand::CreateReg(0, false));
Offset = 0;
return true;
}
// Another common case: imm12.
- if (Offset < 4096) {
+ if (Offset < 4096 &&
+ (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
unsigned NewOpc = isSP
? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12)
: (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12);
MI.setDesc(TII.get(NewOpc));
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
+ // Remove the cc_out operand.
+ if (HasCCOut)
+ MI.RemoveOperand(MI.getNumOperands()-1);
Offset = 0;
return true;
}
@@ -380,6 +394,10 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
"Bit extraction didn't work?");
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
+ // Add cc_out operand if the original instruction did not have one.
+ if (!HasCCOut)
+ MI.addOperand(MachineOperand::CreateReg(0, false));
+
} else {
// AddrMode4 and AddrMode6 cannot handle any offset.
diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td
index 341c4a7..95de3d8 100644
--- a/lib/Target/Alpha/AlphaInstrInfo.td
+++ b/lib/Target/Alpha/AlphaInstrInfo.td
@@ -892,7 +892,7 @@ def : Pat<(brcond (setge GPRC:$RA, 0), bb:$DISP),
(COND_BRANCH_I (immBRCond 2), GPRC:$RA, bb:$DISP)>;
def : Pat<(brcond (setgt GPRC:$RA, 0), bb:$DISP),
(COND_BRANCH_I (immBRCond 3), GPRC:$RA, bb:$DISP)>;
-def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP),
+def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP),
(COND_BRANCH_I (immBRCond 6), GPRC:$RA, bb:$DISP)>;
def : Pat<(brcond (setle GPRC:$RA, 0), bb:$DISP),
(COND_BRANCH_I (immBRCond 4), GPRC:$RA, bb:$DISP)>;
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp
index ba662fb..55eec3a 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.cpp
+++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp
@@ -153,7 +153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h
index a971e21..720367a 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.h
+++ b/lib/Target/Alpha/AlphaRegisterInfo.h
@@ -42,7 +42,7 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
//void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
index 224165b..b39a342 100644
--- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
+++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
@@ -221,7 +221,7 @@ static unsigned findScratchRegister(MachineBasicBlock::iterator II,
unsigned
BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.h b/lib/Target/Blackfin/BlackfinRegisterInfo.h
index 68ef08a..7cfb120 100644
--- a/lib/Target/Blackfin/BlackfinRegisterInfo.h
+++ b/lib/Target/Blackfin/BlackfinRegisterInfo.h
@@ -65,7 +65,7 @@ namespace llvm {
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
diff --git a/lib/Target/CellSPU/CellSDKIntrinsics.td b/lib/Target/CellSPU/CellSDKIntrinsics.td
index 5d759a4..1fe7aff 100644
--- a/lib/Target/CellSPU/CellSDKIntrinsics.td
+++ b/lib/Target/CellSPU/CellSDKIntrinsics.td
@@ -205,6 +205,7 @@ def CellSDKnand:
// Shift/rotate intrinsics:
//===----------------------------------------------------------------------===//
+/* FIXME: These have (currently unenforced) type conflicts. */
def CellSDKshli:
Pat<(int_spu_si_shli (v4i32 VECREG:$rA), uimm7:$val),
(SHLIv4i32 VECREG:$rA, uimm7:$val)>;
diff --git a/lib/Target/CellSPU/SPUInstrInfo.td b/lib/Target/CellSPU/SPUInstrInfo.td
index f24ffd2..b96b64e 100644
--- a/lib/Target/CellSPU/SPUInstrInfo.td
+++ b/lib/Target/CellSPU/SPUInstrInfo.td
@@ -2370,7 +2370,7 @@ class ROTHInst<dag OOL, dag IOL, list<dag> pattern>:
class ROTHVecInst<ValueType vectype>:
ROTHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
[(set (vectype VECREG:$rT),
- (SPUvec_rotl VECREG:$rA, VECREG:$rB))]>;
+ (SPUvec_rotl VECREG:$rA, (v8i16 VECREG:$rB)))]>;
class ROTHRegInst<RegisterClass rclass>:
ROTHInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
diff --git a/lib/Target/CellSPU/SPUMathInstr.td b/lib/Target/CellSPU/SPUMathInstr.td
index 80ebde3..ed7129e 100644
--- a/lib/Target/CellSPU/SPUMathInstr.td
+++ b/lib/Target/CellSPU/SPUMathInstr.td
@@ -45,9 +45,9 @@ def : Pat<(mul (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)),
def MPYv4i32:
Pat<(mul (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)),
(Av4i32
- (Av4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB),
- (MPYHv4i32 VECREG:$rB, VECREG:$rA)),
- (MPYUv4i32 VECREG:$rA, VECREG:$rB))>;
+ (v4i32 (Av4i32 (v4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB)),
+ (v4i32 (MPYHv4i32 VECREG:$rB, VECREG:$rA)))),
+ (v4i32 (MPYUv4i32 VECREG:$rA, VECREG:$rB)))>;
def MPYi32:
Pat<(mul R32C:$rA, R32C:$rB),
diff --git a/lib/Target/CellSPU/SPUNodes.td b/lib/Target/CellSPU/SPUNodes.td
index c722e4b..8507861 100644
--- a/lib/Target/CellSPU/SPUNodes.td
+++ b/lib/Target/CellSPU/SPUNodes.td
@@ -26,7 +26,7 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPUCallSeq,
// Operand constraints:
//===----------------------------------------------------------------------===//
-def SDT_SPUCall : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
+def SDT_SPUCall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
def SPUcall : SDNode<"SPUISD::CALL", SDT_SPUCall,
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp
index af94e67..4ba0cb1 100644
--- a/lib/Target/CellSPU/SPURegisterInfo.cpp
+++ b/lib/Target/CellSPU/SPURegisterInfo.cpp
@@ -328,7 +328,8 @@ SPURegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF,
unsigned
SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
- int *Value, RegScavenger *RS) const
+ FrameIndexValue *Value,
+ RegScavenger *RS) const
{
unsigned i = 0;
MachineInstr &MI = *II;
diff --git a/lib/Target/CellSPU/SPURegisterInfo.h b/lib/Target/CellSPU/SPURegisterInfo.h
index 9691cb6..48feb5c 100644
--- a/lib/Target/CellSPU/SPURegisterInfo.h
+++ b/lib/Target/CellSPU/SPURegisterInfo.h
@@ -64,7 +64,7 @@ namespace llvm {
MachineBasicBlock::iterator I) const;
//! Convert frame indicies into machine operands
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
- int *Value = NULL,
+ FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
//! Determine the frame's layour
void determineFrameLayout(MachineFunction &MF) const;
diff --git a/lib/Target/MBlaze/MBlazeCallingConv.td b/lib/Target/MBlaze/MBlazeCallingConv.td
index dfc87f5..ddd4998 100644
--- a/lib/Target/MBlaze/MBlazeCallingConv.td
+++ b/lib/Target/MBlaze/MBlazeCallingConv.td
@@ -17,21 +17,6 @@ class CCIfSubtarget<string F, CCAction A>:
// MBlaze ABI Calling Convention
//===----------------------------------------------------------------------===//
-def CC_MBlaze : CallingConv<[
- // Promote i8/i16 arguments to i32.
- CCIfType<[i8, i16], CCPromoteToType<i32>>,
-
- // Integer arguments are passed in integer registers.
- CCIfType<[i32], CCAssignToReg<[R5, R6, R7, R8, R9, R10]>>,
-
- // Single fp arguments are passed in floating point registers
- CCIfType<[f32], CCAssignToReg<[F5, F6, F7, F8, F9, F10]>>,
-
- // 32-bit values get stored in stack slots that are 4 bytes in
- // size and 4-byte aligned.
- CCIfType<[i32, f32], CCAssignToStack<4, 4>>
-]>;
-
def RetCC_MBlaze : CallingConv<[
// i32 are returned in registers R3, R4
CCIfType<[i32], CCAssignToReg<[R3, R4]>>,
diff --git a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp
index a0ebea0..7e59c4a 100644
--- a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp
+++ b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp
@@ -129,15 +129,15 @@ SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) {
N.getOpcode() == ISD::TargetGlobalAddress)
return false; // direct calls.
- if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
- N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
- return false; // jump tables.
-
int32_t imm = 0;
if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
if (isIntS32Immediate(N.getOperand(1), imm))
return false; // r+i
+ if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
+ N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
+ return false; // jump tables.
+
Base = N.getOperand(1);
Index = N.getOperand(0);
return true;
diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp
index 7790248..f0864d0 100644
--- a/lib/Target/MBlaze/MBlazeISelLowering.cpp
+++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp
@@ -138,6 +138,13 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM)
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+ // Variable Argument support
+ setOperationAction(ISD::VASTART, MVT::Other, Custom);
+ setOperationAction(ISD::VAEND, MVT::Other, Expand);
+ setOperationAction(ISD::VAARG, MVT::Other, Expand);
+ setOperationAction(ISD::VACOPY, MVT::Other, Expand);
+
+
// Operations not directly supported by MBlaze.
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
@@ -186,6 +193,7 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
+ case ISD::VASTART: return LowerVASTART(Op, DAG);
}
return SDValue();
}
@@ -440,7 +448,6 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
Constant *C = N->getConstVal();
SDValue Zero = DAG.getConstant(0, PtrVT);
- // FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(),
@@ -448,12 +455,71 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP);
}
+SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) {
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue FI = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy());
+
+ // vastart just stores the address of the VarArgsFrameIndex slot into the
+ // memory location argument.
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+ return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0,
+ false, false, 0);
+}
+
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//===----------------------------------------------------------------------===//
#include "MBlazeGenCallingConv.inc"
+static bool CC_MBlaze2(unsigned ValNo, EVT ValVT,
+ EVT LocVT, CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State) {
+ static const unsigned RegsSize=6;
+ static const unsigned IntRegs[] = {
+ MBlaze::R5, MBlaze::R6, MBlaze::R7,
+ MBlaze::R8, MBlaze::R9, MBlaze::R10
+ };
+
+ static const unsigned FltRegs[] = {
+ MBlaze::F5, MBlaze::F6, MBlaze::F7,
+ MBlaze::F8, MBlaze::F9, MBlaze::F10
+ };
+
+ unsigned Reg=0;
+
+ // Promote i8 and i16
+ if (LocVT == MVT::i8 || LocVT == MVT::i16) {
+ LocVT = MVT::i32;
+ if (ArgFlags.isSExt())
+ LocInfo = CCValAssign::SExt;
+ else if (ArgFlags.isZExt())
+ LocInfo = CCValAssign::ZExt;
+ else
+ LocInfo = CCValAssign::AExt;
+ }
+
+ if (ValVT == MVT::i32) {
+ Reg = State.AllocateReg(IntRegs, RegsSize);
+ LocVT = MVT::i32;
+ } else if (ValVT == MVT::f32) {
+ Reg = State.AllocateReg(FltRegs, RegsSize);
+ LocVT = MVT::f32;
+ }
+
+ if (!Reg) {
+ unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
+ unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes);
+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
+ } else {
+ unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
+ State.AllocateStack(SizeInBytes, SizeInBytes);
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ }
+
+ return false; // CC must always match
+}
+
//===----------------------------------------------------------------------===//
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
@@ -468,6 +534,9 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
+ // MBlaze does not yet support tail call optimization
+ isTailCall = false;
+
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
@@ -475,7 +544,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
- CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze);
+ CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@@ -487,7 +556,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
// First/LastArgStackLoc contains the first/last
// "at stack" argument location.
int LastArgStackLoc = 0;
- unsigned FirstStackArgLoc = 4;
+ unsigned FirstStackArgLoc = 0;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@@ -508,9 +577,6 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
case CCValAssign::AExt:
Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg);
break;
- case CCValAssign::BCvt:
- Arg = DAG.getNode(ISD::BIT_CONVERT, dl, RegVT, Arg);
- break;
}
// Arguments that can be passed on register must be kept at
@@ -617,7 +683,7 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv,
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
InVals.push_back(Chain.getValue(0));
- }
+ }
return Chain;
}
@@ -629,7 +695,6 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv,
/// LowerFormalArguments - transform physical registers into
/// virtual registers and generate load operations for
/// arguments places on the stack.
-/// TODO: isVarArg
SDValue MBlazeTargetLowering::
LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -640,16 +705,23 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
+ VarArgsFrameIndex = 0;
+
+ // Used with vargs to acumulate store chains.
+ std::vector<SDValue> OutChains;
+
+ // Keep track of the last register used for arguments
+ unsigned ArgRegEnd = 0;
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
- CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze);
+ CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2);
SDValue StackPtr;
- unsigned FirstStackArgLoc = 4;
+ unsigned FirstStackArgLoc = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
@@ -657,6 +729,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// Arguments stored on registers
if (VA.isRegLoc()) {
EVT RegVT = VA.getLocVT();
+ ArgRegEnd = VA.getLocReg();
TargetRegisterClass *RC = 0;
if (RegVT == MVT::i32)
@@ -668,12 +741,13 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// Transform the arguments stored on
// physical registers into virtual ones
- unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
+ unsigned Reg = MF.addLiveIn(ArgRegEnd, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
// to 32 bits. Insert an assert[sz]ext to capture this, then
- // truncate to the right size.
+ // truncate to the right size. If if is a floating point value
+ // then convert to the correct type.
if (VA.getLocInfo() != CCValAssign::Full) {
unsigned Opcode = 0;
if (VA.getLocInfo() == CCValAssign::SExt)
@@ -688,35 +762,14 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
InVals.push_back(ArgValue);
- // To meet ABI, when VARARGS are passed on registers, the registers
- // must have their values written to the caller stack frame.
- if (isVarArg) {
- if (StackPtr.getNode() == 0)
- StackPtr = DAG.getRegister(StackReg, getPointerTy());
-
- // The stack pointer offset is relative to the caller stack frame.
- // Since the real stack size is unknown here, a negative SPOffset
- // is used so there's a way to adjust these offsets when the stack
- // size get known (on EliminateFrameIndex). A dummy SPOffset is
- // used instead of a direct negative address (which is recorded to
- // be used on emitPrologue) to avoid mis-calc of the first stack
- // offset on PEI::calculateFrameObjectOffsets.
- // Arguments are always 32-bit.
- int FI = MFI->CreateFixedObject(4, 0, true, false);
- MBlazeFI->recordStoreVarArgsFI(FI, -(FirstStackArgLoc+(i*4)));
- SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
-
- // emit ISD::STORE whichs stores the
- // parameter value to a stack Location
- InVals.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0,
- false, false, 0));
- }
-
} else { // VA.isRegLoc()
// sanity check
assert(VA.isMemLoc());
+ // The last argument is not a register
+ ArgRegEnd = 0;
+
// The stack pointer offset is relative to the caller stack frame.
// Since the real stack size is unknown here, a negative SPOffset
// is used so there's a way to adjust these offsets when the stack
@@ -737,6 +790,47 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
}
}
+ // To meet ABI, when VARARGS are passed on registers, the registers
+ // must have their values written to the caller stack frame. If the last
+ // argument was placed in the stack, there's no need to save any register.
+ if ((isVarArg) && ArgRegEnd) {
+ if (StackPtr.getNode() == 0)
+ StackPtr = DAG.getRegister(StackReg, getPointerTy());
+
+ // The last register argument that must be saved is MBlaze::R10
+ TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass;
+
+ unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5);
+ unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1);
+ unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10);
+ unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin);
+
+ for (; Start <= End; ++Start, ++StackLoc) {
+ unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
+ unsigned LiveReg = MF.addLiveIn(Reg, RC);
+ SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);
+
+ int FI = MFI->CreateFixedObject(4, 0, true, false);
+ MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4)));
+ SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
+ OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0,
+ false, false, 0));
+
+ // Record the frame index of the first variable argument
+ // which is a value necessary to VASTART.
+ if (!VarArgsFrameIndex)
+ VarArgsFrameIndex = FI;
+ }
+ }
+
+ // All stores are grouped in one node to allow the matching between
+ // the size of Ins and InVals. This only happens when on varg functions
+ if (!OutChains.empty()) {
+ OutChains.push_back(Chain);
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ &OutChains[0], OutChains.size());
+ }
+
return Chain;
}
diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h
index 75d2552..f8b1470 100644
--- a/lib/Target/MBlaze/MBlazeISelLowering.h
+++ b/lib/Target/MBlaze/MBlazeISelLowering.h
@@ -63,6 +63,8 @@ namespace llvm {
//===--------------------------------------------------------------------===//
class MBlazeTargetLowering : public TargetLowering {
+ int VarArgsFrameIndex; // FrameIndex for start of varargs area.
+
public:
explicit MBlazeTargetLowering(MBlazeTargetMachine &TM);
@@ -96,6 +98,7 @@ namespace llvm {
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
index 9067f8b..6d528a2 100644
--- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
+++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
@@ -85,6 +85,47 @@ unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) {
return 0; // Not reached
}
+/// getRegisterFromNumbering - Given the enum value for some register, e.g.
+/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
+unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) {
+ switch (Reg) {
+ case 0 : return MBlaze::R0;
+ case 1 : return MBlaze::R1;
+ case 2 : return MBlaze::R2;
+ case 3 : return MBlaze::R3;
+ case 4 : return MBlaze::R4;
+ case 5 : return MBlaze::R5;
+ case 6 : return MBlaze::R6;
+ case 7 : return MBlaze::R7;
+ case 8 : return MBlaze::R8;
+ case 9 : return MBlaze::R9;
+ case 10 : return MBlaze::R10;
+ case 11 : return MBlaze::R11;
+ case 12 : return MBlaze::R12;
+ case 13 : return MBlaze::R13;
+ case 14 : return MBlaze::R14;
+ case 15 : return MBlaze::R15;
+ case 16 : return MBlaze::R16;
+ case 17 : return MBlaze::R17;
+ case 18 : return MBlaze::R18;
+ case 19 : return MBlaze::R19;
+ case 20 : return MBlaze::R20;
+ case 21 : return MBlaze::R21;
+ case 22 : return MBlaze::R22;
+ case 23 : return MBlaze::R23;
+ case 24 : return MBlaze::R24;
+ case 25 : return MBlaze::R25;
+ case 26 : return MBlaze::R26;
+ case 27 : return MBlaze::R27;
+ case 28 : return MBlaze::R28;
+ case 29 : return MBlaze::R29;
+ case 30 : return MBlaze::R30;
+ case 31 : return MBlaze::R31;
+ default: llvm_unreachable("Unknown register number!");
+ }
+ return 0; // Not reached
+}
+
unsigned MBlazeRegisterInfo::getPICCallReg() {
return MBlaze::R20;
}
@@ -180,9 +221,9 @@ void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const {
}
if (MFI->hasCalls()) {
+ MBlazeFI->setRAStackOffset(0);
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
- MBlazeFI->setRAStackOffset(StackOffset);
TopCPUSavedRegOff = StackOffset;
StackOffset += RegSize;
}
@@ -219,7 +260,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
// direct reference.
unsigned MBlazeRegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
- int *Value, RegScavenger *RS) const {
+ FrameIndexValue *Value, RegScavenger *RS) const {
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
@@ -245,7 +286,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
// as explained on LowerFormalArguments, detect negative offsets
// and adjust SPOffsets considering the final stack size.
- int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
+ int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4);
Offset += MI.getOperand(oi).getImm();
DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n");
@@ -272,6 +313,7 @@ emitPrologue(MachineFunction &MF) const {
// No need to allocate space on the stack.
if (StackSize == 0 && !MFI->hasCalls()) return;
+ if (StackSize < 28 && MFI->hasCalls()) StackSize = 28;
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@@ -307,9 +349,6 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
DebugLoc dl = MBBI->getDebugLoc();
- // Get the number of bytes from FrameInfo
- int NumBytes = (int) MFI->getStackSize();
-
// Get the FI's where RA and FP are saved.
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@@ -333,11 +372,15 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
.addImm(RAOffset).addReg(MBlaze::R1);
}
+ // Get the number of bytes from FrameInfo
+ int StackSize = (int) MFI->getStackSize();
+ if (StackSize < 28 && MFI->hasCalls()) StackSize = 28;
+
// adjust stack.
// addi R1, R1, imm
- if (NumBytes) {
+ if (StackSize) {
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1)
- .addReg(MBlaze::R1).addImm(NumBytes);
+ .addReg(MBlaze::R1).addImm(StackSize);
}
}
diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h
index 4847f1e..b618bf4 100644
--- a/lib/Target/MBlaze/MBlazeRegisterInfo.h
+++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h
@@ -43,6 +43,7 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// MBlaze::RA, return the number that it corresponds to (e.g. 31).
static unsigned getRegisterNumbering(unsigned RegEnum);
+ static unsigned getRegisterFromNumbering(unsigned RegEnum);
/// Get PIC indirect call register
static unsigned getPICCallReg();
@@ -66,7 +67,7 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
/// Stack Frame Processing Methods
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
@@ -82,6 +83,11 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
+ /// targetHandlesStackFrameRounding - Returns true if the target is
+ /// responsible for rounding up the stack frame (probably at emitPrologue
+ /// time).
+ bool targetHandlesStackFrameRounding() const { return true; }
+
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
};
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
index def5fc6..7a35eb0 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
@@ -98,12 +98,19 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
uint64_t Offset = MO.getOffset();
- O << (isMemOp ? '&' : '#');
+ // If the global address expression is a part of displacement field with a
+ // register base, we should not emit any prefix symbol here, e.g.
+ // mov.w &foo, r1
+ // vs
+ // mov.w glb(r1), r2
+ // Otherwise (!) msp430-as will silently miscompile the output :(
+ if (!Modifier || strcmp(Modifier, "nohash"))
+ O << (isMemOp ? '&' : '#');
if (Offset)
O << '(' << Offset << '+';
O << *GetGlobalValueSymbol(MO.getGlobal());
-
+
if (Offset)
O << ')';
@@ -124,15 +131,11 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
const MachineOperand &Disp = MI->getOperand(OpNum+1);
// Print displacement first
- if (!Disp.isImm()) {
- printOperand(MI, OpNum+1, "mem");
- } else {
- if (!Base.getReg())
- O << '&';
-
- printOperand(MI, OpNum+1, "nohash");
- }
+ // Imm here is in fact global address - print extra modifier.
+ if (Disp.isImm() && !Base.getReg())
+ O << '&';
+ printOperand(MI, OpNum+1, "nohash");
// Print register base field
if (Base.getReg()) {
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
index f6565bd..d7636e6 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
@@ -62,21 +62,26 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
const MCOperand &Disp = MI->getOperand(OpNo+1);
// Print displacement first
- if (Disp.isExpr()) {
- O << '&' << *Disp.getExpr();
- } else {
- assert(Disp.isImm() && "Expected immediate in displacement field");
- if (!Base.getReg())
- O << '&';
+ // If the global address expression is a part of displacement field with a
+ // register base, we should not emit any prefix symbol here, e.g.
+ // mov.w &foo, r1
+ // vs
+ // mov.w glb(r1), r2
+ // Otherwise (!) msp430-as will silently miscompile the output :(
+ if (!Base.getReg())
+ O << '&';
+
+ if (Disp.isExpr())
+ O << *Disp.getExpr();
+ else {
+ assert(Disp.isImm() && "Expected immediate in displacement field");
O << Disp.getImm();
}
-
// Print register base field
- if (Base.getReg()) {
+ if (Base.getReg())
O << '(' << getRegisterName(Base.getReg()) << ')';
- }
}
void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo) {
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
index 4eb7f3d..2e5ef8e 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
@@ -58,7 +58,7 @@ GetJumpTableSymbol(const MachineOperand &MO) const {
}
// Create a symbol for the name.
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Ctx.GetOrCreateTemporarySymbol(Name.str());
}
MCSymbol *MSP430MCInstLower::
@@ -74,7 +74,7 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
}
// Create a symbol for the name.
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Ctx.GetOrCreateTemporarySymbol(Name.str());
}
MCOperand MSP430MCInstLower::
diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp
index 566d902..daac683 100644
--- a/lib/Target/MSP430/MSP430RegisterInfo.cpp
+++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp
@@ -207,7 +207,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
diff --git a/lib/Target/MSP430/MSP430RegisterInfo.h b/lib/Target/MSP430/MSP430RegisterInfo.h
index aa08787..c8684df 100644
--- a/lib/Target/MSP430/MSP430RegisterInfo.h
+++ b/lib/Target/MSP430/MSP430RegisterInfo.h
@@ -50,7 +50,7 @@ public:
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void emitPrologue(MachineFunction &MF) const;
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index f923bed..f3c87bc 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -355,7 +355,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
// direct reference.
unsigned MipsRegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
- int *Value, RegScavenger *RS) const
+ FrameIndexValue *Value, RegScavenger *RS) const
{
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 6a3ec00..9fd044c 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -64,7 +64,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
/// Stack Frame Processing Methods
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp
index 877e4ff..da4e027 100644
--- a/lib/Target/PIC16/PIC16DebugInfo.cpp
+++ b/lib/Target/PIC16/PIC16DebugInfo.cpp
@@ -333,7 +333,7 @@ void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
for (DebugInfoFinder::iterator I = DbgFinder.type_begin(),
E = DbgFinder.type_end(); I != E; ++I) {
DICompositeType CTy(*I);
- if (CTy.isNull())
+ if (!CTy.Verify())
continue;
if (CTy.getTag() == dwarf::DW_TAG_union_type ||
CTy.getTag() == dwarf::DW_TAG_structure_type ) {
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp
index 8ba9a1d..30a1d4a 100644
--- a/lib/Target/PIC16/PIC16RegisterInfo.cpp
+++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp
@@ -53,7 +53,7 @@ bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
unsigned PIC16RegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
- int *Value, RegScavenger *RS) const
+ FrameIndexValue *Value, RegScavenger *RS) const
{
/* NOT YET IMPLEMENTED */
return 0;
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h
index 1d5dbbf..6a9a038 100644
--- a/lib/Target/PIC16/PIC16RegisterInfo.h
+++ b/lib/Target/PIC16/PIC16RegisterInfo.h
@@ -49,7 +49,7 @@ class PIC16RegisterInfo : public PIC16GenRegisterInfo {
virtual bool hasFP(const MachineFunction &MF) const;
virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS=NULL) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
index ac901d0..3c7dfaf 100644
--- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
@@ -309,8 +309,8 @@ namespace {
const MCSymbol *&TOCEntry = TOC[Sym];
if (TOCEntry == 0)
TOCEntry = OutContext.
- GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + "C" +
- Twine(LabelID++));
+ GetOrCreateTemporarySymbol(StringRef(MAI->getPrivateGlobalPrefix()) +
+ "C" + Twine(LabelID++));
O << *TOCEntry << "@toc";
}
@@ -672,14 +672,14 @@ static const MCSymbol *GetLazyPtr(const MCSymbol *Sym, MCContext &Ctx) {
// Remove $stub suffix, add $lazy_ptr.
SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5);
TmpStr += "$lazy_ptr";
- return Ctx.GetOrCreateSymbol(TmpStr.str());
+ return Ctx.GetOrCreateTemporarySymbol(TmpStr.str());
}
static const MCSymbol *GetAnonSym(const MCSymbol *Sym, MCContext &Ctx) {
// Add $tmp suffix to $stub, yielding $stub$tmp.
SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end());
TmpStr += "$tmp";
- return Ctx.GetOrCreateSymbol(TmpStr.str());
+ return Ctx.GetOrCreateTemporarySymbol(TmpStr.str());
}
void PPCDarwinAsmPrinter::
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 3d81afa..aeaa7c6 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3258,6 +3258,16 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee,
false, false, 0);
}
+ // On Darwin, R12 must contain the address of an indirect callee. This does
+ // not mean the MTCTR instruction must use R12; it's easier to model this as
+ // an extra parameter, so do that.
+ if (!isTailCall &&
+ !dyn_cast<GlobalAddressSDNode>(Callee) &&
+ !dyn_cast<ExternalSymbolSDNode>(Callee) &&
+ !isBLACompatibleAddress(Callee, DAG))
+ RegsToPass.push_back(std::make_pair((unsigned)(isPPC64 ? PPC::X12 :
+ PPC::R12), Callee));
+
// Build a sequence of copy-to-reg nodes chained together with token chain
// and flag operands which copy the outgoing args into the appropriate regs.
SDValue InFlag;
diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td
index 3f4d329..3ff8f27 100644
--- a/lib/Target/PowerPC/PPCInstrAltivec.td
+++ b/lib/Target/PowerPC/PPCInstrAltivec.td
@@ -35,33 +35,33 @@ def vpkuwum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
def vmrglb_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 1, false);
}]>;
def vmrglh_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 2, false);
}]>;
def vmrglw_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 4, false);
}]>;
def vmrghb_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 1, false);
}]>;
def vmrghh_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 2, false);
}]>;
def vmrghw_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 4, false);
}]>;
def vmrglb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
+ (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{
return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 1, true);
}]>;
def vmrglh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 0b509ac..31bca16 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -713,7 +713,7 @@ void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II,
unsigned
PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h
index 3aeed80..43cf535 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -67,7 +67,7 @@ public:
void lowerCRSpilling(MachineBasicBlock::iterator II, unsigned FrameIndex,
int SPAdj, RegScavenger *RS) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
/// determineFrameLayout - Determine the size of the frame and maximum call
diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp
index 6f6183e..740e3bc 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -78,7 +78,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h
index 8889ea6..24d43e3 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.h
+++ b/lib/Target/Sparc/SparcRegisterInfo.h
@@ -44,7 +44,7 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index a44f6d9..a75b85d 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -1112,7 +1112,8 @@ def : Pat<(SystemZcall (i64 texternalsym:$dst)), (CALLi texternalsym:$dst)>;
// Arbitrary immediate support.
def : Pat<(i32 imm:$src),
- (EXTRACT_SUBREG (MOV64ri32 (i64 imm:$src)), subreg_32bit)>;
+ (EXTRACT_SUBREG (MOV64ri32 (GetI64FromI32 (i32 imm:$src))),
+ subreg_32bit)>;
// Implement in terms of LLIHF/OILF.
def : Pat<(i64 imm:$imm),
diff --git a/lib/Target/SystemZ/SystemZOperands.td b/lib/Target/SystemZ/SystemZOperands.td
index 156cace..0de50fd 100644
--- a/lib/Target/SystemZ/SystemZOperands.td
+++ b/lib/Target/SystemZ/SystemZOperands.td
@@ -67,6 +67,10 @@ def HI32 : SDNodeXForm<imm, [{
return getI32Imm(N->getZExtValue() >> 32);
}]>;
+def GetI64FromI32 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i64);
+}]>;
+
def i32ll16 : PatLeaf<(i32 imm), [{
// i32ll16 predicate - true if the 32-bit immediate has only rightmost 16
// bits set.
diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index fe50c90..ca2fe6f 100644
--- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -110,7 +110,7 @@ int SystemZRegisterInfo::getFrameIndexOffset(const MachineFunction &MF,
unsigned
SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unxpected");
diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h
index fabd4e8..99e396a 100644
--- a/lib/Target/SystemZ/SystemZRegisterInfo.h
+++ b/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -56,7 +56,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index 82619c7..8c12039 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -56,6 +56,10 @@ TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) {
DwarfARangesSection = 0;
DwarfRangesSection = 0;
DwarfMacroInfoSection = 0;
+
+ IsFunctionEHSymbolGlobal = false;
+ IsFunctionEHFrameSymbolPrivate = true;
+ SupportsWeakOmittedEHFrame = true;
}
TargetLoweringObjectFile::~TargetLoweringObjectFile() {
@@ -295,7 +299,12 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
// FIXME: Use GetGlobalValueSymbol.
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, false);
- const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());
+ const MCSymbol *Sym;
+
+ if (GV->hasPrivateLinkage())
+ Sym = getContext().GetOrCreateTemporarySymbol(Name.str());
+ else
+ Sym = getContext().GetOrCreateSymbol(Name.str());
return getSymbolForDwarfReference(Sym, MMI, Encoding);
}
diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
index 8cab24c..caf84b6 100644
--- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
@@ -26,6 +26,7 @@
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/Assembly/Writer.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionMachO.h"
@@ -36,7 +37,6 @@
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
@@ -56,7 +56,11 @@ void X86AsmPrinter::PrintPICBaseSymbol() const {
MCSymbol *X86AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const {
SmallString<60> NameStr;
Mang->getNameWithPrefix(NameStr, GV, false);
- MCSymbol *Symb = OutContext.GetOrCreateSymbol(NameStr.str());
+ MCSymbol *Symb;
+ if (GV->hasPrivateLinkage())
+ Symb = OutContext.GetOrCreateTemporarySymbol(NameStr.str());
+ else
+ Symb = OutContext.GetOrCreateSymbol(NameStr.str());
if (Subtarget->isTargetCygMing()) {
X86COFFMachineModuleInfo &COFFMMI =
diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
index fa8d13d..b8a6eeb 100644
--- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
+++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
@@ -89,7 +89,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const {
case X86II::MO_DARWIN_NONLAZY:
case X86II::MO_DARWIN_NONLAZY_PIC_BASE: {
Name += "$non_lazy_ptr";
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
+ MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str());
MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym);
if (StubSym == 0) {
@@ -100,7 +100,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const {
}
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
Name += "$non_lazy_ptr";
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
+ MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str());
MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym);
if (StubSym == 0) {
assert(MO.isGlobal() && "Extern symbol not handled yet");
@@ -110,7 +110,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const {
}
case X86II::MO_DARWIN_STUB: {
Name += "$stub";
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
+ MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str());
MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
if (StubSym)
return Sym;
@@ -119,7 +119,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const {
StubSym = AsmPrinter.GetGlobalValueSymbol(MO.getGlobal());
} else {
Name.erase(Name.end()-5, Name.end());
- StubSym = Ctx.GetOrCreateSymbol(Name.str());
+ StubSym = Ctx.GetOrCreateTemporarySymbol(Name.str());
}
return Sym;
}
@@ -394,7 +394,8 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
// However, we can't generate a ".", so just emit a new label here and refer
// to it. We know that this operand flag occurs at most once per function.
const char *Prefix = MAI->getPrivateGlobalPrefix();
- MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Twine(Prefix)+"picbaseref"+
+ MCSymbol *DotSym = OutContext.GetOrCreateTemporarySymbol(Twine(Prefix)+
+ "picbaseref" +
Twine(getFunctionNumber()));
OutStreamer.EmitLabel(DotSym);
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 8384ab7..0cfcbb6 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1105,8 +1105,8 @@ MCSymbol *
X86TargetLowering::getPICBaseSymbol(const MachineFunction *MF,
MCContext &Ctx) const {
const MCAsmInfo &MAI = *getTargetMachine().getMCAsmInfo();
- return Ctx.GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix())+
- Twine(MF->getFunctionNumber())+"$pb");
+ return Ctx.GetOrCreateTemporarySymbol(Twine(MAI.getPrivateGlobalPrefix())+
+ Twine(MF->getFunctionNumber())+"$pb");
}
@@ -6418,24 +6418,13 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
EVT IntPtr = getPointerTy();
EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32;
- Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true));
-
Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Size, Flag);
Flag = Chain.getValue(1);
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- SDValue Ops[] = { Chain,
- DAG.getTargetExternalSymbol("_alloca", IntPtr),
- DAG.getRegister(X86::EAX, IntPtr),
- DAG.getRegister(X86StackPtr, SPTy),
- Flag };
- Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops, 5);
- Flag = Chain.getValue(1);
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- Chain = DAG.getCALLSEQ_END(Chain,
- DAG.getIntPtrConstant(0, true),
- DAG.getIntPtrConstant(0, true),
- Flag);
+ Chain = DAG.getNode(X86ISD::MINGW_ALLOCA, dl, NodeTys, Chain, Flag);
+ Flag = Chain.getValue(1);
Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1);
@@ -7741,6 +7730,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM";
case X86ISD::PTEST: return "X86ISD::PTEST";
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
+ case X86ISD::MINGW_ALLOCA: return "X86ISD::MINGW_ALLOCA";
}
}
@@ -8410,6 +8400,29 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr *MI,
return BB;
}
+MachineBasicBlock *
+X86TargetLowering::EmitLoweredMingwAlloca(MachineInstr *MI,
+ MachineBasicBlock *BB,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
+ const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+ DebugLoc DL = MI->getDebugLoc();
+ MachineFunction *F = BB->getParent();
+
+ // The lowering is pretty easy: we're just emitting the call to _alloca. The
+ // non-trivial part is impdef of ESP.
+ // FIXME: The code should be tweaked as soon as we'll try to do codegen for
+ // mingw-w64.
+
+ BuildMI(BB, DL, TII->get(X86::CALLpcrel32))
+ .addExternalSymbol("_alloca")
+ .addReg(X86::EAX, RegState::Implicit)
+ .addReg(X86::ESP, RegState::Implicit)
+ .addReg(X86::EAX, RegState::Define | RegState::Implicit)
+ .addReg(X86::ESP, RegState::Define | RegState::Implicit);
+
+ F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
+ return BB;
+}
MachineBasicBlock *
X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
@@ -8417,6 +8430,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
switch (MI->getOpcode()) {
default: assert(false && "Unexpected instr type to insert");
+ case X86::MINGW_ALLOCA:
+ return EmitLoweredMingwAlloca(MI, BB, EM);
case X86::CMOV_GR8:
case X86::CMOV_V1I64:
case X86::CMOV_FR32:
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index ffaf1cf..4c12fcc 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -249,6 +249,9 @@ namespace llvm {
// with control flow.
VASTART_SAVE_XMM_REGS,
+ // MINGW_ALLOCA - MingW's __alloca call to do stack probing.
+ MINGW_ALLOCA,
+
// ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG,
// ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG -
// Atomic 64-bit binary operations.
@@ -259,6 +262,10 @@ namespace llvm {
ATOMAND64_DAG,
ATOMNAND64_DAG,
ATOMSWAP64_DAG
+
+ // WARNING: Do not add anything in the end unless you want the node to
+ // have memop! In fact, starting from ATOMADD64_DAG all opcodes will be
+ // thought as target memory ops!
};
}
@@ -789,7 +796,11 @@ namespace llvm {
MachineBasicBlock *EmitLoweredSelect(MachineInstr *I,
MachineBasicBlock *BB,
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
-
+
+ MachineBasicBlock *EmitLoweredMingwAlloca(MachineInstr *MI,
+ MachineBasicBlock *BB,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
+
/// Emit nodes that will be selected as "test Op0,Op0", or something
/// equivalent, for use with the given x86 condition code.
SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG);
diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td
index 8462255..8e684c9 100644
--- a/lib/Target/X86/X86Instr64bit.td
+++ b/lib/Target/X86/X86Instr64bit.td
@@ -2473,7 +2473,7 @@ let isTwoAddress = 1 in {
defm PINSRQ : SS41I_insert64<0x22, "pinsrq">;
// -disable-16bit support.
-def : Pat<(truncstorei16 (i64 imm:$src), addr:$dst),
+def : Pat<(truncstorei16 (i16 imm:$src), addr:$dst),
(MOV16mi addr:$dst, imm:$src)>;
def : Pat<(truncstorei16 GR64:$src, addr:$dst),
(MOV16mr addr:$dst, (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit))>;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 39bda04..4fd91bb 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -2525,6 +2525,11 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
// Folding a V_SET0 or V_SETALLONES as a load, to ease register pressure.
// Create a constant-pool entry and operands to load from it.
+ // Medium and large mode can't fold loads this way.
+ if (TM.getCodeModel() != CodeModel::Small &&
+ TM.getCodeModel() != CodeModel::Kernel)
+ return NULL;
+
// x86-32 PIC requires a PIC base register for constant pools.
unsigned PICBase = 0;
if (TM.getRelocationModel() == Reloc::PIC_) {
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index d46b946..071c5aa 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -65,7 +65,7 @@ def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>,
def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>;
-def SDTX86RdTsc : SDTypeProfile<0, 0, []>;
+def SDTX86Void : SDTypeProfile<0, 0, []>;
def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
@@ -143,7 +143,7 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr,
[SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore,
SDNPMayLoad]>;
-def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
+def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void,
[SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>;
def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>;
@@ -178,6 +178,9 @@ def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags,
def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;
+def X86MingwAlloca : SDNode<"X86ISD::MINGW_ALLOCA", SDTX86Void,
+ [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
@@ -519,7 +522,7 @@ def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
}
// x86-64 va_start lowering magic.
-let usesCustomInserter = 1 in
+let usesCustomInserter = 1 in {
def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
(outs),
(ins GR8:$al,
@@ -530,6 +533,19 @@ def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
imm:$regsavefi,
imm:$offset)]>;
+// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls
+// to _alloca is needed to probe the stack when allocating more than 4k bytes in
+// one go. Touching the stack at 4K increments is necessary to ensure that the
+// guard pages used by the OS virtual memory manager are allocated in correct
+// sequence.
+// The main point of having separate instruction are extra unmodelled effects
+// (compared to ordinary calls) like stack pointer change.
+
+def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins),
+ "# dynamic stack allocation",
+ [(X86MingwAlloca)]>;
+}
+
// Nop
let neverHasSideEffects = 1 in {
def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>;
@@ -2631,6 +2647,17 @@ def ADD32rr : I<0x01, MRMDestReg, (outs GR32:$dst),
} // end isConvertibleToThreeAddress
} // end isCommutable
+// These are alternate spellings for use by the disassembler, we mark them as
+// code gen only to ensure they aren't matched by the assembler.
+let isCodeGenOnly = 1 in {
+ def ADD8rr_alt: I<0x02, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "add{b}\t{$src2, $dst|$dst, $src2}", []>;
+ def ADD16rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2),
+ "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize;
+ def ADD32rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2),
+ "add{l}\t{$src2, $dst|$dst, $src2}", []>;
+}
+
// Register-Memory Addition
def ADD8rm : I<0x02, MRMSrcMem, (outs GR8 :$dst),
(ins GR8 :$src1, i8mem :$src2),
@@ -2648,15 +2675,6 @@ def ADD32rm : I<0x03, MRMSrcMem, (outs GR32:$dst),
[(set GR32:$dst, (add GR32:$src1, (load addr:$src2))),
(implicit EFLAGS)]>;
-// Register-Register Addition - Equivalent to the normal rr forms (ADD8rr,
-// ADD16rr, and ADD32rr), but differently encoded.
-def ADD8mrmrr: I<0x02, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "add{b}\t{$src2, $dst|$dst, $src2}", []>;
-def ADD16mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2),
- "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize;
-def ADD32mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2),
- "add{l}\t{$src2, $dst|$dst, $src2}", []>;
-
// Register-Integer Addition
def ADD8ri : Ii8<0x80, MRM0r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
"add{b}\t{$src2, $dst|$dst, $src2}",
@@ -3119,16 +3137,16 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8
//
let Defs = [EFLAGS] in {
let isCommutable = 1 in { // TEST X, Y --> TEST Y, X
-def TEST8rr : I<0x84, MRMDestReg, (outs), (ins GR8:$src1, GR8:$src2),
+def TEST8rr : I<0x84, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2),
"test{b}\t{$src2, $src1|$src1, $src2}",
[(X86cmp (and_su GR8:$src1, GR8:$src2), 0),
(implicit EFLAGS)]>;
-def TEST16rr : I<0x85, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2),
+def TEST16rr : I<0x85, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2),
"test{w}\t{$src2, $src1|$src1, $src2}",
[(X86cmp (and_su GR16:$src1, GR16:$src2), 0),
(implicit EFLAGS)]>,
OpSize;
-def TEST32rr : I<0x85, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2),
+def TEST32rr : I<0x85, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2),
"test{l}\t{$src2, $src1|$src1, $src2}",
[(X86cmp (and_su GR32:$src1, GR32:$src2), 0),
(implicit EFLAGS)]>;
@@ -3437,12 +3455,18 @@ def CMP32rm : I<0x3B, MRMSrcMem,
"cmp{l}\t{$src2, $src1|$src1, $src2}",
[(X86cmp GR32:$src1, (loadi32 addr:$src2)),
(implicit EFLAGS)]>;
-def CMP8mrmrr : I<0x3A, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2),
- "cmp{b}\t{$src2, $src1|$src1, $src2}", []>;
-def CMP16mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2),
- "cmp{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize;
-def CMP32mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2),
- "cmp{l}\t{$src2, $src1|$src1, $src2}", []>;
+
+// These are alternate spellings for use by the disassembler, we mark them as
+// code gen only to ensure they aren't matched by the assembler.
+let isCodeGenOnly = 1 in {
+ def CMP8rr_alt : I<0x3A, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2),
+ "cmp{b}\t{$src2, $src1|$src1, $src2}", []>;
+ def CMP16rr_alt : I<0x3B, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2),
+ "cmp{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize;
+ def CMP32rr_alt : I<0x3B, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2),
+ "cmp{l}\t{$src2, $src1|$src1, $src2}", []>;
+}
+
def CMP8ri : Ii8<0x80, MRM7r,
(outs), (ins GR8:$src1, i8imm:$src2),
"cmp{b}\t{$src2, $src1|$src1, $src2}",
@@ -4236,7 +4260,7 @@ def VMWRITE32rr : I<0x79, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
// 0F 01 C4
def VMXOFF : I<0x01, MRM_C4, (outs), (ins), "vmxoff", []>, TB;
def VMXON : I<0xC7, MRM6m, (outs), (ins i64mem:$vmxon),
- "vmxon\t{$vmxon}", []>, XD;
+ "vmxon\t{$vmxon}", []>, XS;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
@@ -5134,7 +5158,7 @@ def : Pat<(parallel (store (X86and_flag (loadi32 addr:$dst), i32immSExt8:$src2),
(AND32mi8 addr:$dst, i32immSExt8:$src2)>;
// -disable-16bit support.
-def : Pat<(truncstorei16 (i32 imm:$src), addr:$dst),
+def : Pat<(truncstorei16 (i16 imm:$src), addr:$dst),
(MOV16mi addr:$dst, imm:$src)>;
def : Pat<(truncstorei16 GR32:$src, addr:$dst),
(MOV16mr addr:$dst, (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit))>;
diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td
index c8e0723..eea0eb8 100644
--- a/lib/Target/X86/X86InstrMMX.td
+++ b/lib/Target/X86/X86InstrMMX.td
@@ -160,7 +160,8 @@ def MMX_MOVQ2DQrr : SSDIi8<0xD6, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src),
"movq2dq\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
(movl immAllZerosV,
- (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src))))))]>;
+ (v2i64 (scalar_to_vector
+ (i64 (bitconvert (v1i64 VR64:$src)))))))]>;
let neverHasSideEffects = 1 in
def MMX_MOVQ2FR64rr: SSDIi8<0xD6, MRMSrcReg, (outs FR64:$dst), (ins VR64:$src),
@@ -271,9 +272,9 @@ defm MMX_PSRAD : MMXI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad",
// Shift up / down and insert zero's.
def : Pat<(v1i64 (X86vshl VR64:$src, (i8 imm:$amt))),
- (v1i64 (MMX_PSLLQri VR64:$src, imm:$amt))>;
+ (MMX_PSLLQri VR64:$src, imm:$amt)>;
def : Pat<(v1i64 (X86vshr VR64:$src, (i8 imm:$amt))),
- (v1i64 (MMX_PSRLQri VR64:$src, imm:$amt))>;
+ (MMX_PSRLQri VR64:$src, imm:$amt)>;
// Comparison Instructions
defm MMX_PCMPEQB : MMXI_binop_rm_int<0x74, "pcmpeqb", int_x86_mmx_pcmpeq_b>;
@@ -577,7 +578,7 @@ let AddedComplexity = 20 in {
// Clear top half.
let AddedComplexity = 15 in {
def : Pat<(v2i32 (X86vzmovl VR64:$src)),
- (MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>;
+ (MMX_PUNPCKLDQrr VR64:$src, (v2i32 (MMX_V_SET0)))>;
}
// Patterns to perform canonical versions of vector shuffling.
diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td
index 2743dba..bd6e1b8 100644
--- a/lib/Target/X86/X86InstrSSE.td
+++ b/lib/Target/X86/X86InstrSSE.td
@@ -385,7 +385,7 @@ def MOVSSrr : SSI<0x10, MRMSrcReg,
// Extract the low 32-bit value from one vector and insert it into another.
let AddedComplexity = 15 in
def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)),
- (MOVSSrr VR128:$src1,
+ (MOVSSrr (v4f32 VR128:$src1),
(EXTRACT_SUBREG (v4f32 VR128:$src2), x86_subreg_ss))>;
// Implicitly promote a 32-bit scalar to a vector.
@@ -827,7 +827,7 @@ let Constraints = "$src1 = $dst" in {
def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
- (MOVHPSrm VR128:$src1, addr:$src2)>;
+ (MOVHPSrm (v4i32 VR128:$src1), addr:$src2)>;
def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
"movlps\t{$src, $dst|$dst, $src}",
@@ -860,9 +860,9 @@ def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst),
let AddedComplexity = 20 in {
def : Pat<(v4f32 (movddup VR128:$src, (undef))),
- (MOVLHPSrr VR128:$src, VR128:$src)>;
+ (MOVLHPSrr (v4f32 VR128:$src), (v4f32 VR128:$src))>;
def : Pat<(v2i64 (movddup VR128:$src, (undef))),
- (MOVLHPSrr VR128:$src, VR128:$src)>;
+ (MOVLHPSrr (v2i64 VR128:$src), (v2i64 VR128:$src))>;
}
@@ -1011,9 +1011,9 @@ let Constraints = "$src1 = $dst" in {
(memop addr:$src), imm:$cc))]>;
}
def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)),
- (CMPPSrri VR128:$src1, VR128:$src2, imm:$cc)>;
+ (CMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>;
def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)),
- (CMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>;
+ (CMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>;
// Shuffle and unpack instructions
let Constraints = "$src1 = $dst" in {
@@ -1090,9 +1090,6 @@ def MOVNTDQ_64mr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
"movntdq\t{$src, $dst|$dst, $src}",
[(alignednontemporalstore (v2f64 VR128:$src), addr:$dst)]>;
-def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst),
- (MOVNTDQ_64mr VR128:$src, addr:$dst)>;
-
def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src),
"movnti\t{$src, $dst|$dst, $src}",
[(nontemporalstore (i32 GR32:$src), addr:$dst)]>,
@@ -1150,7 +1147,7 @@ def MOVSDrr : SDI<0x10, MRMSrcReg,
// Extract the low 64-bit value from one vector and insert it into another.
let AddedComplexity = 15 in
def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1,
+ (MOVSDrr (v2f64 VR128:$src1),
(EXTRACT_SUBREG (v2f64 VR128:$src2), x86_subreg_sd))>;
// Implicitly promote a 64-bit scalar to a vector.
@@ -2394,9 +2391,6 @@ def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
"movntdq\t{$src, $dst|$dst, $src}",
[(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>;
-
-def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst),
- (MOVNTDQmr VR128:$src, addr:$dst)>;
}
// Flush cache
diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp
index 250634f..9498810 100644
--- a/lib/Target/X86/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/X86MCAsmInfo.cpp
@@ -68,7 +68,6 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) {
// Exceptions handling
ExceptionsType = ExceptionHandling::Dwarf;
- AbsoluteEHSectionOffsets = false;
}
X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) {
@@ -90,7 +89,6 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) {
// Exceptions handling
ExceptionsType = ExceptionHandling::Dwarf;
- AbsoluteEHSectionOffsets = false;
}
MCSection *X86ELFMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const {
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index 946d6b2..cdb579c 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -589,7 +589,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const{
assert(SPAdj == 0 && "Unexpected");
@@ -1057,7 +1057,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
.addImm(NumBytes);
BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
- .addExternalSymbol("_alloca");
+ .addExternalSymbol("_alloca")
+ .addReg(StackPtr, RegState::Define | RegState::Implicit);
} else {
// Save EAX
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
@@ -1068,7 +1069,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
.addImm(NumBytes - 4);
BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
- .addExternalSymbol("_alloca");
+ .addExternalSymbol("_alloca")
+ .addReg(StackPtr, RegState::Define | RegState::Implicit);
// Restore EAX
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h
index e4bdb4e..12b2f3e 100644
--- a/lib/Target/X86/X86RegisterInfo.h
+++ b/lib/Target/X86/X86RegisterInfo.h
@@ -143,7 +143,7 @@ public:
MachineBasicBlock::iterator MI) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp
index 29a0be5..c80ae19 100644
--- a/lib/Target/X86/X86TargetObjectFile.cpp
+++ b/lib/Target/X86/X86TargetObjectFile.cpp
@@ -20,14 +20,19 @@ using namespace dwarf;
const MCExpr *X8664_MachoTargetObjectFile::
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
- MachineModuleInfo *MMI, unsigned Encoding) const {
+ MachineModuleInfo *MMI,
+ unsigned Encoding) const {
// On Darwin/X86-64, we can reference dwarf symbols with foo@GOTPCREL+4, which
// is an indirect pc-relative reference.
if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) {
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, false);
- const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+ const MCSymbol *Sym;
+ if (GV->hasPrivateLinkage())
+ Sym = getContext().GetOrCreateTemporarySymbol(Name);
+ else
+ Sym = getContext().GetOrCreateSymbol(Name);
const MCExpr *Res =
X86MCTargetExpr::Create(Sym, X86MCTargetExpr::GOTPCREL, getContext());
const MCExpr *Four = MCConstantExpr::Create(4, getContext());
diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp
index b1ab132..29a6ab7 100644
--- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp
+++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp
@@ -208,6 +208,24 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
Ops, 3);
}
+ case XCoreISD::MACCU: {
+ SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+ N->getOperand(2), N->getOperand(3) };
+ return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
+ Ops, 4);
+ }
+ case XCoreISD::MACCS: {
+ SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+ N->getOperand(2), N->getOperand(3) };
+ return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
+ Ops, 4);
+ }
+ case XCoreISD::LMUL: {
+ SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+ N->getOperand(2), N->getOperand(3) };
+ return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
+ Ops, 4);
+ }
// Other cases are autogenerated.
}
}
diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp
index e6515d8..8249219 100644
--- a/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/lib/Target/XCore/XCoreISelLowering.cpp
@@ -54,9 +54,12 @@ getTargetNodeName(unsigned Opcode) const
case XCoreISD::RETSP : return "XCoreISD::RETSP";
case XCoreISD::LADD : return "XCoreISD::LADD";
case XCoreISD::LSUB : return "XCoreISD::LSUB";
+ case XCoreISD::LMUL : return "XCoreISD::LMUL";
+ case XCoreISD::MACCU : return "XCoreISD::MACCU";
+ case XCoreISD::MACCS : return "XCoreISD::MACCS";
case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
- default : return NULL;
+ default : return NULL;
}
}
@@ -96,6 +99,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// 64bit
setOperationAction(ISD::ADD, MVT::i64, Custom);
setOperationAction(ISD::SUB, MVT::i64, Custom);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
setOperationAction(ISD::MULHS, MVT::i32, Expand);
setOperationAction(ISD::MULHU, MVT::i32, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
@@ -149,6 +154,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// We have target-specific dag combine patterns for the following nodes:
setTargetDAGCombine(ISD::STORE);
+ setTargetDAGCombine(ISD::ADD);
}
SDValue XCoreTargetLowering::
@@ -165,6 +171,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
case ISD::VAARG: return LowerVAARG(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG);
+ case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG);
+ case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG);
// FIXME: Remove these when LegalizeDAGTypes lands.
case ISD::ADD:
case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
@@ -542,11 +550,171 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG)
}
SDValue XCoreTargetLowering::
+LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG)
+{
+ assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&
+ "Unexpected operand to lower!");
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ SDValue Zero = DAG.getConstant(0, MVT::i32);
+ SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,
+ LHS, RHS);
+ SDValue Lo(Hi.getNode(), 1);
+ SDValue Ops[] = { Lo, Hi };
+ return DAG.getMergeValues(Ops, 2, dl);
+}
+
+SDValue XCoreTargetLowering::
+LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG)
+{
+ assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&
+ "Unexpected operand to lower!");
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ SDValue Zero = DAG.getConstant(0, MVT::i32);
+ SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,
+ Zero, Zero);
+ SDValue Lo(Hi.getNode(), 1);
+ SDValue Ops[] = { Lo, Hi };
+ return DAG.getMergeValues(Ops, 2, dl);
+}
+
+/// isADDADDMUL - Return whether Op is in a form that is equivalent to
+/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then
+/// each intermediate result in the calculation must also have a single use.
+/// If the Op is in the correct form the constituent parts are written to Mul0,
+/// Mul1, Addend0 and Addend1.
+static bool
+isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,
+ SDValue &Addend1, bool requireIntermediatesHaveOneUse)
+{
+ if (Op.getOpcode() != ISD::ADD)
+ return false;
+ SDValue N0 = Op.getOperand(0);
+ SDValue N1 = Op.getOperand(1);
+ SDValue AddOp;
+ SDValue OtherOp;
+ if (N0.getOpcode() == ISD::ADD) {
+ AddOp = N0;
+ OtherOp = N1;
+ } else if (N1.getOpcode() == ISD::ADD) {
+ AddOp = N1;
+ OtherOp = N0;
+ } else {
+ return false;
+ }
+ if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())
+ return false;
+ if (OtherOp.getOpcode() == ISD::MUL) {
+ // add(add(a,b),mul(x,y))
+ if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())
+ return false;
+ Mul0 = OtherOp.getOperand(0);
+ Mul1 = OtherOp.getOperand(1);
+ Addend0 = AddOp.getOperand(0);
+ Addend1 = AddOp.getOperand(1);
+ return true;
+ }
+ if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
+ // add(add(mul(x,y),a),b)
+ if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())
+ return false;
+ Mul0 = AddOp.getOperand(0).getOperand(0);
+ Mul1 = AddOp.getOperand(0).getOperand(1);
+ Addend0 = AddOp.getOperand(1);
+ Addend1 = OtherOp;
+ return true;
+ }
+ if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
+ // add(add(a,mul(x,y)),b)
+ if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())
+ return false;
+ Mul0 = AddOp.getOperand(1).getOperand(0);
+ Mul1 = AddOp.getOperand(1).getOperand(1);
+ Addend0 = AddOp.getOperand(0);
+ Addend1 = OtherOp;
+ return true;
+ }
+ return false;
+}
+
+SDValue XCoreTargetLowering::
+TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG)
+{
+ SDValue Mul;
+ SDValue Other;
+ if (N->getOperand(0).getOpcode() == ISD::MUL) {
+ Mul = N->getOperand(0);
+ Other = N->getOperand(1);
+ } else if (N->getOperand(1).getOpcode() == ISD::MUL) {
+ Mul = N->getOperand(1);
+ Other = N->getOperand(0);
+ } else {
+ return SDValue();
+ }
+ DebugLoc dl = N->getDebugLoc();
+ SDValue LL, RL, AddendL, AddendH;
+ LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Mul.getOperand(0), DAG.getConstant(0, MVT::i32));
+ RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Mul.getOperand(1), DAG.getConstant(0, MVT::i32));
+ AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Other, DAG.getConstant(0, MVT::i32));
+ AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Other, DAG.getConstant(1, MVT::i32));
+ APInt HighMask = APInt::getHighBitsSet(64, 32);
+ unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
+ unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
+ if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
+ DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
+ // The inputs are both zero-extended.
+ SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), AddendH,
+ AddendL, LL, RL);
+ SDValue Lo(Hi.getNode(), 1);
+ return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
+ }
+ if (LHSSB > 32 && RHSSB > 32) {
+ // The inputs are both sign-extended.
+ SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), AddendH,
+ AddendL, LL, RL);
+ SDValue Lo(Hi.getNode(), 1);
+ return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
+ }
+ SDValue LH, RH;
+ LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Mul.getOperand(0), DAG.getConstant(1, MVT::i32));
+ RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Mul.getOperand(1), DAG.getConstant(1, MVT::i32));
+ SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), AddendH,
+ AddendL, LL, RL);
+ SDValue Lo(Hi.getNode(), 1);
+ RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
+ LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
+ Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
+ Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
+ return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
+}
+
+SDValue XCoreTargetLowering::
ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
{
assert(N->getValueType(0) == MVT::i64 &&
(N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
"Unknown operand to lower!");
+
+ if (N->getOpcode() == ISD::ADD) {
+ SDValue Result = TryExpandADDWithMul(N, DAG);
+ if (Result.getNode() != 0)
+ return Result;
+ }
+
DebugLoc dl = N->getDebugLoc();
// Extract components
@@ -1097,6 +1265,97 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
DebugLoc dl = N->getDebugLoc();
switch (N->getOpcode()) {
default: break;
+ case XCoreISD::LADD: {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ SDValue N2 = N->getOperand(2);
+ ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
+ ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
+ EVT VT = N0.getValueType();
+
+ // canonicalize constant to RHS
+ if (N0C && !N1C)
+ return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);
+
+ // fold (ladd 0, 0, x) -> 0, x & 1
+ if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
+ SDValue Carry = DAG.getConstant(0, VT);
+ SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
+ DAG.getConstant(1, VT));
+ SDValue Ops [] = { Carry, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+
+ // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
+ // low bit set
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
+ VT.getSizeInBits() - 1);
+ DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
+ if (KnownZero == Mask) {
+ SDValue Carry = DAG.getConstant(0, VT);
+ SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
+ SDValue Ops [] = { Carry, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+ }
+ }
+ break;
+ case XCoreISD::LSUB: {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ SDValue N2 = N->getOperand(2);
+ ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
+ ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
+ EVT VT = N0.getValueType();
+
+ // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
+ if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
+ VT.getSizeInBits() - 1);
+ DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
+ if (KnownZero == Mask) {
+ SDValue Borrow = N2;
+ SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
+ DAG.getConstant(0, VT), N2);
+ SDValue Ops [] = { Borrow, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+ }
+
+ // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
+ // low bit set
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
+ VT.getSizeInBits() - 1);
+ DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
+ if (KnownZero == Mask) {
+ SDValue Borrow = DAG.getConstant(0, VT);
+ SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
+ SDValue Ops [] = { Borrow, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+ }
+ }
+ break;
+ case ISD::ADD: {
+ // Fold expressions such as add(add(mul(x,y),a),b) -> lmul(x, y, a, b).
+ // This is only profitable if the intermediate results are unused
+ // elsewhere.
+ SDValue Mul0, Mul1, Addend0, Addend1;
+ if (isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {
+ SDValue Zero = DAG.getConstant(0, MVT::i32);
+ SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
+ DAG.getVTList(MVT::i32, MVT::i32), Mul0,
+ Mul1, Addend0, Addend1);
+ SDValue Result(Ignored.getNode(), 1);
+ return Result;
+ }
+ }
+ break;
case ISD::STORE: {
// Replace unaligned store of unaligned load with memmove.
StoreSDNode *ST = cast<StoreSDNode>(N);
@@ -1137,6 +1396,27 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
return SDValue();
}
+void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
+ const APInt &Mask,
+ APInt &KnownZero,
+ APInt &KnownOne,
+ const SelectionDAG &DAG,
+ unsigned Depth) const {
+ KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
+ switch (Op.getOpcode()) {
+ default: break;
+ case XCoreISD::LADD:
+ case XCoreISD::LSUB:
+ if (Op.getResNo() == 0) {
+ // Top bits of carry / borrow are clear.
+ KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(),
+ Mask.getBitWidth() - 1);
+ KnownZero &= Mask;
+ }
+ break;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Addressing mode description hooks
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h
index 0c638af..f597780 100644
--- a/lib/Target/XCore/XCoreISelLowering.h
+++ b/lib/Target/XCore/XCoreISelLowering.h
@@ -54,6 +54,15 @@ namespace llvm {
// Corresponds to LSUB instruction
LSUB,
+ // Corresponds to LMUL instruction
+ LMUL,
+
+ // Corresponds to MACCU instruction
+ MACCU,
+
+ // Corresponds to MACCS instruction
+ MACCS,
+
// Jumptable branch.
BR_JT,
@@ -132,6 +141,8 @@ namespace llvm {
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG);
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG);
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG);
// Inline asm support
@@ -140,10 +151,18 @@ namespace llvm {
EVT VT) const;
// Expand specifics
+ SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG);
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ virtual void computeMaskedBitsForTargetNode(const SDValue Op,
+ const APInt &Mask,
+ APInt &KnownZero,
+ APInt &KnownOne,
+ const SelectionDAG &DAG,
+ unsigned Depth = 0) const;
+
virtual SDValue
LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv,
diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp
index c7c8c7b..0ab312e 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.cpp
+++ b/lib/Target/XCore/XCoreRegisterInfo.cpp
@@ -173,7 +173,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned
XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h
index 8ab1750..5bdd059 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.h
+++ b/lib/Target/XCore/XCoreRegisterInfo.h
@@ -58,7 +58,7 @@ public:
MachineBasicBlock::iterator I) const;
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value = NULL,
+ int SPAdj, FrameIndexValue *Value = NULL,
RegScavenger *RS = NULL) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp
index f11ecae..bc8028c 100644
--- a/lib/Transforms/IPO/InlineAlways.cpp
+++ b/lib/Transforms/IPO/InlineAlways.cpp
@@ -45,7 +45,10 @@ namespace {
return CA.getInlineFudgeFactor(CS);
}
void resetCachedCostInfo(Function *Caller) {
- return CA.resetCachedCostInfo(Caller);
+ CA.resetCachedCostInfo(Caller);
+ }
+ void growCachedCostInfo(Function* Caller, Function* Callee) {
+ CA.growCachedCostInfo(Caller, Callee);
}
virtual bool doFinalization(CallGraph &CG) {
return removeDeadFunctions(CG, &NeverInline);
diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp
index 598043d..46cf4b2 100644
--- a/lib/Transforms/IPO/InlineSimple.cpp
+++ b/lib/Transforms/IPO/InlineSimple.cpp
@@ -45,6 +45,9 @@ namespace {
void resetCachedCostInfo(Function *Caller) {
CA.resetCachedCostInfo(Caller);
}
+ void growCachedCostInfo(Function* Caller, Function* Callee) {
+ CA.growCachedCostInfo(Caller, Callee);
+ }
virtual bool doInitialization(CallGraph &CG);
};
}
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 752a97c..03ec72c 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -219,8 +219,10 @@ bool Inliner::shouldInline(CallSite CS) {
Function *Caller = CS.getCaller();
int CurrentThreshold = getInlineThreshold(CS);
float FudgeFactor = getInlineFudgeFactor(CS);
- if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
+ int AdjThreshold = (int)(CurrentThreshold * FudgeFactor);
+ if (Cost >= AdjThreshold) {
DEBUG(dbgs() << " NOT Inlining: cost=" << Cost
+ << ", thres=" << AdjThreshold
<< ", Call: " << *CS.getInstruction() << "\n");
return false;
}
@@ -285,6 +287,7 @@ bool Inliner::shouldInline(CallSite CS) {
}
DEBUG(dbgs() << " Inlining: cost=" << Cost
+ << ", thres=" << AdjThreshold
<< ", Call: " << *CS.getInstruction() << '\n');
return true;
}
@@ -366,6 +369,8 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
CG[Caller]->removeCallEdgeFor(CS);
CS.getInstruction()->eraseFromParent();
++NumCallsDeleted;
+ // Update the cached cost info with the missing call
+ growCachedCostInfo(Caller, NULL);
} else {
// We can only inline direct calls to non-declarations.
if (Callee == 0 || Callee->isDeclaration()) continue;
@@ -379,6 +384,9 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas))
continue;
++NumInlined;
+
+ // Update the cached cost info with the inlined call.
+ growCachedCostInfo(Caller, Callee);
}
// If we inlined or deleted the last possible call site to the function,
@@ -404,11 +412,6 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
delete CG.removeFunctionFromModule(CalleeNode);
++NumDeleted;
}
-
- // Remove any cached cost info for this caller, as inlining the
- // callee has increased the size of the caller (which may be the
- // same as the callee).
- resetCachedCostInfo(Caller);
// Remove this call site from the list. If possible, use
// swap/pop_back for efficiency, but do not use it if doing so would
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index 07fb15e..bd06499 100644
--- a/lib/Transforms/InstCombine/InstCombine.h
+++ b/lib/Transforms/InstCombine/InstCombine.h
@@ -207,6 +207,7 @@ private:
const Type *Ty);
Instruction *visitCallSite(CallSite CS);
+ Instruction *tryOptimizeCall(CallInst *CI, const TargetData *TD);
bool transformConstExprCastCall(CallSite CS);
Instruction *transformCallThroughTrampoline(CallSite CS);
Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI,
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a241f169..0582210 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -16,6 +16,7 @@
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Analysis/MemoryBuiltins.h"
+#include "llvm/Transforms/Utils/BuildLibCalls.h"
using namespace llvm;
/// getPromotedType - Return the specified type promoted as it would be to pass
@@ -336,6 +337,16 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
}
return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize));
}
+ } else if (CallInst *MI = extractMallocCall(Op1)) {
+ const Type* MallocType = getMallocAllocatedType(MI);
+ // Get alloca size.
+ if (MallocType && MallocType->isSized()) {
+ if (Value *NElems = getMallocArraySize(MI, TD, true)) {
+ if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems))
+ return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy,
+ (NElements->getZExtValue() * TD->getTypeAllocSize(MallocType))));
+ }
+ }
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) {
// Only handle constant GEPs here.
if (CE->getOpcode() != Instruction::GetElementPtr) break;
@@ -347,7 +358,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Operand = Operand->stripPointerCasts();
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand))
if (!GV->hasDefinitiveInitializer()) break;
-
+
// Get what we're pointing to and its size.
const PointerType *BaseType =
cast<PointerType>(Operand->getType());
@@ -370,7 +381,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset);
return ReplaceInstUsesWith(CI, RetVal);
- }
+ }
// Do not return "I don't know" here. Later optimization passes could
// make it possible to evaluate objectsize to a constant.
@@ -740,6 +751,122 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS,
return true;
}
+// Try to fold some different type of calls here.
+// Currently we're only working with the checking functions, memcpy_chk,
+// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk,
+// strcat_chk and strncat_chk.
+Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) {
+ if (CI->getCalledFunction() == 0) return 0;
+
+ StringRef Name = CI->getCalledFunction()->getName();
+ BasicBlock *BB = CI->getParent();
+ IRBuilder<> B(CI->getParent()->getContext());
+
+ // Set the builder to the instruction after the call.
+ B.SetInsertPoint(BB, CI);
+
+ if (Name == "__memcpy_chk") {
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+ if (!SizeCI)
+ return 0;
+ ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeArg)
+ return 0;
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+ EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
+ 1, B, TD);
+ return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+ }
+ return 0;
+ }
+
+ // Should be similar to memcpy.
+ if (Name == "__mempcpy_chk") {
+ return 0;
+ }
+
+ if (Name == "__memmove_chk") {
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+ if (!SizeCI)
+ return 0;
+ ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeArg)
+ return 0;
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+ EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
+ 1, B, TD);
+ return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+ }
+ return 0;
+ }
+
+ if (Name == "__memset_chk") {
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+ if (!SizeCI)
+ return 0;
+ ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeArg)
+ return 0;
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+ Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(),
+ false);
+ EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD);
+ return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+ }
+ return 0;
+ }
+
+ if (Name == "__strcpy_chk") {
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeCI)
+ return 0;
+ // If a) we don't have any length information, or b) we know this will
+ // fit then just lower to a plain strcpy. Otherwise we'll keep our
+ // strcpy_chk call which may fail at runtime if the size is too long.
+ // TODO: It might be nice to get a maximum length out of the possible
+ // string lengths for varying.
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) {
+ Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD);
+ return ReplaceInstUsesWith(*CI, Ret);
+ }
+ return 0;
+ }
+
+ // Should be similar to strcpy.
+ if (Name == "__stpcpy_chk") {
+ return 0;
+ }
+
+ if (Name == "__strncpy_chk") {
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+ if (!SizeCI)
+ return 0;
+ ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeArg)
+ return 0;
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+ Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD);
+ return ReplaceInstUsesWith(*CI, Ret);
+ }
+ return 0;
+ }
+
+ if (Name == "__strcat_chk") {
+ return 0;
+ }
+
+ if (Name == "__strncat_chk") {
+ return 0;
+ }
+
+ return 0;
+}
+
// visitCallSite - Improvements for call and invoke instructions.
//
Instruction *InstCombiner::visitCallSite(CallSite CS) {
@@ -826,6 +953,16 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
Changed = true;
}
+ // Try to optimize the call if possible, we require TargetData for most of
+ // this. None of these calls are seen as possibly dead so go ahead and
+ // delete the instruction now.
+ if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) {
+ Instruction *I = tryOptimizeCall(CI, TD);
+ // If we changed something return the result, etc. Otherwise let
+ // the fallthrough check.
+ if (I) return EraseInstFromFunction(*I);
+ }
+
return Changed ? CS.getInstruction() : 0;
}
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index 86ddeac..05027ae 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -633,130 +633,6 @@ struct MemSetOpt : public LibCallOptimization {
};
//===----------------------------------------------------------------------===//
-// Object Size Checking Optimizations
-//===----------------------------------------------------------------------===//
-
-//===---------------------------------------===//
-// 'memcpy_chk' Optimizations
-
-struct MemCpyChkOpt : public LibCallOptimization {
- virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- // These optimizations require TargetData.
- if (!TD) return 0;
-
- const FunctionType *FT = Callee->getFunctionType();
- if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
- !FT->getParamType(0)->isPointerTy() ||
- !FT->getParamType(1)->isPointerTy() ||
- !FT->getParamType(3)->isIntegerTy() ||
- FT->getParamType(2) != TD->getIntPtrType(*Context))
- return 0;
-
- ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
- if (!ObjSizeCI)
- return 0;
- ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
- if (ObjSizeCI->isAllOnesValue() ||
- (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) {
- EmitMemCpy(CI->getOperand(1), CI->getOperand(2),
- CI->getOperand(3), 1, B, TD);
- return CI->getOperand(1);
- }
-
- return 0;
- }
-};
-
-//===---------------------------------------===//
-// 'memset_chk' Optimizations
-
-struct MemSetChkOpt : public LibCallOptimization {
- virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- // These optimizations require TargetData.
- if (!TD) return 0;
-
- const FunctionType *FT = Callee->getFunctionType();
- if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
- !FT->getParamType(0)->isPointerTy() ||
- !FT->getParamType(1)->isIntegerTy() ||
- !FT->getParamType(3)->isIntegerTy() ||
- FT->getParamType(2) != TD->getIntPtrType(*Context))
- return 0;
-
- ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
- if (!ObjSizeCI)
- return 0;
- ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
- if (ObjSizeCI->isAllOnesValue() ||
- (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) {
- Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context),
- false);
- EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD);
- return CI->getOperand(1);
- }
-
- return 0;
- }
-};
-
-//===---------------------------------------===//
-// 'memmove_chk' Optimizations
-
-struct MemMoveChkOpt : public LibCallOptimization {
- virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- // These optimizations require TargetData.
- if (!TD) return 0;
-
- const FunctionType *FT = Callee->getFunctionType();
- if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
- !FT->getParamType(0)->isPointerTy() ||
- !FT->getParamType(1)->isPointerTy() ||
- !FT->getParamType(3)->isIntegerTy() ||
- FT->getParamType(2) != TD->getIntPtrType(*Context))
- return 0;
-
- ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
- if (!ObjSizeCI)
- return 0;
- ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
- if (ObjSizeCI->isAllOnesValue() ||
- (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) {
- EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
- 1, B, TD);
- return CI->getOperand(1);
- }
-
- return 0;
- }
-};
-
-struct StrCpyChkOpt : public LibCallOptimization {
- virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
- if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
- !FT->getParamType(0)->isPointerTy() ||
- !FT->getParamType(1)->isPointerTy())
- return 0;
-
- ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
- if (!ObjSizeCI)
- return 0;
-
- // If a) we don't have any length information, or b) we know this will
- // fit then just lower to a plain strcpy. Otherwise we'll keep our
- // strcpy_chk call which may fail at runtime if the size is too long.
- // TODO: It might be nice to get a maximum length out of the possible
- // string lengths for varying.
- if (ObjSizeCI->isAllOnesValue() ||
- ObjSizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2)))
- return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD);
-
- return 0;
- }
-};
-
-
-//===----------------------------------------------------------------------===//
// Math Library Optimizations
//===----------------------------------------------------------------------===//
@@ -1298,10 +1174,6 @@ namespace {
SPrintFOpt SPrintF; PrintFOpt PrintF;
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
- // Object Size Checking
- MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk;
- StrCpyChkOpt StrCpyChk;
-
bool Modified; // This is only used by doInitialization.
public:
static char ID; // Pass identification
@@ -1407,12 +1279,6 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["fwrite"] = &FWrite;
Optimizations["fputs"] = &FPuts;
Optimizations["fprintf"] = &FPrintF;
-
- // Object Size Checking
- Optimizations["__memcpy_chk"] = &MemCpyChk;
- Optimizations["__memset_chk"] = &MemSetChk;
- Optimizations["__memmove_chk"] = &MemMoveChk;
- Optimizations["__strcpy_chk"] = &StrCpyChk;
}
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp
index c80827d..62fc2ec 100644
--- a/lib/Transforms/Utils/CloneFunction.cpp
+++ b/lib/Transforms/Utils/CloneFunction.cpp
@@ -336,14 +336,14 @@ ConstantFoldMappedInstruction(const Instruction *I) {
static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD) {
DILocation ILoc(InsnMD);
- if (ILoc.isNull()) return InsnMD;
+ if (!ILoc.Verify()) return InsnMD;
DILocation CallLoc(TheCallMD);
- if (CallLoc.isNull()) return InsnMD;
+ if (!CallLoc.Verify()) return InsnMD;
DILocation OrigLocation = ILoc.getOrigLocation();
MDNode *NewLoc = TheCallMD;
- if (!OrigLocation.isNull())
+ if (OrigLocation.Verify())
NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD);
Value *MDVs[] = {
diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp
index 924b744..584ec14 100644
--- a/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/lib/Transforms/Utils/LoopSimplify.cpp
@@ -132,7 +132,7 @@ bool LoopSimplify::ProcessLoop(Loop *L, LPPassManager &LPM) {
bool Changed = false;
ReprocessLoop:
- // Check to see that no blocks (other than the header) in this loop that has
+ // Check to see that no blocks (other than the header) in this loop have
// predecessors that are not in the loop. This is not valid for natural
// loops, but can occur if the blocks are unreachable. Since they are
// unreachable we can just shamelessly delete those CFG edges!
diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp
index a08c454..379aeb5 100644
--- a/lib/VMCore/Metadata.cpp
+++ b/lib/VMCore/Metadata.cpp
@@ -39,15 +39,6 @@ MDString *MDString::get(LLVMContext &Context, StringRef Str) {
return S;
}
-MDString *MDString::get(LLVMContext &Context, const char *Str) {
- LLVMContextImpl *pImpl = Context.pImpl;
- StringMapEntry<MDString *> &Entry =
- pImpl->MDStringCache.GetOrCreateValue(Str ? StringRef(Str) : StringRef());
- MDString *&S = Entry.getValue();
- if (!S) S = new MDString(Context, Entry.getKey());
- return S;
-}
-
//===----------------------------------------------------------------------===//
// MDNodeOperand implementation.
//
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 35625a5..721e96a 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1525,6 +1525,15 @@ void Verifier::VerifyType(const Type *Ty) {
VerifyType(ElTy);
}
} break;
+ case Type::UnionTyID: {
+ const UnionType *UTy = cast<UnionType>(Ty);
+ for (unsigned i = 0, e = UTy->getNumElements(); i != e; ++i) {
+ const Type *ElTy = UTy->getElementType(i);
+ Assert2(UnionType::isValidElementType(ElTy),
+ "Union type with invalid element type", ElTy, UTy);
+ VerifyType(ElTy);
+ }
+ } break;
case Type::ArrayTyID: {
const ArrayType *ATy = cast<ArrayType>(Ty);
Assert1(ArrayType::isValidElementType(ATy->getElementType()),
diff --git a/runtime/Makefile b/runtime/Makefile
index f9a4054..7209867 100644
--- a/runtime/Makefile
+++ b/runtime/Makefile
@@ -20,7 +20,7 @@ ifeq ($(ARCH), Sparc)
PARALLEL_DIRS := $(filter-out libprofile, $(PARALLEL_DIRS))
endif
-ifeq ($(OS), Cygwin)
+ifeq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW))
PARALLEL_DIRS := $(filter-out libprofile, $(PARALLEL_DIRS))
endif
diff --git a/test/Analysis/ScalarEvolution/unreachable-code.ll b/test/Analysis/ScalarEvolution/unreachable-code.ll
new file mode 100644
index 0000000..51d9398
--- /dev/null
+++ b/test/Analysis/ScalarEvolution/unreachable-code.ll
@@ -0,0 +1,13 @@
+; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s
+
+; CHECK: %t = add i64 %t, 1
+; CHECK: --> %t
+
+define void @foo() {
+entry:
+ ret void
+
+dead:
+ %t = add i64 %t, 1
+ ret void
+}
diff --git a/test/CodeGen/ARM/armv4.ll b/test/CodeGen/ARM/armv4.ll
new file mode 100644
index 0000000..49b129da
--- /dev/null
+++ b/test/CodeGen/ARM/armv4.ll
@@ -0,0 +1,13 @@
+; RUN: llc < %s -mtriple=arm-unknown-eabi | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=strongarm | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=cortex-a8 | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mattr=+v6 | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=armv4-unknown-eabi | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=armv4t-unknown-eabi | FileCheck %s -check-prefix=THUMB
+
+define arm_aapcscc i32 @test(i32 %a) nounwind readnone {
+entry:
+; ARM: mov pc
+; THUMB: bx
+ ret i32 %a
+}
diff --git a/test/CodeGen/ARM/indirectbr.ll b/test/CodeGen/ARM/indirectbr.ll
index 5135d03..f050337 100644
--- a/test/CodeGen/ARM/indirectbr.ll
+++ b/test/CodeGen/ARM/indirectbr.ll
@@ -15,14 +15,14 @@ entry:
; indirect branch gets duplicated here
; ARM: bx
; THUMB: mov pc, r1
-; THUMB2: mov pc, r1
+; THUMB2: mov pc, r2
br i1 %1, label %bb3, label %bb2
bb2: ; preds = %entry, %bb3
%gotovar.4.0 = phi i8* [ %gotovar.4.0.pre, %bb3 ], [ %0, %entry ] ; <i8*> [#uses=1]
; ARM: bx
; THUMB: mov pc, r1
-; THUMB2: mov pc, r1
+; THUMB2: mov pc, r2
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]
bb3: ; preds = %entry
diff --git a/test/CodeGen/MBlaze/cc.ll b/test/CodeGen/MBlaze/cc.ll
index de55728..aaa918f 100644
--- a/test/CodeGen/MBlaze/cc.ll
+++ b/test/CodeGen/MBlaze/cc.ll
@@ -101,7 +101,7 @@ define i32 @params7_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g) {
; CHECK: params7_32bitret:
ret i32 %g
- ; CHECK: {{lwi? r3, r1, 8}}
+ ; CHECK: {{lwi? r3, r1, 32}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@@ -110,7 +110,7 @@ define i32 @params8_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h) {
; CHECK: params8_32bitret:
ret i32 %h
- ; CHECK: {{lwi? r3, r1, 12}}
+ ; CHECK: {{lwi? r3, r1, 36}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@@ -119,7 +119,7 @@ define i32 @params9_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h, i32 %i) {
; CHECK: params9_32bitret:
ret i32 %i
- ; CHECK: {{lwi? r3, r1, 16}}
+ ; CHECK: {{lwi? r3, r1, 40}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@@ -128,7 +128,7 @@ define i32 @params10_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
i32 %g, i32 %h, i32 %i, i32 %j) {
; CHECK: params10_32bitret:
ret i32 %j
- ; CHECK: {{lwi? r3, r1, 20}}
+ ; CHECK: {{lwi? r3, r1, 44}}
; CHECK-NOT: {{.* r4, .*, .*}}
; CHECK: rtsd
}
@@ -243,7 +243,7 @@ define void @testing() {
%tmp.11 = call i32 @params7_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7)
- ; CHECK: {{swi? .*, r1, 4}}
+ ; CHECK: {{swi? .*, r1, 28}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@@ -259,8 +259,8 @@ define void @testing() {
%tmp.12 = call i32 @params8_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8)
- ; CHECK: {{swi? .*, r1, 4}}
- ; CHECK: {{swi? .*, r1, 8}}
+ ; CHECK: {{swi? .*, r1, 28}}
+ ; CHECK: {{swi? .*, r1, 32}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@@ -276,9 +276,9 @@ define void @testing() {
%tmp.13 = call i32 @params9_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8, i32 9)
- ; CHECK: {{swi? .*, r1, 4}}
- ; CHECK: {{swi? .*, r1, 8}}
- ; CHECK: {{swi? .*, r1, 12}}
+ ; CHECK: {{swi? .*, r1, 28}}
+ ; CHECK: {{swi? .*, r1, 32}}
+ ; CHECK: {{swi? .*, r1, 36}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
@@ -294,10 +294,10 @@ define void @testing() {
%tmp.14 = call i32 @params10_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
i32 6, i32 7, i32 8, i32 9, i32 10)
- ; CHECK: {{swi? .*, r1, 4}}
- ; CHECK: {{swi? .*, r1, 8}}
- ; CHECK: {{swi? .*, r1, 12}}
- ; CHECK: {{swi? .*, r1, 16}}
+ ; CHECK: {{swi? .*, r1, 28}}
+ ; CHECK: {{swi? .*, r1, 32}}
+ ; CHECK: {{swi? .*, r1, 36}}
+ ; CHECK: {{swi? .*, r1, 40}}
; CHECK: {{.* r5, .*, .*}}
; CHECK: {{.* r6, .*, .*}}
; CHECK: {{.* r7, .*, .*}}
diff --git a/test/CodeGen/MSP430/AddrMode-bis-rx.ll b/test/CodeGen/MSP430/AddrMode-bis-rx.ll
index 115464d..4f9a724 100644
--- a/test/CodeGen/MSP430/AddrMode-bis-rx.ll
+++ b/test/CodeGen/MSP430/AddrMode-bis-rx.ll
@@ -29,7 +29,7 @@ define i8 @am3(i8 %x, i16 %n) nounwind {
ret i8 %3
}
; CHECK: am3:
-; CHECK: bis.b &bar(r14), r15
+; CHECK: bis.b bar(r14), r15
define i16 @am4(i16 %x) nounwind {
%1 = volatile load i16* inttoptr(i16 32 to i16*)
@@ -70,5 +70,5 @@ define i8 @am7(i8 %x, i16 %n) nounwind {
ret i8 %4
}
; CHECK: am7:
-; CHECK: bis.b &duh+2(r14), r15
+; CHECK: bis.b duh+2(r14), r15
diff --git a/test/CodeGen/MSP430/AddrMode-bis-xr.ll b/test/CodeGen/MSP430/AddrMode-bis-xr.ll
index 3baf332..17ebd87 100644
--- a/test/CodeGen/MSP430/AddrMode-bis-xr.ll
+++ b/test/CodeGen/MSP430/AddrMode-bis-xr.ll
@@ -32,7 +32,7 @@ define void @am3(i16 %i, i8 %x) nounwind {
ret void
}
; CHECK: am3:
-; CHECK: bis.b r14, &bar(r15)
+; CHECK: bis.b r14, bar(r15)
define void @am4(i16 %x) nounwind {
%1 = volatile load i16* inttoptr(i16 32 to i16*)
@@ -77,5 +77,5 @@ define void @am7(i16 %n, i8 %x) nounwind {
ret void
}
; CHECK: am7:
-; CHECK: bis.b r14, &duh+2(r15)
+; CHECK: bis.b r14, duh+2(r15)
diff --git a/test/CodeGen/MSP430/AddrMode-mov-rx.ll b/test/CodeGen/MSP430/AddrMode-mov-rx.ll
index 9144f9a..6676b88 100644
--- a/test/CodeGen/MSP430/AddrMode-mov-rx.ll
+++ b/test/CodeGen/MSP430/AddrMode-mov-rx.ll
@@ -26,7 +26,7 @@ define i8 @am3(i16 %n) nounwind {
ret i8 %2
}
; CHECK: am3:
-; CHECK: mov.b &bar(r15), r15
+; CHECK: mov.b bar(r15), r15
define i16 @am4() nounwind {
%1 = volatile load i16* inttoptr(i16 32 to i16*)
@@ -63,5 +63,5 @@ define i8 @am7(i16 %n) nounwind {
ret i8 %3
}
; CHECK: am7:
-; CHECK: mov.b &duh+2(r15), r15
+; CHECK: mov.b duh+2(r15), r15
diff --git a/test/CodeGen/MSP430/AddrMode-mov-xr.ll b/test/CodeGen/MSP430/AddrMode-mov-xr.ll
index 333c800..4b327b0 100644
--- a/test/CodeGen/MSP430/AddrMode-mov-xr.ll
+++ b/test/CodeGen/MSP430/AddrMode-mov-xr.ll
@@ -26,7 +26,7 @@ define void @am3(i16 %i, i8 %a) nounwind {
ret void
}
; CHECK: am3:
-; CHECK: mov.b r14, &bar(r15)
+; CHECK: mov.b r14, bar(r15)
define void @am4(i16 %a) nounwind {
volatile store i16 %a, i16* inttoptr(i16 32 to i16*)
@@ -63,5 +63,5 @@ define void @am7(i16 %n, i8 %a) nounwind {
ret void
}
; CHECK: am7:
-; CHECK: mov.b r14, &duh+2(r15)
+; CHECK: mov.b r14, duh+2(r15)
diff --git a/test/CodeGen/PowerPC/2010-03-09-indirect-call.ll b/test/CodeGen/PowerPC/2010-03-09-indirect-call.ll
new file mode 100644
index 0000000..d094509
--- /dev/null
+++ b/test/CodeGen/PowerPC/2010-03-09-indirect-call.ll
@@ -0,0 +1,19 @@
+; RUN: llc < %s -march=ppc32 -mcpu=g5 -mtriple=powerpc-apple-darwin10.0 | FileCheck %s
+; ModuleID = 'nn.c'
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128"
+target triple = "powerpc-apple-darwin11.0"
+; Indirect calls must use R12 on Darwin (i.e., R12 must contain the address of
+; the function being called; the mtctr is not required to use it).
+
+@p = external global void (...)* ; <void (...)**> [#uses=1]
+
+define void @foo() nounwind ssp {
+entry:
+; CHECK: mtctr r12
+ %0 = load void (...)** @p, align 4 ; <void (...)*> [#uses=1]
+ call void (...)* %0() nounwind
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
diff --git a/test/CodeGen/PowerPC/indirectbr.ll b/test/CodeGen/PowerPC/indirectbr.ll
index 2094e10..233d923 100644
--- a/test/CodeGen/PowerPC/indirectbr.ll
+++ b/test/CodeGen/PowerPC/indirectbr.ll
@@ -43,13 +43,13 @@ L2: ; preds = %L3, %bb2
L1: ; preds = %L2, %bb2
%res.3 = phi i32 [ %phitmp, %L2 ], [ 2, %bb2 ] ; <i32> [#uses=1]
-; PIC: addis r5, r4, ha16(L_BA4__foo_L5-"L1$pb")
+; PIC: addis r4, r4, ha16(L_BA4__foo_L5-"L1$pb")
; PIC: li r6, lo16(L_BA4__foo_L5-"L1$pb")
-; PIC: add r5, r5, r6
-; PIC: stw r5
-; STATIC: li r4, lo16(L_BA4__foo_L5)
-; STATIC: addis r4, r4, ha16(L_BA4__foo_L5)
-; STATIC: stw r4
+; PIC: add r4, r4, r6
+; PIC: stw r4
+; STATIC: li r5, lo16(L_BA4__foo_L5)
+; STATIC: addis r5, r5, ha16(L_BA4__foo_L5)
+; STATIC: stw r5
store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4
ret i32 %res.3
}
diff --git a/test/CodeGen/Thumb/2009-08-20-ISelBug.ll b/test/CodeGen/Thumb/2009-08-20-ISelBug.ll
index c31b65b..72c9e62 100644
--- a/test/CodeGen/Thumb/2009-08-20-ISelBug.ll
+++ b/test/CodeGen/Thumb/2009-08-20-ISelBug.ll
@@ -11,7 +11,7 @@
define arm_apcscc i32 @t(%struct.asl_file_t* %s, i64 %off, i64* %out) nounwind optsize {
; CHECK: t:
-; CHECK: adds r3, #8
+; CHECK: adds r0, #8
entry:
%val = alloca i64, align 4 ; <i64*> [#uses=3]
%0 = icmp eq %struct.asl_file_t* %s, null ; <i1> [#uses=1]
diff --git a/test/CodeGen/Thumb2/2010-03-08-addi12-ccout.ll b/test/CodeGen/Thumb2/2010-03-08-addi12-ccout.ll
new file mode 100644
index 0000000..54f4122
--- /dev/null
+++ b/test/CodeGen/Thumb2/2010-03-08-addi12-ccout.ll
@@ -0,0 +1,266 @@
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin
+
+@.str41196 = external constant [2 x i8], align 4 ; <[2 x i8]*> [#uses=1]
+
+declare arm_apcscc void @syStopraw(i32) nounwind
+
+declare arm_apcscc i32 @SyFopen(i8*, i8*) nounwind
+
+declare arm_apcscc i8* @SyFgets(i8*, i32) nounwind
+
+define arm_apcscc void @SyHelp(i8* nocapture %topic, i32 %fin) nounwind {
+entry:
+ %line = alloca [256 x i8], align 4 ; <[256 x i8]*> [#uses=1]
+ %secname = alloca [1024 x i8], align 4 ; <[1024 x i8]*> [#uses=0]
+ %last = alloca [256 x i8], align 4 ; <[256 x i8]*> [#uses=1]
+ %last2 = alloca [256 x i8], align 4 ; <[256 x i8]*> [#uses=1]
+ br i1 undef, label %bb, label %bb2
+
+bb: ; preds = %entry
+ br i1 undef, label %bb2, label %bb3
+
+bb2: ; preds = %bb, %entry
+ br label %bb3
+
+bb3: ; preds = %bb2, %bb
+ %storemerge = phi i32 [ 0, %bb2 ], [ 1, %bb ] ; <i32> [#uses=1]
+ br i1 undef, label %bb19, label %bb20
+
+bb19: ; preds = %bb3
+ br label %bb20
+
+bb20: ; preds = %bb19, %bb3
+ br i1 undef, label %bb25, label %bb26
+
+bb25: ; preds = %bb20
+ br label %bb26
+
+bb26: ; preds = %bb25, %bb20
+ %offset.2 = phi i32 [ -2, %bb25 ], [ 0, %bb20 ] ; <i32> [#uses=1]
+ br i1 undef, label %bb.nph508, label %bb49
+
+bb.nph508: ; preds = %bb26
+ unreachable
+
+bb49: ; preds = %bb26
+ br i1 undef, label %bb51, label %bb50
+
+bb50: ; preds = %bb49
+ br i1 undef, label %bb51, label %bb104
+
+bb51: ; preds = %bb50, %bb49
+ unreachable
+
+bb104: ; preds = %bb50
+ br i1 undef, label %bb106, label %bb105
+
+bb105: ; preds = %bb104
+ br i1 undef, label %bb106, label %bb161
+
+bb106: ; preds = %bb105, %bb104
+ unreachable
+
+bb161: ; preds = %bb105
+ br i1 false, label %bb163, label %bb162
+
+bb162: ; preds = %bb161
+ br i1 undef, label %bb163, label %bb224
+
+bb163: ; preds = %bb162, %bb161
+ unreachable
+
+bb224: ; preds = %bb162
+ %0 = call arm_apcscc i32 @SyFopen(i8* undef, i8* getelementptr inbounds ([2 x i8]* @.str41196, i32 0, i32 0)) nounwind ; <i32> [#uses=2]
+ br i1 false, label %bb297, label %bb300
+
+bb297: ; preds = %bb224
+ unreachable
+
+bb300: ; preds = %bb224
+ %1 = icmp eq i32 %offset.2, -1 ; <i1> [#uses=1]
+ br label %bb440
+
+bb307: ; preds = %isdigit1498.exit67
+ br label %bb308
+
+bb308: ; preds = %bb440, %bb307
+ br i1 undef, label %bb309, label %isdigit1498.exit67
+
+isdigit1498.exit67: ; preds = %bb308
+ br i1 undef, label %bb309, label %bb307
+
+bb309: ; preds = %isdigit1498.exit67, %bb308
+ br i1 undef, label %bb310, label %bb313
+
+bb310: ; preds = %bb309
+ br label %bb313
+
+bb313: ; preds = %bb310, %bb309
+ br i1 false, label %bb318, label %bb317
+
+bb317: ; preds = %bb313
+ %2 = icmp sgt i8 undef, -1 ; <i1> [#uses=1]
+ br i1 %2, label %bb.i.i73, label %bb1.i.i74
+
+bb.i.i73: ; preds = %bb317
+ br i1 false, label %bb318, label %bb329.outer
+
+bb1.i.i74: ; preds = %bb317
+ unreachable
+
+bb318: ; preds = %bb.i.i73, %bb313
+ ret void
+
+bb329.outer: ; preds = %bb.i.i73
+ br i1 undef, label %bb333, label %bb329.us.us
+
+bb329.us.us: ; preds = %bb329.us.us, %bb329.outer
+ br i1 undef, label %bb333, label %bb329.us.us
+
+bb333: ; preds = %bb329.us.us, %bb329.outer
+ %match.0.lcssa = phi i32 [ undef, %bb329.us.us ], [ 2, %bb329.outer ] ; <i32> [#uses=2]
+ br i1 undef, label %bb335, label %bb388
+
+bb335: ; preds = %bb333
+ %3 = and i1 undef, %1 ; <i1> [#uses=1]
+ br i1 %3, label %bb339, label %bb348
+
+bb339: ; preds = %bb335
+ br i1 false, label %bb340, label %bb345
+
+bb340: ; preds = %bb339
+ br i1 undef, label %return, label %bb341
+
+bb341: ; preds = %bb340
+ ret void
+
+bb345: ; preds = %bb345, %bb339
+ %4 = phi i8 [ %5, %bb345 ], [ undef, %bb339 ] ; <i8> [#uses=0]
+ %indvar670 = phi i32 [ %tmp673, %bb345 ], [ 0, %bb339 ] ; <i32> [#uses=1]
+ %tmp673 = add i32 %indvar670, 1 ; <i32> [#uses=2]
+ %scevgep674 = getelementptr [256 x i8]* %last, i32 0, i32 %tmp673 ; <i8*> [#uses=1]
+ %5 = load i8* %scevgep674, align 1 ; <i8> [#uses=1]
+ br i1 undef, label %bb347, label %bb345
+
+bb347: ; preds = %bb345
+ br label %bb348
+
+bb348: ; preds = %bb347, %bb335
+ br i1 false, label %bb352, label %bb356
+
+bb352: ; preds = %bb348
+ unreachable
+
+bb356: ; preds = %bb348
+ br i1 undef, label %bb360, label %bb369
+
+bb360: ; preds = %bb356
+ br i1 false, label %bb361, label %bb366
+
+bb361: ; preds = %bb360
+ br i1 undef, label %return, label %bb362
+
+bb362: ; preds = %bb361
+ ret void
+
+bb366: ; preds = %bb366, %bb360
+ %indvar662 = phi i32 [ %tmp665, %bb366 ], [ 0, %bb360 ] ; <i32> [#uses=1]
+ %tmp665 = add i32 %indvar662, 1 ; <i32> [#uses=2]
+ %scevgep666 = getelementptr [256 x i8]* %last2, i32 0, i32 %tmp665 ; <i8*> [#uses=1]
+ %6 = load i8* %scevgep666, align 1 ; <i8> [#uses=0]
+ br i1 false, label %bb368, label %bb366
+
+bb368: ; preds = %bb366
+ br label %bb369
+
+bb369: ; preds = %bb368, %bb356
+ br i1 undef, label %bb373, label %bb388
+
+bb373: ; preds = %bb383, %bb369
+ %7 = call arm_apcscc i8* @SyFgets(i8* undef, i32 %0) nounwind ; <i8*> [#uses=1]
+ %8 = icmp eq i8* %7, null ; <i1> [#uses=1]
+ br i1 %8, label %bb375, label %bb383
+
+bb375: ; preds = %bb373
+ %9 = icmp eq i32 %storemerge, 0 ; <i1> [#uses=1]
+ br i1 %9, label %return, label %bb376
+
+bb376: ; preds = %bb375
+ ret void
+
+bb383: ; preds = %bb373
+ %10 = load i8* undef, align 1 ; <i8> [#uses=1]
+ %cond1 = icmp eq i8 %10, 46 ; <i1> [#uses=1]
+ br i1 %cond1, label %bb373, label %bb388
+
+bb388: ; preds = %bb383, %bb369, %bb333
+ %match.1140 = phi i32 [ %match.0.lcssa, %bb369 ], [ 0, %bb333 ], [ %match.0.lcssa, %bb383 ] ; <i32> [#uses=1]
+ br label %bb391
+
+bb390: ; preds = %isdigit1498.exit83, %bb392
+ %indvar.next725 = add i32 %indvar724, 1 ; <i32> [#uses=1]
+ br label %bb391
+
+bb391: ; preds = %bb390, %bb388
+ %indvar724 = phi i32 [ %indvar.next725, %bb390 ], [ 0, %bb388 ] ; <i32> [#uses=2]
+ %11 = load i8* undef, align 1 ; <i8> [#uses=0]
+ br i1 false, label %bb395, label %bb392
+
+bb392: ; preds = %bb391
+ br i1 undef, label %bb390, label %isdigit1498.exit83
+
+isdigit1498.exit83: ; preds = %bb392
+ br i1 undef, label %bb390, label %bb395
+
+bb394: ; preds = %isdigit1498.exit87
+ br label %bb395
+
+bb395: ; preds = %bb394, %isdigit1498.exit83, %bb391
+ %storemerge14.sum = add i32 %indvar724, undef ; <i32> [#uses=1]
+ %p.26 = getelementptr [256 x i8]* %line, i32 0, i32 %storemerge14.sum ; <i8*> [#uses=1]
+ br i1 undef, label %bb400, label %isdigit1498.exit87
+
+isdigit1498.exit87: ; preds = %bb395
+ br i1 false, label %bb400, label %bb394
+
+bb400: ; preds = %isdigit1498.exit87, %bb395
+ br i1 undef, label %bb402, label %bb403
+
+bb402: ; preds = %bb400
+ %12 = getelementptr inbounds i8* %p.26, i32 undef ; <i8*> [#uses=1]
+ br label %bb403
+
+bb403: ; preds = %bb402, %bb400
+ %p.29 = phi i8* [ %12, %bb402 ], [ undef, %bb400 ] ; <i8*> [#uses=0]
+ br i1 undef, label %bb405, label %bb404
+
+bb404: ; preds = %bb403
+ br i1 undef, label %bb405, label %bb407
+
+bb405: ; preds = %bb404, %bb403
+ br i1 undef, label %return, label %bb406
+
+bb406: ; preds = %bb405
+ call arm_apcscc void @syStopraw(i32 %fin) nounwind
+ ret void
+
+bb407: ; preds = %bb404
+ %cond = icmp eq i32 %match.1140, 2 ; <i1> [#uses=1]
+ br i1 %cond, label %bb408, label %bb428
+
+bb408: ; preds = %bb407
+ unreachable
+
+bb428: ; preds = %bb407
+ br label %bb440
+
+bb440: ; preds = %bb428, %bb300
+ %13 = call arm_apcscc i8* @SyFgets(i8* undef, i32 %0) nounwind ; <i8*> [#uses=0]
+ br i1 false, label %bb442, label %bb308
+
+bb442: ; preds = %bb440
+ unreachable
+
+return: ; preds = %bb405, %bb375, %bb361, %bb340
+ ret void
+}
diff --git a/test/CodeGen/Thumb2/machine-licm.ll b/test/CodeGen/Thumb2/machine-licm.ll
index 9ab19e9..53ff537 100644
--- a/test/CodeGen/Thumb2/machine-licm.ll
+++ b/test/CodeGen/Thumb2/machine-licm.ll
@@ -18,9 +18,8 @@ entry:
bb.nph: ; preds = %entry
; CHECK: BB#1
; CHECK: ldr.n r2, LCPI1_0
-; CHECK: ldr r3, [r2]
-; CHECK: ldr r3, [r3]
; CHECK: ldr r2, [r2]
+; CHECK: ldr r3, [r2]
; CHECK: LBB1_2
; CHECK: LCPI1_0:
; CHECK-NOT: LCPI1_1:
@@ -29,9 +28,8 @@ bb.nph: ; preds = %entry
; PIC: BB#1
; PIC: ldr.n r2, LCPI1_0
; PIC: add r2, pc
-; PIC: ldr r3, [r2]
-; PIC: ldr r3, [r3]
; PIC: ldr r2, [r2]
+; PIC: ldr r3, [r2]
; PIC: LBB1_2
; PIC: LCPI1_0:
; PIC-NOT: LCPI1_1:
diff --git a/test/CodeGen/X86/2007-10-16-IllegalAsm.ll b/test/CodeGen/X86/2007-10-16-IllegalAsm.ll
deleted file mode 100644
index 6d0cb47..0000000
--- a/test/CodeGen/X86/2007-10-16-IllegalAsm.ll
+++ /dev/null
@@ -1,272 +0,0 @@
-; RUN: llc < %s -mtriple=x86_64-linux-gnu | grep movb | not grep x
-; PR1734
-
- %struct.CUMULATIVE_ARGS = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }
- %struct.eh_status = type opaque
- %struct.emit_status = type { i32, i32, %struct.rtx_def*, %struct.rtx_def*, %struct.sequence_stack*, i32, %struct.location_t, i32, i8*, %struct.rtx_def** }
- %struct.expr_status = type { i32, i32, i32, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def* }
- %struct.function = type { %struct.eh_status*, %struct.expr_status*, %struct.emit_status*, %struct.varasm_status*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.function*, i32, i32, i32, i32, %struct.rtx_def*, %struct.CUMULATIVE_ARGS, %struct.rtx_def*, %struct.rtx_def*, %struct.initial_value_struct*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, i8, i32, i64, %struct.tree_node*, %struct.tree_node*, %struct.rtx_def*, %struct.varray_head_tag*, %struct.temp_slot*, i32, %struct.var_refs_queue*, i32, i32, %struct.rtvec_def*, %struct.tree_node*, i32, i32, i32, %struct.machine_function*, i32, i32, i8, i8, %struct.language_function*, %struct.rtx_def*, i32, i32, i32, i32, %struct.location_t, %struct.varray_head_tag*, %struct.tree_node*, %struct.tree_node*, i8, i8, i8 }
- %struct.initial_value_struct = type opaque
- %struct.lang_decl = type opaque
- %struct.lang_type = type opaque
- %struct.language_function = type opaque
- %struct.location_t = type { i8*, i32 }
- %struct.machine_function = type { %struct.stack_local_entry*, i8*, %struct.rtx_def*, i32, i32, i32, i32, i32 }
- %struct.rtunion = type { i8* }
- %struct.rtvec_def = type { i32, [1 x %struct.rtx_def*] }
- %struct.rtx_def = type { i16, i8, i8, %struct.u }
- %struct.sequence_stack = type { %struct.rtx_def*, %struct.rtx_def*, %struct.sequence_stack* }
- %struct.stack_local_entry = type opaque
- %struct.temp_slot = type opaque
- %struct.tree_common = type { %struct.tree_node*, %struct.tree_node*, %union.tree_ann_d*, i8, i8, i8, i8, i8 }
- %struct.tree_decl = type { %struct.tree_common, %struct.location_t, i32, %struct.tree_node*, i8, i8, i8, i8, i8, i8, i8, i8, i32, %struct.tree_decl_u1, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.rtx_def*, i32, %struct.tree_decl_u2, %struct.tree_node*, %struct.tree_node*, i64, %struct.lang_decl* }
- %struct.tree_decl_u1 = type { i64 }
- %struct.tree_decl_u2 = type { %struct.function* }
- %struct.tree_node = type { %struct.tree_decl }
- %struct.tree_type = type { %struct.tree_common, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, i32, i16, i8, i8, i32, %struct.tree_node*, %struct.tree_node*, %struct.rtunion, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, %struct.tree_node*, i64, %struct.lang_type* }
- %struct.u = type { [1 x %struct.rtunion] }
- %struct.var_refs_queue = type { %struct.rtx_def*, i32, i32, %struct.var_refs_queue* }
- %struct.varasm_status = type opaque
- %struct.varray_data = type { [1 x i64] }
- %struct.varray_head_tag = type { i64, i64, i32, i8*, %struct.varray_data }
- %union.tree_ann_d = type opaque
-@.str = external constant [28 x i8] ; <[28 x i8]*> [#uses=1]
-@tree_code_type = external constant [0 x i32] ; <[0 x i32]*> [#uses=5]
-@global_trees = external global [47 x %struct.tree_node*] ; <[47 x %struct.tree_node*]*> [#uses=1]
-@mode_size = external global [48 x i8] ; <[48 x i8]*> [#uses=1]
-@__FUNCTION__.22683 = external constant [12 x i8] ; <[12 x i8]*> [#uses=1]
-
-define void @layout_type(%struct.tree_node* %type) {
-entry:
- %tmp15 = icmp eq %struct.tree_node* %type, null ; <i1> [#uses=1]
- br i1 %tmp15, label %cond_true, label %cond_false
-
-cond_true: ; preds = %entry
- tail call void @fancy_abort( i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1713, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_false: ; preds = %entry
- %tmp19 = load %struct.tree_node** getelementptr ([47 x %struct.tree_node*]* @global_trees, i32 0, i64 0), align 8 ; <%struct.tree_node*> [#uses=1]
- %tmp21 = icmp eq %struct.tree_node* %tmp19, %type ; <i1> [#uses=1]
- br i1 %tmp21, label %UnifiedReturnBlock, label %cond_next25
-
-cond_next25: ; preds = %cond_false
- %tmp30 = getelementptr %struct.tree_node* %type, i32 0, i32 0, i32 0, i32 3 ; <i8*> [#uses=1]
- %tmp3031 = bitcast i8* %tmp30 to i32* ; <i32*> [#uses=6]
- %tmp32 = load i32* %tmp3031, align 8 ; <i32> [#uses=3]
- %tmp3435 = trunc i32 %tmp32 to i8 ; <i8> [#uses=3]
- %tmp34353637 = zext i8 %tmp3435 to i64 ; <i64> [#uses=1]
- %tmp38 = getelementptr [0 x i32]* @tree_code_type, i32 0, i64 %tmp34353637 ; <i32*> [#uses=1]
- %tmp39 = load i32* %tmp38, align 4 ; <i32> [#uses=1]
- %tmp40 = icmp eq i32 %tmp39, 2 ; <i1> [#uses=4]
- br i1 %tmp40, label %cond_next46, label %cond_true43
-
-cond_true43: ; preds = %cond_next25
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1719, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next46: ; preds = %cond_next25
- %tmp4950 = bitcast %struct.tree_node* %type to %struct.tree_type* ; <%struct.tree_type*> [#uses=2]
- %tmp51 = getelementptr %struct.tree_type* %tmp4950, i32 0, i32 2 ; <%struct.tree_node**> [#uses=2]
- %tmp52 = load %struct.tree_node** %tmp51, align 8 ; <%struct.tree_node*> [#uses=1]
- %tmp53 = icmp eq %struct.tree_node* %tmp52, null ; <i1> [#uses=1]
- br i1 %tmp53, label %cond_next57, label %UnifiedReturnBlock
-
-cond_next57: ; preds = %cond_next46
- %tmp65 = and i32 %tmp32, 255 ; <i32> [#uses=1]
- switch i32 %tmp65, label %UnifiedReturnBlock [
- i32 6, label %bb140
- i32 7, label %bb69
- i32 8, label %bb140
- i32 13, label %bb478
- i32 23, label %bb
- ]
-
-bb: ; preds = %cond_next57
- tail call void @fancy_abort( i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1727, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-bb69: ; preds = %cond_next57
- br i1 %tmp40, label %cond_next91, label %cond_true88
-
-cond_true88: ; preds = %bb69
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1730, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next91: ; preds = %bb69
- %tmp96 = getelementptr %struct.tree_node* %type, i32 0, i32 0, i32 8 ; <i8*> [#uses=1]
- %tmp9697 = bitcast i8* %tmp96 to i32* ; <i32*> [#uses=2]
- %tmp98 = load i32* %tmp9697, align 8 ; <i32> [#uses=2]
- %tmp100101552 = and i32 %tmp98, 511 ; <i32> [#uses=1]
- %tmp102 = icmp eq i32 %tmp100101552, 0 ; <i1> [#uses=1]
- br i1 %tmp102, label %cond_true105, label %bb140
-
-cond_true105: ; preds = %cond_next91
- br i1 %tmp40, label %cond_next127, label %cond_true124
-
-cond_true124: ; preds = %cond_true105
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1731, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next127: ; preds = %cond_true105
- %tmp136 = or i32 %tmp98, 1 ; <i32> [#uses=1]
- %tmp137 = and i32 %tmp136, -511 ; <i32> [#uses=1]
- store i32 %tmp137, i32* %tmp9697, align 8
- br label %bb140
-
-bb140: ; preds = %cond_next127, %cond_next91, %cond_next57, %cond_next57
- switch i8 %tmp3435, label %cond_true202 [
- i8 6, label %cond_next208
- i8 9, label %cond_next208
- i8 7, label %cond_next208
- i8 8, label %cond_next208
- i8 10, label %cond_next208
- ]
-
-cond_true202: ; preds = %bb140
- tail call void (%struct.tree_node*, i8*, i32, i8*, ...)* @tree_check_failed( %struct.tree_node* %type, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1738, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0), i32 9, i32 6, i32 7, i32 8, i32 10, i32 0 )
- unreachable
-
-cond_next208: ; preds = %bb140, %bb140, %bb140, %bb140, %bb140
- %tmp213 = getelementptr %struct.tree_type* %tmp4950, i32 0, i32 14 ; <%struct.tree_node**> [#uses=1]
- %tmp214 = load %struct.tree_node** %tmp213, align 8 ; <%struct.tree_node*> [#uses=2]
- %tmp217 = getelementptr %struct.tree_node* %tmp214, i32 0, i32 0, i32 0, i32 3 ; <i8*> [#uses=1]
- %tmp217218 = bitcast i8* %tmp217 to i32* ; <i32*> [#uses=1]
- %tmp219 = load i32* %tmp217218, align 8 ; <i32> [#uses=1]
- %tmp221222 = trunc i32 %tmp219 to i8 ; <i8> [#uses=1]
- %tmp223 = icmp eq i8 %tmp221222, 24 ; <i1> [#uses=1]
- br i1 %tmp223, label %cond_true226, label %cond_next340
-
-cond_true226: ; preds = %cond_next208
- switch i8 %tmp3435, label %cond_true288 [
- i8 6, label %cond_next294
- i8 9, label %cond_next294
- i8 7, label %cond_next294
- i8 8, label %cond_next294
- i8 10, label %cond_next294
- ]
-
-cond_true288: ; preds = %cond_true226
- tail call void (%struct.tree_node*, i8*, i32, i8*, ...)* @tree_check_failed( %struct.tree_node* %type, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1739, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0), i32 9, i32 6, i32 7, i32 8, i32 10, i32 0 )
- unreachable
-
-cond_next294: ; preds = %cond_true226, %cond_true226, %cond_true226, %cond_true226, %cond_true226
- %tmp301 = tail call i32 @tree_int_cst_sgn( %struct.tree_node* %tmp214 ) ; <i32> [#uses=1]
- %tmp302 = icmp sgt i32 %tmp301, -1 ; <i1> [#uses=1]
- br i1 %tmp302, label %cond_true305, label %cond_next340
-
-cond_true305: ; preds = %cond_next294
- %tmp313 = load i32* %tmp3031, align 8 ; <i32> [#uses=2]
- %tmp315316 = trunc i32 %tmp313 to i8 ; <i8> [#uses=1]
- %tmp315316317318 = zext i8 %tmp315316 to i64 ; <i64> [#uses=1]
- %tmp319 = getelementptr [0 x i32]* @tree_code_type, i32 0, i64 %tmp315316317318 ; <i32*> [#uses=1]
- %tmp320 = load i32* %tmp319, align 4 ; <i32> [#uses=1]
- %tmp321 = icmp eq i32 %tmp320, 2 ; <i1> [#uses=1]
- br i1 %tmp321, label %cond_next327, label %cond_true324
-
-cond_true324: ; preds = %cond_true305
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1740, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next327: ; preds = %cond_true305
- %tmp338 = or i32 %tmp313, 8192 ; <i32> [#uses=1]
- store i32 %tmp338, i32* %tmp3031, align 8
- br label %cond_next340
-
-cond_next340: ; preds = %cond_next327, %cond_next294, %cond_next208
- %tmp348 = load i32* %tmp3031, align 8 ; <i32> [#uses=1]
- %tmp350351 = trunc i32 %tmp348 to i8 ; <i8> [#uses=1]
- %tmp350351352353 = zext i8 %tmp350351 to i64 ; <i64> [#uses=1]
- %tmp354 = getelementptr [0 x i32]* @tree_code_type, i32 0, i64 %tmp350351352353 ; <i32*> [#uses=1]
- %tmp355 = load i32* %tmp354, align 4 ; <i32> [#uses=1]
- %tmp356 = icmp eq i32 %tmp355, 2 ; <i1> [#uses=1]
- br i1 %tmp356, label %cond_next385, label %cond_true359
-
-cond_true359: ; preds = %cond_next340
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1742, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next385: ; preds = %cond_next340
- %tmp390 = getelementptr %struct.tree_node* %type, i32 0, i32 0, i32 8 ; <i8*> [#uses=1]
- %tmp390391 = bitcast i8* %tmp390 to i32* ; <i32*> [#uses=3]
- %tmp392 = load i32* %tmp390391, align 8 ; <i32> [#uses=1]
- %tmp394 = and i32 %tmp392, 511 ; <i32> [#uses=1]
- %tmp397 = tail call i32 @smallest_mode_for_size( i32 %tmp394, i32 2 ) ; <i32> [#uses=1]
- %tmp404 = load i32* %tmp390391, align 8 ; <i32> [#uses=1]
- %tmp397398405 = shl i32 %tmp397, 9 ; <i32> [#uses=1]
- %tmp407 = and i32 %tmp397398405, 65024 ; <i32> [#uses=1]
- %tmp408 = and i32 %tmp404, -65025 ; <i32> [#uses=1]
- %tmp409 = or i32 %tmp408, %tmp407 ; <i32> [#uses=2]
- store i32 %tmp409, i32* %tmp390391, align 8
- %tmp417 = load i32* %tmp3031, align 8 ; <i32> [#uses=1]
- %tmp419420 = trunc i32 %tmp417 to i8 ; <i8> [#uses=1]
- %tmp419420421422 = zext i8 %tmp419420 to i64 ; <i64> [#uses=1]
- %tmp423 = getelementptr [0 x i32]* @tree_code_type, i32 0, i64 %tmp419420421422 ; <i32*> [#uses=1]
- %tmp424 = load i32* %tmp423, align 4 ; <i32> [#uses=1]
- %tmp425 = icmp eq i32 %tmp424, 2 ; <i1> [#uses=1]
- br i1 %tmp425, label %cond_next454, label %cond_true428
-
-cond_true428: ; preds = %cond_next385
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1744, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next454: ; preds = %cond_next385
- lshr i32 %tmp409, 9 ; <i32>:0 [#uses=1]
- trunc i32 %0 to i8 ; <i8>:1 [#uses=1]
- %tmp463464 = and i8 %1, 127 ; <i8> [#uses=1]
- %tmp463464465466 = zext i8 %tmp463464 to i64 ; <i64> [#uses=1]
- %tmp467 = getelementptr [48 x i8]* @mode_size, i32 0, i64 %tmp463464465466 ; <i8*> [#uses=1]
- %tmp468 = load i8* %tmp467, align 1 ; <i8> [#uses=1]
- %tmp468469553 = zext i8 %tmp468 to i16 ; <i16> [#uses=1]
- %tmp470471 = shl i16 %tmp468469553, 3 ; <i16> [#uses=1]
- %tmp470471472 = zext i16 %tmp470471 to i64 ; <i64> [#uses=1]
- %tmp473 = tail call %struct.tree_node* @size_int_kind( i64 %tmp470471472, i32 2 ) ; <%struct.tree_node*> [#uses=1]
- store %struct.tree_node* %tmp473, %struct.tree_node** %tmp51, align 8
- ret void
-
-bb478: ; preds = %cond_next57
- br i1 %tmp40, label %cond_next500, label %cond_true497
-
-cond_true497: ; preds = %bb478
- tail call void @tree_class_check_failed( %struct.tree_node* %type, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1755, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next500: ; preds = %bb478
- %tmp506 = getelementptr %struct.tree_node* %type, i32 0, i32 0, i32 0, i32 1 ; <%struct.tree_node**> [#uses=1]
- %tmp507 = load %struct.tree_node** %tmp506, align 8 ; <%struct.tree_node*> [#uses=2]
- %tmp511 = getelementptr %struct.tree_node* %tmp507, i32 0, i32 0, i32 0, i32 3 ; <i8*> [#uses=1]
- %tmp511512 = bitcast i8* %tmp511 to i32* ; <i32*> [#uses=1]
- %tmp513 = load i32* %tmp511512, align 8 ; <i32> [#uses=2]
- %tmp515516 = trunc i32 %tmp513 to i8 ; <i8> [#uses=1]
- %tmp515516517518 = zext i8 %tmp515516 to i64 ; <i64> [#uses=1]
- %tmp519 = getelementptr [0 x i32]* @tree_code_type, i32 0, i64 %tmp515516517518 ; <i32*> [#uses=1]
- %tmp520 = load i32* %tmp519, align 4 ; <i32> [#uses=1]
- %tmp521 = icmp eq i32 %tmp520, 2 ; <i1> [#uses=1]
- br i1 %tmp521, label %cond_next527, label %cond_true524
-
-cond_true524: ; preds = %cond_next500
- tail call void @tree_class_check_failed( %struct.tree_node* %tmp507, i32 2, i8* getelementptr ([28 x i8]* @.str, i32 0, i64 0), i32 1755, i8* getelementptr ([12 x i8]* @__FUNCTION__.22683, i32 0, i32 0) )
- unreachable
-
-cond_next527: ; preds = %cond_next500
- %tmp545 = and i32 %tmp513, 8192 ; <i32> [#uses=1]
- %tmp547 = and i32 %tmp32, -8193 ; <i32> [#uses=1]
- %tmp548 = or i32 %tmp547, %tmp545 ; <i32> [#uses=1]
- store i32 %tmp548, i32* %tmp3031, align 8
- ret void
-
-UnifiedReturnBlock: ; preds = %cond_next57, %cond_next46, %cond_false
- ret void
-}
-
-declare void @fancy_abort(i8*, i32, i8*)
-
-declare void @tree_class_check_failed(%struct.tree_node*, i32, i8*, i32, i8*)
-
-declare i32 @smallest_mode_for_size(i32, i32)
-
-declare %struct.tree_node* @size_int_kind(i64, i32)
-
-declare void @tree_check_failed(%struct.tree_node*, i8*, i32, i8*, ...)
-
-declare i32 @tree_int_cst_sgn(%struct.tree_node*)
diff --git a/test/CodeGen/X86/2009-08-06-inlineasm.ll b/test/CodeGen/X86/2009-08-06-inlineasm.ll
index cc2f3d8..de32c21 100644
--- a/test/CodeGen/X86/2009-08-06-inlineasm.ll
+++ b/test/CodeGen/X86/2009-08-06-inlineasm.ll
@@ -1,8 +1,10 @@
-; RUN: llc < %s
+; RUN: llc -mtriple=i386-pc-linux-gnu < %s
; PR4668
-; ModuleID = '<stdin>'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
-target triple = "i386-pc-linux-gnu"
+; XFAIL: *
+; FIXME: If the coalescer happens to coalesce %level.1 with the copy to EAX
+; (for ret) then this will fail to compile. The fundamental problem is
+; once the coalescer fixes a virtual register to physical register we can't
+; evict it.
define i32 @x(i32 %qscale) nounwind {
entry:
diff --git a/test/CodeGen/X86/aliases.ll b/test/CodeGen/X86/aliases.ll
index 3020eb3..3ed3bd6 100644
--- a/test/CodeGen/X86/aliases.ll
+++ b/test/CodeGen/X86/aliases.ll
@@ -1,6 +1,6 @@
; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=false -o %t
-; RUN: grep { = } %t | count 7
-; RUN: grep set %t | count 16
+; RUN: grep { = } %t | count 16
+; RUN: grep set %t | count 18
; RUN: grep globl %t | count 6
; RUN: grep weak %t | count 1
; RUN: grep hidden %t | count 1
diff --git a/test/CodeGen/X86/machine-cse.ll b/test/CodeGen/X86/machine-cse.ll
new file mode 100644
index 0000000..a8afdc8
--- /dev/null
+++ b/test/CodeGen/X86/machine-cse.ll
@@ -0,0 +1,39 @@
+; RUN: llc -mtriple=x86_64-apple-darwin < %s | FileCheck %s
+; rdar://7610418
+
+%ptr = type { i8* }
+%struct.s1 = type { %ptr, %ptr }
+%struct.s2 = type { i32, i8*, i8*, [256 x %struct.s1*], [8 x i32], i64, i8*, i32, i64, i64, i32, %struct.s3*, %struct.s3*, [49 x i64] }
+%struct.s3 = type { %struct.s3*, %struct.s3*, i32, i32, i32 }
+
+define fastcc i8* @t(i64 %size) nounwind {
+entry:
+; CHECK: t:
+; CHECK: leaq (%rax,%rax,4)
+ %0 = zext i32 undef to i64
+ %1 = getelementptr inbounds %struct.s2* null, i64 %0
+ br i1 undef, label %bb1, label %bb2
+
+bb1:
+; CHECK: %bb1
+; CHECK-NOT: shlq $9
+; CHECK-NOT: leaq
+; CHECK: call
+ %2 = getelementptr inbounds %struct.s2* null, i64 %0, i32 0
+ call void @bar(i32* %2) nounwind
+ unreachable
+
+bb2:
+; CHECK: %bb2
+; CHECK-NOT: leaq
+; CHECK: callq
+ %3 = call fastcc i8* @foo(%struct.s2* %1) nounwind
+ unreachable
+
+bb3:
+ ret i8* undef
+}
+
+declare void @bar(i32*)
+
+declare fastcc i8* @foo(%struct.s2*) nounwind
diff --git a/test/CodeGen/X86/pre-split6.ll b/test/CodeGen/X86/pre-split6.ll
index d38e630..837e238 100644
--- a/test/CodeGen/X86/pre-split6.ll
+++ b/test/CodeGen/X86/pre-split6.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split | grep {divsd 8} | count 1
+; RUN: llc < %s -mtriple=i386-apple-darwin -mattr=+sse2 -pre-alloc-split | grep {divsd 24} | count 1
@current_surfaces.b = external global i1 ; <i1*> [#uses=1]
diff --git a/test/CodeGen/X86/tailcall2.ll b/test/CodeGen/X86/sibcall.ll
index 90315fd..90315fd 100644
--- a/test/CodeGen/X86/tailcall2.ll
+++ b/test/CodeGen/X86/sibcall.ll
diff --git a/test/CodeGen/X86/stack-color-with-reg.ll b/test/CodeGen/X86/stack-color-with-reg.ll
index 42e7a39..83f56c1 100644
--- a/test/CodeGen/X86/stack-color-with-reg.ll
+++ b/test/CodeGen/X86/stack-color-with-reg.ll
@@ -1,5 +1,6 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin10 -relocation-model=pic -disable-fp-elim -color-ss-with-regs -stats -info-output-file - > %t
-; RUN: grep stackcoloring %t | grep "stack slot refs replaced with reg refs" | grep 8
+; RUN: grep asm-printer %t | grep 156
+; RUN: grep stackcoloring %t | grep "stack slot refs replaced with reg refs" | grep 4
type { [62 x %struct.Bitvec*] } ; type %0
type { i8* } ; type %1
diff --git a/test/CodeGen/XCore/addsub64.ll b/test/CodeGen/XCore/addsub64.ll
index a1494ad..0432e5e 100644
--- a/test/CodeGen/XCore/addsub64.ll
+++ b/test/CodeGen/XCore/addsub64.ll
@@ -1,12 +1,44 @@
-; RUN: llc < %s -march=xcore -mcpu=xs1b-generic > %t1.s
-; RUN: grep ladd %t1.s | count 2
-; RUN: grep lsub %t1.s | count 2
+; RUN: llc < %s -march=xcore | FileCheck %s
define i64 @add64(i64 %a, i64 %b) {
%result = add i64 %a, %b
ret i64 %result
}
+; CHECK: add64
+; CHECK: ldc r11, 0
+; CHECK-NEXT: ladd r2, r0, r0, r2, r11
+; CHECK-NEXT: ladd r2, r1, r1, r3, r2
+; CHECK-NEXT: retsp 0
define i64 @sub64(i64 %a, i64 %b) {
%result = sub i64 %a, %b
ret i64 %result
}
+; CHECK: sub64
+; CHECK: ldc r11, 0
+; CHECK-NEXT: lsub r2, r0, r0, r2, r11
+; CHECK-NEXT: lsub r2, r1, r1, r3, r2
+; CHECK-NEXT: retsp 0
+
+define i64 @maccu(i64 %a, i32 %b, i32 %c) {
+entry:
+ %0 = zext i32 %b to i64
+ %1 = zext i32 %c to i64
+ %2 = mul i64 %1, %0
+ %3 = add i64 %2, %a
+ ret i64 %3
+}
+; CHECK: maccu:
+; CHECK: maccu r1, r0, r3, r2
+; CHECK-NEXT: retsp 0
+
+define i64 @maccs(i64 %a, i32 %b, i32 %c) {
+entry:
+ %0 = sext i32 %b to i64
+ %1 = sext i32 %c to i64
+ %2 = mul i64 %1, %0
+ %3 = add i64 %2, %a
+ ret i64 %3
+}
+; CHECK: maccs:
+; CHECK: maccs r1, r0, r3, r2
+; CHECK-NEXT: retsp 0
diff --git a/test/CodeGen/XCore/ladd_lsub_combine.ll b/test/CodeGen/XCore/ladd_lsub_combine.ll
new file mode 100644
index 0000000..a693ee2
--- /dev/null
+++ b/test/CodeGen/XCore/ladd_lsub_combine.ll
@@ -0,0 +1,67 @@
+; RUN: llvm-as < %s | llc -march=xcore | FileCheck %s
+
+; Only needs one ladd
+define i64 @f1(i32 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %x to i64 ; <i64> [#uses=1]
+ %1 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %2 = add i64 %1, %0 ; <i64> [#uses=1]
+ ret i64 %2
+}
+; CHECK: f1:
+; CHECK: ldc r2, 0
+; CHECK-NEXT: ladd r1, r0, r1, r0, r2
+; CHECK-NEXT: retsp 0
+
+; Only needs one lsub and one neg
+define i64 @f2(i32 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %x to i64 ; <i64> [#uses=1]
+ %1 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %2 = sub i64 %1, %0 ; <i64> [#uses=1]
+ ret i64 %2
+}
+; CHECK: f2:
+; CHECK: ldc r2, 0
+; CHECK-NEXT: lsub r1, r0, r1, r0, r2
+; CHECK-NEXT: neg r1, r1
+; CHECK-NEXT: retsp 0
+
+; Should compile to one ladd and one add
+define i64 @f3(i64 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %1 = add i64 %x, %0 ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f3:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: ladd r2, r0, r0, r2, r3
+; CHECK-NEXT: add r1, r1, r2
+; CHECK-NEXT: retsp 0
+
+; Should compile to one ladd and one add
+define i64 @f4(i32 %x, i64 %y) nounwind {
+entry:
+ %0 = zext i32 %x to i64 ; <i64> [#uses=1]
+ %1 = add i64 %0, %y ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f4:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: ladd r1, r0, r0, r1, r3
+; CHECK-NEXT: add r1, r2, r1
+; CHECK-NEXT: retsp 0
+
+; Should compile to one lsub and one sub
+define i64 @f5(i64 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %1 = sub i64 %x, %0 ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f5:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: lsub r2, r0, r0, r2, r3
+; CHECK-NEXT: sub r1, r1, r2
+; CHECK-NEXT: retsp 0
diff --git a/test/CodeGen/XCore/mul64.ll b/test/CodeGen/XCore/mul64.ll
new file mode 100644
index 0000000..329e214
--- /dev/null
+++ b/test/CodeGen/XCore/mul64.ll
@@ -0,0 +1,39 @@
+; RUN: llc < %s -march=xcore | FileCheck %s
+define i64 @umul_lohi(i32 %a, i32 %b) {
+entry:
+ %0 = zext i32 %a to i64
+ %1 = zext i32 %b to i64
+ %2 = mul i64 %1, %0
+ ret i64 %2
+}
+; CHECK: umul_lohi:
+; CHECK: ldc r2, 0
+; CHECK-NEXT: lmul r1, r0, r1, r0, r2, r2
+; CHECK-NEXT: retsp 0
+
+define i64 @smul_lohi(i32 %a, i32 %b) {
+entry:
+ %0 = sext i32 %a to i64
+ %1 = sext i32 %b to i64
+ %2 = mul i64 %1, %0
+ ret i64 %2
+}
+; CHECK: smul_lohi:
+; CHECK: ldc r2, 0
+; CHECK-NEXT: mov r3, r2
+; CHECK-NEXT: maccs r2, r3, r1, r0
+; CHECK-NEXT: mov r0, r3
+; CHECK-NEXT: mov r1, r2
+; CHECK-NEXT: retsp 0
+
+define i64 @mul64(i64 %a, i64 %b) {
+entry:
+ %0 = mul i64 %a, %b
+ ret i64 %0
+}
+; CHECK: mul64:
+; CHECK: ldc r11, 0
+; CHECK-NEXT: lmul r11, r4, r0, r2, r11, r11
+; CHECK-NEXT: mul r0, r0, r3
+; CHECK-NEXT: lmul r0, r1, r1, r2, r11, r0
+; CHECK-NEXT: mov r0, r4
diff --git a/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp b/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp
index 4c8e0e5..2a9f1f1 100644
--- a/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp
+++ b/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp
@@ -1,4 +1,4 @@
-// RUN: %llvmgcc -g -S %s -o - | grep DW_TAG_pointer_type | grep "i32 458767, metadata .., metadata ..., metadata .., i32 ., i64 .., i64 .., i64 0, i32 64, metadata ..."
+// RUN: %llvmgcc -g -S %s -o - | grep DW_TAG_pointer_type | grep "i32 524303, metadata .., metadata ..., metadata .., i32 ., i64 .., i64 .., i64 0, i32 64, metadata ..."
// Here, second to last argument "i32 64" indicates that artificial type is set.
// Test to artificial attribute attahed to "this" pointer type.
// Radar 7655792 and 7655002
diff --git a/test/MC/AsmParser/X86/x86_32-new-encoder.s b/test/MC/AsmParser/X86/x86_32-new-encoder.s
index 6fd0cbb..d4e3be4 100644
--- a/test/MC/AsmParser/X86/x86_32-new-encoder.s
+++ b/test/MC/AsmParser/X86/x86_32-new-encoder.s
@@ -38,4 +38,12 @@ rdtscp
movl %eax, 16(%ebp)
// CHECK: movl %eax, -16(%ebp) # encoding: [0x89,0x45,0xf0]
movl %eax, -16(%ebp)
-
+
+// CHECK: testb %bl, %cl # encoding: [0x84,0xcb]
+ testb %bl, %cl
+
+// CHECK: cmpl %eax, %ebx # encoding: [0x39,0xc3]
+ cmpl %eax, %ebx
+
+// CHECK: addw %ax, %ax # encoding: [0x66,0x01,0xc0]
+ addw %ax, %ax
diff --git a/test/MC/Disassembler/simple-tests.txt b/test/MC/Disassembler/simple-tests.txt
index 11c077d..b6bb35d 100644
--- a/test/MC/Disassembler/simple-tests.txt
+++ b/test/MC/Disassembler/simple-tests.txt
@@ -41,4 +41,13 @@
0x0f 0x01 0xf8
# CHECK: rdtscp
-0x0f 0x01 0xf9 \ No newline at end of file
+0x0f 0x01 0xf9
+
+# CHECK: vmxon
+0xf3 0x0f 0xc7 0x30
+
+# CHECK: vmptrld
+0x0f 0xc7 0x30
+
+# CHECK: vmptrst
+0x0f 0xc7 0x38
diff --git a/test/MC/MachO/reloc-diff.s b/test/MC/MachO/reloc-diff.s
new file mode 100644
index 0000000..601edba
--- /dev/null
+++ b/test/MC/MachO/reloc-diff.s
@@ -0,0 +1,55 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+// CHECK: # Relocation 0
+// CHECK: (('word-0', 0xa2000014),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 1
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 2
+// CHECK: (('word-0', 0xa4000010),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 3
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 4
+// CHECK: (('word-0', 0xa400000c),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 5
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 6
+// CHECK: (('word-0', 0xa4000008),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 7
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 8
+// CHECK: (('word-0', 0xa4000004),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 9
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 10
+// CHECK: (('word-0', 0xa2000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK: # Relocation 11
+// CHECK: (('word-0', 0xa1000000),
+// CHECK: ('word-1', 0x0)),
+// CHECK-NEXT: ])
+
+_local_def:
+ .globl _external_def
+_external_def:
+Ltemp:
+ ret
+
+ .data
+ .long _external_def - _local_def
+ .long Ltemp - _local_def
+
+ .long _local_def - _external_def
+ .long Ltemp - _external_def
+
+ .long _local_def - Ltemp
+ .long _external_def - Ltemp
diff --git a/test/MC/MachO/reloc-pcrel.s b/test/MC/MachO/reloc-pcrel.s
new file mode 100644
index 0000000..fff7cc0
--- /dev/null
+++ b/test/MC/MachO/reloc-pcrel.s
@@ -0,0 +1,62 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+// CHECK: # Relocation 0
+// CHECK: (('word-0', 0xe4000045),
+// CHECK: ('word-1', 0x4)),
+// CHECK: # Relocation 1
+// CHECK: (('word-0', 0xe1000000),
+// CHECK: ('word-1', 0x6)),
+// CHECK: # Relocation 2
+// CHECK: (('word-0', 0x40),
+// CHECK: ('word-1', 0xd000002)),
+// CHECK: # Relocation 3
+// CHECK: (('word-0', 0x3b),
+// CHECK: ('word-1', 0xd000002)),
+// CHECK: # Relocation 4
+// CHECK: (('word-0', 0x36),
+// CHECK: ('word-1', 0xd000002)),
+// CHECK: # Relocation 5
+// CHECK: (('word-0', 0xe0000031),
+// CHECK: ('word-1', 0x4)),
+// CHECK: # Relocation 6
+// CHECK: (('word-0', 0xe000002c),
+// CHECK: ('word-1', 0x4)),
+// CHECK: # Relocation 7
+// CHECK: (('word-0', 0x27),
+// CHECK: ('word-1', 0x5000001)),
+// CHECK: # Relocation 8
+// CHECK: (('word-0', 0xe0000022),
+// CHECK: ('word-1', 0x2)),
+// CHECK: # Relocation 9
+// CHECK: (('word-0', 0xe000001d),
+// CHECK: ('word-1', 0x2)),
+// CHECK: # Relocation 10
+// CHECK: (('word-0', 0x18),
+// CHECK: ('word-1', 0x5000001)),
+// CHECK-NEXT: ])
+
+ xorl %eax,%eax
+
+ .globl _a
+_a:
+ xorl %eax,%eax
+_b:
+ xorl %eax,%eax
+L0:
+ xorl %eax,%eax
+L1:
+
+ call L0
+ call L0 - 1
+ call L0 + 1
+ call _a
+ call _a - 1
+ call _a + 1
+ call _b
+ call _b - 1
+ call _b + 1
+ call _c
+ call _c - 1
+ call _c + 1
+// call _a - L0
+ call _b - L0
diff --git a/test/MC/MachO/zerofill-4.s b/test/MC/MachO/zerofill-4.s
new file mode 100644
index 0000000..d9c987c
--- /dev/null
+++ b/test/MC/MachO/zerofill-4.s
@@ -0,0 +1,35 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+.zerofill __DATA,__bss,_fill0,1,0
+.zerofill __DATA,__bss,_a,4,2
+.zerofill __DATA,__bss,_fill1,1,0
+.zerofill __DATA,__bss,_b,4,3
+.zerofill __DATA,__bss,_fill2,1,0
+.zerofill __DATA,__bss,_c,4,4
+.zerofill __DATA,__bss,_fill3,1,0
+.zerofill __DATA,__bss,_d,4,5
+
+// CHECK: # Symbol 0
+// CHECK: ('n_value', 0)
+// CHECK: ('_string', '_fill0')
+// CHECK: # Symbol 1
+// CHECK: ('n_value', 4)
+// CHECK: ('_string', '_a')
+// CHECK: # Symbol 2
+// CHECK: ('n_value', 8)
+// CHECK: ('_string', '_fill1')
+// CHECK: # Symbol 3
+// CHECK: ('n_value', 16)
+// CHECK: ('_string', '_b')
+// CHECK: # Symbol 4
+// CHECK: ('n_value', 20)
+// CHECK: ('_string', '_fill2')
+// CHECK: # Symbol 5
+// CHECK: ('n_value', 32)
+// CHECK: ('_string', '_c')
+// CHECK: # Symbol 6
+// CHECK: ('n_value', 36)
+// CHECK: ('_string', '_fill3')
+// CHECK: # Symbol 7
+// CHECK: ('n_value', 64)
+// CHECK: ('_string', '_d')
diff --git a/test/MC/MachO/zerofill-sect-align.s b/test/MC/MachO/zerofill-sect-align.s
new file mode 100644
index 0000000..5d7730f
--- /dev/null
+++ b/test/MC/MachO/zerofill-sect-align.s
@@ -0,0 +1,15 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+//
+// Check that the section itself is aligned.
+
+ .byte 0
+
+.zerofill __DATA,__bss,_a,1,0
+.zerofill __DATA,__bss,_b,4,4
+
+// CHECK: # Symbol 0
+// CHECK: ('n_value', 16)
+// CHECK: ('_string', '_a')
+// CHECK: # Symbol 1
+// CHECK: ('n_value', 32)
+// CHECK: ('_string', '_b')
diff --git a/test/Transforms/SimplifyLibCalls/memset_chk.ll b/test/Transforms/InstCombine/memset_chk.ll
index c4ef60e..5a4e6d9 100644
--- a/test/Transforms/SimplifyLibCalls/memset_chk.ll
+++ b/test/Transforms/InstCombine/memset_chk.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
+; RUN: opt < %s -instcombine -S | FileCheck %s
; rdar://7719085
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll
index bf1a37f..cd7b7c8 100644
--- a/test/Transforms/InstCombine/objsize.ll
+++ b/test/Transforms/InstCombine/objsize.ll
@@ -91,7 +91,7 @@ bb11:
%1 = bitcast float* %0 to i8* ; <i8*> [#uses=1]
%2 = call i32 @llvm.objectsize.i32(i8* %1, i1 false) ; <i32> [#uses=1]
%3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; <i8*> [#uses=0]
-; CHECK: @__memcpy_chk
+; CHECK: unreachable
unreachable
bb12:
@@ -113,13 +113,29 @@ entry:
%1 = bitcast %struct.data* %0 to i8*
%2 = call i64 @llvm.objectsize.i64(i8* %1, i1 false) nounwind
; CHECK-NOT: @llvm.objectsize
-; CHECK: @__memset_chk(i8* %1, i32 0, i64 1824, i64 1824)
+; CHECK: @llvm.memset.i64(i8* %1, i8 0, i64 1824, i32 8)
%3 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 %2) nounwind
ret i32 0
}
+@s = external global i8*
+
+define void @test5(i32 %n) nounwind ssp {
+; CHECK: @test5
+entry:
+ %0 = tail call noalias i8* @malloc(i32 20) nounwind
+ %1 = tail call i32 @llvm.objectsize.i32(i8* %0, i1 false)
+ %2 = load i8** @s, align 8
+; CHECK-NOT: @llvm.objectsize
+; CHECK: @__memcpy_chk(i8* %0, i8* %1, i32 10, i32 20)
+ %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 10, i32 %1) nounwind
+ ret void
+}
+
declare i8* @__memset_chk(i8*, i32, i64, i64) nounwind
+declare noalias i8* @malloc(i32) nounwind
+
declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly
declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly
diff --git a/test/Transforms/SimplifyLibCalls/strcpy_chk.ll b/test/Transforms/InstCombine/strcpy_chk.ll
index 422cbd9..a20a13c 100644
--- a/test/Transforms/SimplifyLibCalls/strcpy_chk.ll
+++ b/test/Transforms/InstCombine/strcpy_chk.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
+; RUN: opt < %s -instcombine -S | FileCheck %s
@a = common global [60 x i8] zeroinitializer, align 1 ; <[60 x i8]*> [#uses=1]
@.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*> [#uses=1]
diff --git a/test/Transforms/LCSSA/unreachable-use.ll b/test/Transforms/LCSSA/unreachable-use.ll
new file mode 100644
index 0000000..c389c9c
--- /dev/null
+++ b/test/Transforms/LCSSA/unreachable-use.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -lcssa -S -verify-loop-info | grep {\[%\]tmp33 = load i1\\*\\* \[%\]tmp}
+; PR6546
+
+; LCSSA doesn't need to transform uses in blocks not reachable
+; from the entry block.
+
+define fastcc void @dfs() nounwind {
+bb:
+ br label %bb44
+
+bb44:
+ br i1 undef, label %bb7, label %bb45
+
+bb7:
+ %tmp = bitcast i1** undef to i1**
+ br label %bb15
+
+bb15:
+ br label %bb44
+
+bb32:
+ %tmp33 = load i1** %tmp, align 8
+ br label %bb45
+
+bb45:
+ unreachable
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index b4aec5a..929871a 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -144,9 +144,6 @@ bindings = set(site_exp['llvm_bindings'].split(','))
def llvm_supports_binding(name):
return name in bindings
-config.conditions["TARGET"] = llvm_supports_target
-config.conditions["BINDING"] = llvm_supports_binding
-
# Provide on_clone hook for reading 'dg.exp'.
import os
simpleLibData = re.compile(r"""load_lib llvm.exp
diff --git a/tools/Makefile b/tools/Makefile
index 86ba72d..5813057 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -42,8 +42,7 @@ ifeq ($(ENABLE_PIC),1)
# gold only builds if binutils is around. It requires "lto" to build before
# it so it is added to DIRS.
ifdef BINUTILS_INCDIR
- PARALLEL_DIRS += gold
- DIRS += lto
+ DIRS += lto gold
else
PARALLEL_DIRS += lto
endif
diff --git a/unittests/Makefile.unittest b/unittests/Makefile.unittest
index b1c1d2c..8fbcfd2 100644
--- a/unittests/Makefile.unittest
+++ b/unittests/Makefile.unittest
@@ -14,18 +14,20 @@
# Set up variables for building a unit test.
ifdef TESTNAME
-CPP.Flags += -DGTEST_HAS_RTTI=0
-# gcc's TR1 <tuple> header depends on RTTI, so force googletest to use
-# its own tuple implementation. When we import googletest >=1.4.0, we
-# can drop this line.
-CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0
-
include $(LEVEL)/Makefile.common
LLVMUnitTestExe = $(BuildMode)/$(TESTNAME)Tests$(EXEEXT)
-CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/
-CPP.Flags += $(NO_VARIADIC_MACROS)
+# Note that these flags are duplicated when building GoogleTest itself in
+# utils/unittest/googletest/Makefile; ensure that any changes are made to both.
+CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
+CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+# When we import googletest >=1.4.0, we can drop this line.
+CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0
+
TESTLIBS = -lGoogleTest -lUnitTestMain
ifeq ($(ENABLE_SHARED), 1)
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index ce737bf..e793333 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1238,6 +1238,14 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
std::vector<std::pair<Init*, std::string> >()));
return ParseTreePattern(Dag);
}
+
+ // Input argument?
+ if (R->getName() == "node") {
+ if (Dag->getArgName(0).empty())
+ error("'node' argument requires a name to match with operand list");
+ Args.push_back(Dag->getArgName(0));
+ }
+
New = new TreePatternNode(DI);
} else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
New = ParseTreePattern(DI);
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index c4f1cbf..22d2fe8 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -29,6 +29,54 @@ void Matcher::printOne(raw_ostream &OS) const {
printImpl(OS, 0);
}
+/// unlinkNode - Unlink the specified node from this chain. If Other == this,
+/// we unlink the next pointer and return it. Otherwise we unlink Other from
+/// the list and return this.
+Matcher *Matcher::unlinkNode(Matcher *Other) {
+ if (this == Other)
+ return takeNext();
+
+ // Scan until we find the predecessor of Other.
+ Matcher *Cur = this;
+ for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
+ /*empty*/;
+
+ if (Cur == 0) return 0;
+ Cur->takeNext();
+ Cur->setNext(Other->takeNext());
+ return this;
+}
+
+/// canMoveBefore - Return true if this matcher is the same as Other, or if
+/// we can move this matcher past all of the nodes in-between Other and this
+/// node. Other must be equal to or before this.
+bool Matcher::canMoveBefore(const Matcher *Other) const {
+ for (;; Other = Other->getNext()) {
+ assert(Other && "Other didn't come before 'this'?");
+ if (this == Other) return true;
+
+ // We have to be able to move this node across the Other node.
+ if (!canMoveBeforeNode(Other))
+ return false;
+ }
+}
+
+/// canMoveBefore - Return true if it is safe to move the current matcher
+/// across the specified one.
+bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
+ // We can move simple predicates before record nodes.
+ if (isSimplePredicateNode())
+ return Other->isSimplePredicateOrRecordNode();
+
+ // We can move record nodes across simple predicates.
+ if (isSimplePredicateOrRecordNode())
+ return isSimplePredicateNode();
+
+ // We can't move record nodes across each other etc.
+ return false;
+}
+
+
ScopeMatcher::~ScopeMatcher() {
for (unsigned i = 0, e = Children.size(); i != e; ++i)
delete Children[i];
@@ -345,3 +393,10 @@ bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
return CIM->getValue() != getValue();
return false;
}
+
+bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))
+ return CVT->getTypeName() != getTypeName();
+ return false;
+}
+
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index 7955c7e..ef7ecf4 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -113,6 +113,49 @@ public:
return false;
}
+ /// isSimplePredicateNode - Return true if this is a simple predicate that
+ /// operates on the node or its children without potential side effects or a
+ /// change of the current node.
+ bool isSimplePredicateNode() const {
+ switch (getKind()) {
+ default: return false;
+ case CheckSame:
+ case CheckPatternPredicate:
+ case CheckPredicate:
+ case CheckOpcode:
+ case CheckType:
+ case CheckChildType:
+ case CheckInteger:
+ case CheckCondCode:
+ case CheckValueType:
+ case CheckAndImm:
+ case CheckOrImm:
+ case CheckFoldableChainNode:
+ return true;
+ }
+ }
+
+ /// isSimplePredicateOrRecordNode - Return true if this is a record node or
+ /// a simple predicate.
+ bool isSimplePredicateOrRecordNode() const {
+ return isSimplePredicateNode() ||
+ getKind() == RecordNode || getKind() == RecordChild;
+ }
+
+ /// unlinkNode - Unlink the specified node from this chain. If Other == this,
+ /// we unlink the next pointer and return it. Otherwise we unlink Other from
+ /// the list and return this.
+ Matcher *unlinkNode(Matcher *Other);
+
+ /// canMoveBefore - Return true if this matcher is the same as Other, or if
+ /// we can move this matcher past all of the nodes in-between Other and this
+ /// node. Other must be equal to or before this.
+ bool canMoveBefore(const Matcher *Other) const;
+
+ /// canMoveBefore - Return true if it is safe to move the current matcher
+ /// across the specified one.
+ bool canMoveBeforeNode(const Matcher *Other) const;
+
/// isContradictory - Return true of these two matchers could never match on
/// the same node.
bool isContradictory(const Matcher *Other) const {
@@ -601,6 +644,7 @@ private:
return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
}
virtual unsigned getHashImpl() const;
+ bool isContradictoryImpl(const Matcher *M) const;
};
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 5488853..4951a42 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -201,10 +201,6 @@ void MatcherGen::AddMatcher(Matcher *NewNode) {
void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
assert(N->isLeaf() && "Not a leaf?");
- // If there are node predicates for this node, generate their checks.
- for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
- AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
-
// Direct match against an integer constant.
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
// If this is the root of the dag we're matching, we emit a redundant opcode
@@ -310,11 +306,6 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
// Check that the current opcode lines up.
AddMatcher(new CheckOpcodeMatcher(CInfo));
- // If there are node predicates for this node, generate their checks.
- for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
- AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
-
-
// If this node has memory references (i.e. is a load or store), tell the
// interpreter to capture them in the memref array.
if (N->NodeHasProperty(SDNPMemOperand, CGP))
@@ -447,9 +438,12 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N,
else
EmitOperatorMatchCode(N, NodeNoTypes);
+ // If there are node predicates for this node, generate their checks.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
+
if (NodeType != EEVT::isUnknown)
AddMatcher(new CheckTypeMatcher((MVT::SimpleValueType)NodeType));
-
}
/// EmitMatcherCode - Generate the code that matches the predicate of this
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index dc077a9..910c4c5 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -220,6 +220,17 @@ static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) {
N->setNext(CPPM);
}
+/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
+/// specified kind. Return null if we didn't find one otherwise return the
+/// matcher.
+static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
+ for (; M; M = M->getNext())
+ if (M->getKind() == Kind)
+ return M;
+ return 0;
+}
+
+
/// FactorNodes - Turn matches like this:
/// Scope
/// OPC_CheckType i32
@@ -287,19 +298,46 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
// we can merge anything else into this matching group.
unsigned Scan = OptionIdx;
while (1) {
- while (Scan != e && Optn->isContradictory(OptionsToMatch[Scan]))
- ++Scan;
+ // If we ran out of stuff to scan, we're done.
+ if (Scan == e) break;
+
+ Matcher *ScanMatcher = OptionsToMatch[Scan];
- // Ok, we found something that isn't known to be contradictory. If it is
- // equal, we can merge it into the set of nodes to factor, if not, we have
- // to cease factoring.
- if (Scan == e || !Optn->isEqual(OptionsToMatch[Scan])) break;
+ // If we found an entry that matches out matcher, merge it into the set to
+ // handle.
+ if (Optn->isEqual(ScanMatcher)) {
+ // If is equal after all, add the option to EqualMatchers and remove it
+ // from OptionsToMatch.
+ EqualMatchers.push_back(ScanMatcher);
+ OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
+ --e;
+ continue;
+ }
+
+ // If the option we're checking for contradicts the start of the list,
+ // skip over it.
+ if (Optn->isContradictory(ScanMatcher)) {
+ ++Scan;
+ continue;
+ }
- // If is equal after all, add the option to EqualMatchers and remove it
- // from OptionsToMatch.
- EqualMatchers.push_back(OptionsToMatch[Scan]);
- OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
- --e;
+ // If we're scanning for a simple node, see if it occurs later in the
+ // sequence. If so, and if we can move it up, it might be contradictory
+ // or the same as what we're looking for. If so, reorder it.
+ if (Optn->isSimplePredicateOrRecordNode()) {
+ Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
+ if (M2 != 0 && M2 != ScanMatcher &&
+ M2->canMoveBefore(ScanMatcher) &&
+ (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
+ Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
+ M2->setNext(MatcherWithoutM2);
+ OptionsToMatch[Scan] = M2;
+ continue;
+ }
+ }
+
+ // Otherwise, we don't know how to handle this entry, we have to bail.
+ break;
}
if (Scan != e &&
@@ -363,9 +401,11 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
// we can convert this Scope to be a OpcodeSwitch instead.
bool AllOpcodeChecks = true, AllTypeChecks = true;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
- if (!isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
+ // Check to see if this breaks a series of CheckOpcodeMatchers.
+ if (AllOpcodeChecks &&
+ !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
#if 0
- if (i > 3 && AllOpcodeChecks) {
+ if (i > 3) {
errs() << "FAILING OPC #" << i << "\n";
NewOptionsToMatch[i]->dump();
}
@@ -373,20 +413,28 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
AllOpcodeChecks = false;
}
- if (!isa<CheckTypeMatcher>(NewOptionsToMatch[i]) ||
- // iPTR checks could alias any other case without us knowing, don't
- // bother with them.
- cast<CheckTypeMatcher>(NewOptionsToMatch[i])->getType() == MVT::iPTR) {
+ // Check to see if this breaks a series of CheckTypeMatcher's.
+ if (AllTypeChecks) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ if (CTM == 0 ||
+ // iPTR checks could alias any other case without us knowing, don't
+ // bother with them.
+ CTM->getType() == MVT::iPTR ||
+ // If the CheckType isn't at the start of the list, see if we can move
+ // it there.
+ !CTM->canMoveBefore(NewOptionsToMatch[i])) {
#if 0
- if (i > 3 && AllTypeChecks) {
- errs() << "FAILING TYPE #" << i << "\n";
- NewOptionsToMatch[i]->dump();
- }
+ if (i > 3 && AllTypeChecks) {
+ errs() << "FAILING TYPE #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
#endif
- AllTypeChecks = false;
+ AllTypeChecks = false;
+ }
}
}
- // TODO: Can also do CheckChildNType.
// If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
if (AllOpcodeChecks) {
@@ -405,16 +453,42 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
// If all the options are CheckType's, we can form the SwitchType, woot.
if (AllTypeChecks) {
- DenseSet<unsigned> Types;
+ DenseMap<unsigned, unsigned> TypeEntry;
SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
- CheckTypeMatcher *CTM = cast<CheckTypeMatcher>(NewOptionsToMatch[i]);
- assert(Types.insert(CTM->getType()).second &&
- "Duplicate types not factored?");
- Cases.push_back(std::make_pair(CTM->getType(), CTM->getNext()));
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
+ MVT::SimpleValueType CTMTy = CTM->getType();
+ delete CTM;
+
+ unsigned &Entry = TypeEntry[CTMTy];
+ if (Entry != 0) {
+ // If we have unfactored duplicate types, then we should factor them.
+ Matcher *PrevMatcher = Cases[Entry-1].second;
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
+ SM->setNumChildren(SM->getNumChildren()+1);
+ SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);
+ continue;
+ }
+
+ Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
+ Cases[Entry-1].second = new ScopeMatcher(Entries, 2);
+ continue;
+ }
+
+ Entry = Cases.size()+1;
+ Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
}
- MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size()));
+ if (Cases.size() != 1) {
+ MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size()));
+ } else {
+ // If we factored and ended up with one case, create it now.
+ MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first));
+ MatcherPtr->setNext(Cases[0].second);
+ }
return;
}
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index a7de2b7..20fbc6c 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -353,8 +353,6 @@ def isExpectedFail(xfails, xtargets, target_triple):
return True
-import re
-
def parseIntegratedTestScript(test):
"""parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
@@ -387,21 +385,7 @@ def parseIntegratedTestScript(test):
script = []
xfails = []
xtargets = []
- ignoredAny = False
for ln in open(sourcepath):
- conditional = re.search('IF\((.+?)\((.+?)\)\):', ln)
- if conditional:
- ln = ln[conditional.end():]
- condition = conditional.group(1)
- value = conditional.group(2)
-
- # Actually test the condition.
- if condition not in test.config.conditions:
- return (Test.UNRESOLVED, "unknown condition '"+condition+"'")
- if not test.config.conditions[condition](value):
- ignoredAny = True
- continue
-
if 'RUN:' in ln:
# Isolate the command to run.
index = ln.index('RUN:')
@@ -438,8 +422,6 @@ def parseIntegratedTestScript(test):
# Verify the script contains a run line.
if not script:
- if ignoredAny:
- return (Test.UNSUPPORTED, "Test has only ignored run lines")
return (Test.UNRESOLVED, "Test has no run line!")
if script[-1][-1] == '\\':
diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py
index d6f2a4d..dd905ef 100644
--- a/utils/lit/lit/TestingConfig.py
+++ b/utils/lit/lit/TestingConfig.py
@@ -28,8 +28,7 @@ class TestingConfig:
on_clone = None,
test_exec_root = None,
test_source_root = None,
- excludes = [],
- conditions = {})
+ excludes = [])
if os.path.exists(path):
# FIXME: Improve detection and error reporting of errors in the
@@ -55,7 +54,7 @@ class TestingConfig:
def __init__(self, parent, name, suffixes, test_format,
environment, substitutions, unsupported, on_clone,
- test_exec_root, test_source_root, excludes, conditions):
+ test_exec_root, test_source_root, excludes):
self.parent = parent
self.name = str(name)
self.suffixes = set(suffixes)
@@ -67,7 +66,6 @@ class TestingConfig:
self.test_exec_root = test_exec_root
self.test_source_root = test_source_root
self.excludes = set(excludes)
- self.conditions = dict(conditions)
def clone(self, path):
# FIXME: Chain implementations?
@@ -77,7 +75,7 @@ class TestingConfig:
self.environment, self.substitutions,
self.unsupported, self.on_clone,
self.test_exec_root, self.test_source_root,
- self.excludes, self.conditions)
+ self.excludes)
if cfg.on_clone:
cfg.on_clone(self, cfg, path)
return cfg
diff --git a/utils/unittest/UnitTestMain/Makefile b/utils/unittest/UnitTestMain/Makefile
index 328d5e2..5c10049 100644
--- a/utils/unittest/UnitTestMain/Makefile
+++ b/utils/unittest/UnitTestMain/Makefile
@@ -14,7 +14,13 @@ include $(LEVEL)/Makefile.config
LIBRARYNAME = UnitTestMain
BUILD_ARCHIVE = 1
REQUIRES_RTTI = 1
+
CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+# When we import googletest >=1.4.0, we can drop this line.
+CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0
include $(LEVEL)/Makefile.common
diff --git a/utils/unittest/googletest/Makefile b/utils/unittest/googletest/Makefile
index 15bbf4e..1ec979d 100644
--- a/utils/unittest/googletest/Makefile
+++ b/utils/unittest/googletest/Makefile
@@ -14,8 +14,18 @@ include $(LEVEL)/Makefile.config
LIBRARYNAME = GoogleTest
BUILD_ARCHIVE = 1
REQUIRES_RTTI = 1
+
+# Note that these flags are duplicated when building individual tests in
+# unittests/Makefile.unittest and ../UnitTestMain/Makefile; ensure that any
+# changes are made to both.
CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+# When we import googletest >=1.4.0, we can drop this line.
+CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0
+
ifeq ($(HOST_OS),MingW)
CPP.Flags += -DGTEST_OS_WINDOWS=1
OpenPOWER on IntegriCloud