summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-01-23 11:09:33 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-01-23 11:09:33 +0000
commit3fd58f91dd318518f7daa4ba64c0aaf31799d89b (patch)
tree74eecbae571601ec6a626a53374b1eddc7b164a5 /lib
parent3fba7d16b41dfbefe3b1be6bc0ab94c017728f79 (diff)
downloadFreeBSD-src-3fd58f91dd318518f7daa4ba64c0aaf31799d89b.zip
FreeBSD-src-3fd58f91dd318518f7daa4ba64c0aaf31799d89b.tar.gz
Update LLVM to r94309.
Diffstat (limited to 'lib')
-rw-r--r--lib/Analysis/AliasAnalysisCounter.cpp14
-rw-r--r--lib/Analysis/AliasDebugger.cpp10
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp20
-rw-r--r--lib/Analysis/DebugInfo.cpp60
-rw-r--r--lib/Analysis/DomPrinter.cpp74
-rw-r--r--lib/Analysis/IPA/Andersens.cpp10
-rw-r--r--lib/Analysis/IPA/CallGraph.cpp12
-rw-r--r--lib/Analysis/IPA/CallGraphSCCPass.cpp57
-rw-r--r--lib/Analysis/IPA/GlobalsModRef.cpp10
-rw-r--r--lib/Analysis/IPA/Makefile2
-rw-r--r--lib/Analysis/IVUsers.cpp19
-rw-r--r--lib/Analysis/LoopPass.cpp45
-rw-r--r--lib/Analysis/Makefile1
-rw-r--r--lib/Analysis/ProfileEstimatorPass.cpp10
-rw-r--r--lib/Analysis/ProfileInfo.cpp14
-rw-r--r--lib/Analysis/ProfileInfoLoaderPass.cpp10
-rw-r--r--lib/Analysis/ScalarEvolution.cpp212
-rw-r--r--lib/Analysis/ScalarEvolutionAliasAnalysis.cpp10
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp238
-rw-r--r--lib/Archive/Makefile1
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp1
-rw-r--r--lib/AsmParser/LLParser.h1
-rw-r--r--lib/AsmParser/LLToken.h1
-rw-r--r--lib/AsmParser/Makefile1
-rw-r--r--lib/AsmParser/Parser.cpp3
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp2
-rw-r--r--lib/Bitcode/Reader/Makefile1
-rw-r--r--lib/Bitcode/Writer/Makefile1
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp9
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.h2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp1452
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp70
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h29
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp387
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h18
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp191
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h10
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.cpp214
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.h266
-rw-r--r--lib/CodeGen/AsmPrinter/Makefile5
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp13
-rw-r--r--lib/CodeGen/CMakeLists.txt2
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp13
-rw-r--r--lib/CodeGen/ELFWriter.cpp18
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp25
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp12
-rw-r--r--lib/CodeGen/MachO.h412
-rw-r--r--lib/CodeGen/MachOCodeEmitter.cpp193
-rw-r--r--lib/CodeGen/MachOCodeEmitter.h69
-rw-r--r--lib/CodeGen/MachOWriter.cpp785
-rw-r--r--lib/CodeGen/MachOWriter.h192
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp21
-rw-r--r--lib/CodeGen/MachineFunction.cpp7
-rw-r--r--lib/CodeGen/MachineInstr.cpp17
-rw-r--r--lib/CodeGen/Makefile1
-rw-r--r--lib/CodeGen/MaxStackAlignment.cpp70
-rw-r--r--lib/CodeGen/OptimizeExts.cpp12
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp23
-rw-r--r--lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/InstrEmitter.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/Makefile3
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp70
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp124
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h4
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp98
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp1095
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp4
-rw-r--r--lib/CodeGen/SlotIndexes.cpp3
-rw-r--r--lib/CodeGen/TailDuplication.cpp34
-rw-r--r--lib/ExecutionEngine/Interpreter/Makefile2
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp10
-rw-r--r--lib/ExecutionEngine/JIT/Makefile2
-rw-r--r--lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp20
-rw-r--r--lib/ExecutionEngine/Makefile1
-rw-r--r--lib/Linker/LinkModules.cpp2
-rw-r--r--lib/Linker/Makefile1
-rw-r--r--lib/MC/CMakeLists.txt3
-rw-r--r--lib/MC/MCAsmInfo.cpp17
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp7
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp17
-rw-r--r--lib/MC/MCAsmStreamer.cpp352
-rw-r--r--lib/MC/MCAssembler.cpp2
-rw-r--r--lib/MC/MCExpr.cpp29
-rw-r--r--lib/MC/MCInst.cpp4
-rw-r--r--lib/MC/MCMachOStreamer.cpp71
-rw-r--r--lib/MC/MCNullStreamer.cpp12
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp320
-rw-r--r--lib/MC/MCParser/AsmParser.cpp1781
-rw-r--r--lib/MC/MCParser/CMakeLists.txt7
-rw-r--r--lib/MC/MCParser/MCAsmLexer.cpp (renamed from lib/MC/MCAsmLexer.cpp)2
-rw-r--r--lib/MC/MCParser/MCAsmParser.cpp35
-rw-r--r--lib/MC/MCParser/Makefile16
-rw-r--r--lib/MC/MCParser/TargetAsmParser.cpp (renamed from lib/MC/TargetAsmParser.cpp)0
-rw-r--r--lib/MC/MCSectionELF.cpp12
-rw-r--r--lib/MC/MCStreamer.cpp25
-rw-r--r--lib/MC/MCSymbol.cpp77
-rw-r--r--lib/MC/MCValue.cpp8
-rw-r--r--lib/MC/Makefile2
-rw-r--r--lib/Support/Debug.cpp4
-rw-r--r--lib/Support/SourceMgr.cpp21
-rw-r--r--lib/Support/StringExtras.cpp4
-rw-r--r--lib/Support/raw_ostream.cpp11
-rw-r--r--lib/System/Host.cpp4
-rw-r--r--lib/System/Unix/TimeValue.inc2
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.cpp4
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp8
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.h1
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp4
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp23
-rw-r--r--lib/Target/ARM/ARMISelLowering.h2
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td23
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td65
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td20
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td16
-rw-r--r--lib/Target/ARM/ARMMCAsmInfo.cpp2
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp4
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp138
-rw-r--r--lib/Target/ARM/AsmParser/Makefile1
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp239
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp2
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp14
-rw-r--r--lib/Target/ARM/AsmPrinter/Makefile1
-rw-r--r--lib/Target/ARM/Makefile1
-rw-r--r--lib/Target/ARM/README.txt9
-rw-r--r--lib/Target/ARM/TargetInfo/Makefile1
-rw-r--r--lib/Target/ARM/Thumb1InstrInfo.cpp8
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp8
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.cpp10
-rw-r--r--lib/Target/ARM/Thumb2SizeReduction.cpp3
-rw-r--r--lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp82
-rw-r--r--lib/Target/Alpha/AsmPrinter/Makefile1
-rw-r--r--lib/Target/Alpha/Makefile2
-rw-r--r--lib/Target/Alpha/TargetInfo/Makefile1
-rw-r--r--lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp58
-rw-r--r--lib/Target/Blackfin/AsmPrinter/Makefile1
-rw-r--r--lib/Target/Blackfin/Makefile2
-rw-r--r--lib/Target/Blackfin/TargetInfo/Makefile1
-rw-r--r--lib/Target/CBackend/CBackend.cpp75
-rw-r--r--lib/Target/CBackend/Makefile1
-rw-r--r--lib/Target/CBackend/TargetInfo/Makefile1
-rw-r--r--lib/Target/CMakeLists.txt2
-rw-r--r--lib/Target/CellSPU/AsmPrinter/Makefile1
-rw-r--r--lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp129
-rw-r--r--lib/Target/CellSPU/Makefile1
-rw-r--r--lib/Target/CellSPU/SPUMCAsmInfo.cpp2
-rw-r--r--lib/Target/CellSPU/TargetInfo/Makefile1
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp1
-rw-r--r--lib/Target/CppBackend/Makefile1
-rw-r--r--lib/Target/CppBackend/TargetInfo/Makefile1
-rw-r--r--lib/Target/MSIL/MSILWriter.cpp10
-rw-r--r--lib/Target/MSIL/MSILWriter.h2
-rw-r--r--lib/Target/MSIL/Makefile1
-rw-r--r--lib/Target/MSIL/TargetInfo/Makefile1
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp111
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp8
-rw-r--r--lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp14
-rw-r--r--lib/Target/MSP430/AsmPrinter/Makefile1
-rw-r--r--lib/Target/MSP430/CMakeLists.txt3
-rw-r--r--lib/Target/MSP430/MSP430.h2
-rw-r--r--lib/Target/MSP430/MSP430.td10
-rw-r--r--lib/Target/MSP430/MSP430BranchSelector.cpp179
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp67
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.h17
-rw-r--r--lib/Target/MSP430/MSP430InstrFormats.td166
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.cpp42
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.h18
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.td1340
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp6
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.h1
-rw-r--r--lib/Target/MSP430/Makefile2
-rw-r--r--lib/Target/MSP430/TargetInfo/Makefile1
-rw-r--r--lib/Target/Makefile1
-rw-r--r--lib/Target/Mangler.cpp179
-rw-r--r--lib/Target/Mips/AsmPrinter/Makefile1
-rw-r--r--lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp121
-rw-r--r--lib/Target/Mips/Makefile2
-rw-r--r--lib/Target/Mips/MipsCallingConv.td8
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp54
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp9
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td10
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp2
-rw-r--r--lib/Target/Mips/TargetInfo/Makefile1
-rw-r--r--lib/Target/PIC16/AsmPrinter/Makefile1
-rw-r--r--lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp82
-rw-r--r--lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h4
-rw-r--r--lib/Target/PIC16/Makefile2
-rw-r--r--lib/Target/PIC16/PIC16DebugInfo.cpp5
-rw-r--r--lib/Target/PIC16/PIC16Passes/Makefile1
-rw-r--r--lib/Target/PIC16/TargetInfo/Makefile1
-rw-r--r--lib/Target/PowerPC/AsmPrinter/Makefile1
-rw-r--r--lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp563
-rw-r--r--lib/Target/PowerPC/Makefile2
-rw-r--r--lib/Target/PowerPC/PPCMCAsmInfo.cpp3
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp29
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.h12
-rw-r--r--lib/Target/PowerPC/TargetInfo/Makefile1
-rw-r--r--lib/Target/README.txt51
-rw-r--r--lib/Target/Sparc/AsmPrinter/Makefile2
-rw-r--r--lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp97
-rw-r--r--lib/Target/Sparc/Makefile2
-rw-r--r--lib/Target/Sparc/TargetInfo/Makefile1
-rw-r--r--lib/Target/SystemZ/AsmPrinter/Makefile1
-rw-r--r--lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp116
-rw-r--r--lib/Target/SystemZ/Makefile2
-rw-r--r--lib/Target/SystemZ/SystemZMCAsmInfo.cpp6
-rw-r--r--lib/Target/SystemZ/SystemZMCAsmInfo.h3
-rw-r--r--lib/Target/SystemZ/TargetInfo/Makefile1
-rw-r--r--lib/Target/TargetAsmLexer.cpp (renamed from lib/MC/MCAsmParser.cpp)12
-rw-r--r--lib/Target/TargetLoweringObjectFile.cpp98
-rw-r--r--lib/Target/TargetMachine.cpp6
-rw-r--r--lib/Target/X86/AsmParser/CMakeLists.txt1
-rw-r--r--lib/Target/X86/AsmParser/Makefile1
-rw-r--r--lib/Target/X86/AsmParser/X86AsmLexer.cpp43
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp239
-rw-r--r--lib/Target/X86/AsmPrinter/Makefile1
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp7
-rw-r--r--lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp314
-rw-r--r--lib/Target/X86/AsmPrinter/X86AsmPrinter.h1
-rw-r--r--lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp6
-rw-r--r--lib/Target/X86/AsmPrinter/X86MCInstLower.cpp52
-rw-r--r--lib/Target/X86/Disassembler/Makefile1
-rw-r--r--lib/Target/X86/Makefile2
-rw-r--r--lib/Target/X86/TargetInfo/Makefile2
-rw-r--r--lib/Target/X86/X86COFFMachineModuleInfo.cpp11
-rw-r--r--lib/Target/X86/X86COFFMachineModuleInfo.h4
-rw-r--r--lib/Target/X86/X86FastISel.cpp4
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp8
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp17
-rw-r--r--lib/Target/X86/X86Instr64bit.td2
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp146
-rw-r--r--lib/Target/X86/X86InstrInfo.h20
-rw-r--r--lib/Target/X86/X86MCAsmInfo.cpp9
-rw-r--r--lib/Target/X86/X86MCAsmInfo.h1
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp21
-rw-r--r--lib/Target/X86/X86RegisterInfo.h2
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp32
-rw-r--r--lib/Target/X86/X86TargetMachine.h12
-rw-r--r--lib/Target/X86/X86TargetObjectFile.cpp7
-rw-r--r--lib/Target/XCore/AsmPrinter/Makefile1
-rw-r--r--lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp105
-rw-r--r--lib/Target/XCore/Makefile2
-rw-r--r--lib/Target/XCore/TargetInfo/Makefile2
-rw-r--r--lib/Transforms/Hello/Makefile1
-rw-r--r--lib/Transforms/IPO/Inliner.cpp26
-rw-r--r--lib/Transforms/IPO/Makefile1
-rw-r--r--lib/Transforms/IPO/StripSymbols.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp5
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp13
-rw-r--r--lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp9
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineShifts.cpp24
-rw-r--r--lib/Transforms/InstCombine/Makefile1
-rw-r--r--lib/Transforms/Instrumentation/Makefile1
-rw-r--r--lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp2
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp29
-rw-r--r--lib/Transforms/Scalar/GVN.cpp99
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp14
-rw-r--r--lib/Transforms/Scalar/Makefile1
-rw-r--r--lib/Transforms/Scalar/ScalarReplAggregates.cpp82
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp47
-rw-r--r--lib/Transforms/Utils/BasicBlockUtils.cpp5
-rw-r--r--lib/Transforms/Utils/Local.cpp24
-rw-r--r--lib/Transforms/Utils/LoopSimplify.cpp2
-rw-r--r--lib/Transforms/Utils/Makefile1
-rw-r--r--lib/Transforms/Utils/PromoteMemoryToRegister.cpp61
-rw-r--r--lib/Transforms/Utils/ValueMapper.cpp30
-rw-r--r--lib/VMCore/AsmWriter.cpp4
-rw-r--r--lib/VMCore/Attributes.cpp2
-rw-r--r--lib/VMCore/AutoUpgrade.cpp2
-rw-r--r--lib/VMCore/CMakeLists.txt1
-rw-r--r--lib/VMCore/ConstantFold.cpp5
-rw-r--r--lib/VMCore/Constants.cpp20
-rw-r--r--lib/VMCore/Instructions.cpp13
-rw-r--r--lib/VMCore/IntrinsicInst.cpp11
-rw-r--r--lib/VMCore/Makefile1
-rw-r--r--lib/VMCore/Mangler.cpp273
-rw-r--r--lib/VMCore/Metadata.cpp97
-rw-r--r--lib/VMCore/Pass.cpp3
-rw-r--r--lib/VMCore/PassManager.cpp76
-rw-r--r--lib/VMCore/Verifier.cpp17
282 files changed, 8672 insertions, 7577 deletions
diff --git a/lib/Analysis/AliasAnalysisCounter.cpp b/lib/Analysis/AliasAnalysisCounter.cpp
index ae28b55..761cd46 100644
--- a/lib/Analysis/AliasAnalysisCounter.cpp
+++ b/lib/Analysis/AliasAnalysisCounter.cpp
@@ -31,7 +31,6 @@ namespace {
class AliasAnalysisCounter : public ModulePass, public AliasAnalysis {
unsigned No, May, Must;
unsigned NoMR, JustRef, JustMod, MR;
- const char *Name;
Module *M;
public:
static char ID; // Class identification, replacement for typeinfo
@@ -49,7 +48,7 @@ namespace {
unsigned MRSum = NoMR+JustRef+JustMod+MR;
if (AASum + MRSum) { // Print a report if any counted queries occurred...
errs() << "\n===== Alias Analysis Counter Report =====\n"
- << " Analysis counted: " << Name << "\n"
+ << " Analysis counted:\n"
<< " " << AASum << " Total Alias Queries Performed\n";
if (AASum) {
printLine("no alias", No, AASum);
@@ -75,7 +74,6 @@ namespace {
bool runOnModule(Module &M) {
this->M = &M;
InitializeAliasAnalysis(this);
- Name = dynamic_cast<Pass*>(&getAnalysis<AliasAnalysis>())->getPassName();
return false;
}
@@ -85,6 +83,16 @@ namespace {
AU.setPreservesAll();
}
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
// FIXME: We could count these too...
bool pointsToConstantMemory(const Value *P) {
return getAnalysis<AliasAnalysis>().pointsToConstantMemory(P);
diff --git a/lib/Analysis/AliasDebugger.cpp b/lib/Analysis/AliasDebugger.cpp
index 6868e3f..88c2875 100644
--- a/lib/Analysis/AliasDebugger.cpp
+++ b/lib/Analysis/AliasDebugger.cpp
@@ -71,6 +71,16 @@ namespace {
AU.setPreservesAll(); // Does not transform code
}
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
//------------------------------------------------
// Implement the AliasAnalysis API
//
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index b2983c7..36b831c 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -153,6 +153,16 @@ namespace {
virtual void deleteValue(Value *V) {}
virtual void copyValue(Value *From, Value *To) {}
+
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it should
+ /// override this to adjust the this pointer as needed for the specified pass
+ /// info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
};
} // End of anonymous namespace
@@ -192,6 +202,16 @@ namespace {
/// global) or not.
bool pointsToConstantMemory(const Value *P);
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it should
+ /// override this to adjust the this pointer as needed for the specified pass
+ /// info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
private:
// VisitedPHIs - Track PHI nodes visited by a aliasCheck() call.
SmallPtrSet<const Value*, 16> VisitedPHIs;
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index 59ba807..4ba837a 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/lib/Analysis/DebugInfo.cpp
@@ -599,7 +599,7 @@ void DIVariable::dump() const {
//===----------------------------------------------------------------------===//
DIFactory::DIFactory(Module &m)
- : M(m), VMContext(M.getContext()), DeclareFn(0) {}
+ : M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {}
Constant *DIFactory::GetTagConstant(unsigned TAG) {
assert((TAG & LLVMDebugVersionMask) == 0 &&
@@ -854,7 +854,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
StringRef DisplayName,
StringRef LinkageName,
DICompileUnit CompileUnit,
- unsigned LineNo, DIType Type,
+ unsigned LineNo, DIType Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned VK, unsigned VIndex,
@@ -869,7 +869,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
MDString::get(VMContext, LinkageName),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- Type.getNode(),
+ Ty.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK),
@@ -911,7 +911,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
DICompileUnit CompileUnit,
- unsigned LineNo, DIType Type,bool isLocalToUnit,
+ unsigned LineNo, DIType Ty,bool isLocalToUnit,
bool isDefinition, llvm::GlobalVariable *Val) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_variable),
@@ -922,7 +922,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
MDString::get(VMContext, LinkageName),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- Type.getNode(),
+ Ty.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
Val
@@ -943,14 +943,14 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
StringRef Name,
DICompileUnit CompileUnit, unsigned LineNo,
- DIType Type) {
+ DIType Ty) {
Value *Elts[] = {
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- Type.getNode(),
+ Ty.getNode(),
};
return DIVariable(MDNode::get(VMContext, &Elts[0], 6));
}
@@ -962,14 +962,15 @@ DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
const std::string &Name,
DICompileUnit CompileUnit,
unsigned LineNo,
- DIType Type, SmallVector<Value *, 9> &addr) {
+ DIType Ty,
+ SmallVector<Value *, 9> &addr) {
SmallVector<Value *, 9> Elts;
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(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo));
- Elts.push_back(Type.getNode());
+ Elts.push_back(Ty.getNode());
Elts.insert(Elts.end(), addr.begin(), addr.end());
return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size()));
@@ -1035,8 +1036,8 @@ Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Elts[] = { Storage };
- Value *Args[] = { MDNode::get(Storage->getContext(), Elts, 1), D.getNode() };
+ Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1),
+ D.getNode() };
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore);
}
@@ -1046,8 +1047,8 @@ Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Elts[] = { Storage };
- Value *Args[] = { MDNode::get(Storage->getContext(), Elts, 1), D.getNode() };
+ Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1),
+ D.getNode() };
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);
}
@@ -1059,8 +1060,7 @@ Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Elts[] = { V };
- Value *Args[] = { MDNode::get(V->getContext(), Elts, 1),
+ Value *Args[] = { MDNode::get(V->getContext(), &V, 1),
ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
D.getNode() };
return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore);
@@ -1074,8 +1074,7 @@ Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Elts[] = { V };
- Value *Args[] = { MDNode::get(V->getContext(), Elts, 1),
+ Value *Args[] = { MDNode::get(V->getContext(), &V, 1),
ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
D.getNode() };
return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd);
@@ -1139,9 +1138,9 @@ void DebugInfoFinder::processType(DIType DT) {
if (!DA.isNull())
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
DIDescriptor D = DA.getElement(i);
- DIType TypeE = DIType(D.getNode());
- if (!TypeE.isNull())
- processType(TypeE);
+ DIType TyE = DIType(D.getNode());
+ if (!TyE.isNull())
+ processType(TyE);
else
processSubprogram(DISubprogram(D.getNode()));
}
@@ -1234,7 +1233,8 @@ bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
return true;
}
-Value *llvm::findDbgGlobalDeclare(GlobalVariable *V) {
+/// Find the debug info descriptor corresponding to this global variable.
+static Value *findDbgGlobalDeclare(GlobalVariable *V) {
const Module *M = V->getParent();
NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
if (!NMD)
@@ -1252,7 +1252,7 @@ Value *llvm::findDbgGlobalDeclare(GlobalVariable *V) {
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
/// It looks through pointer casts too.
-const DbgDeclareInst *llvm::findDbgDeclare(const Value *V) {
+static const DbgDeclareInst *findDbgDeclare(const Value *V) {
V = V->stripPointerCasts();
if (!isa<Instruction>(V) && !isa<Argument>(V))
@@ -1320,23 +1320,15 @@ bool llvm::getLocationInfo(const Value *V, std::string &DisplayName,
/// from DILocation.
DebugLoc llvm::ExtractDebugLocation(DILocation &Loc,
DebugLocTracker &DebugLocInfo) {
- DebugLoc DL;
- MDNode *Context = Loc.getScope().getNode();
- MDNode *InlinedLoc = NULL;
- if (!Loc.getOrigLocation().isNull())
- InlinedLoc = Loc.getOrigLocation().getNode();
- // If this location is already tracked then use it.
- DebugLocTuple Tuple(Context, InlinedLoc, Loc.getLineNumber(),
- Loc.getColumnNumber());
- DenseMap<DebugLocTuple, unsigned>::iterator II
- = DebugLocInfo.DebugIdMap.find(Tuple);
+ DenseMap<MDNode *, unsigned>::iterator II
+ = DebugLocInfo.DebugIdMap.find(Loc.getNode());
if (II != DebugLocInfo.DebugIdMap.end())
return DebugLoc::get(II->second);
// Add a new location entry.
unsigned Id = DebugLocInfo.DebugLocations.size();
- DebugLocInfo.DebugLocations.push_back(Tuple);
- DebugLocInfo.DebugIdMap[Tuple] = Id;
+ DebugLocInfo.DebugLocations.push_back(Loc.getNode());
+ DebugLocInfo.DebugIdMap[Loc.getNode()] = Id;
return DebugLoc::get(Id);
}
diff --git a/lib/Analysis/DomPrinter.cpp b/lib/Analysis/DomPrinter.cpp
index 32b8994..3af687a 100644
--- a/lib/Analysis/DomPrinter.cpp
+++ b/lib/Analysis/DomPrinter.cpp
@@ -19,10 +19,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DomPrinter.h"
-#include "llvm/Pass.h"
-#include "llvm/Function.h"
-#include "llvm/Analysis/CFGPrinter.h"
+
#include "llvm/Analysis/Dominators.h"
+#include "llvm/Analysis/DOTGraphTraitsPass.h"
#include "llvm/Analysis/PostDominators.h"
using namespace llvm;
@@ -110,29 +109,29 @@ struct GenericGraphViewer : public FunctionPass {
};
struct DomViewer
- : public GenericGraphViewer<DominatorTree, false> {
+ : public DOTGraphTraitsViewer<DominatorTree, false> {
static char ID;
- DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
+ DomViewer() : DOTGraphTraitsViewer<DominatorTree, false>("dom", &ID){}
};
struct DomOnlyViewer
- : public GenericGraphViewer<DominatorTree, true> {
+ : public DOTGraphTraitsViewer<DominatorTree, true> {
static char ID;
- DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
+ DomOnlyViewer() : DOTGraphTraitsViewer<DominatorTree, true>("domonly", &ID){}
};
struct PostDomViewer
- : public GenericGraphViewer<PostDominatorTree, false> {
+ : public DOTGraphTraitsViewer<PostDominatorTree, false> {
static char ID;
PostDomViewer() :
- GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
+ DOTGraphTraitsViewer<PostDominatorTree, false>("postdom", &ID){}
};
struct PostDomOnlyViewer
- : public GenericGraphViewer<PostDominatorTree, true> {
+ : public DOTGraphTraitsViewer<PostDominatorTree, true> {
static char ID;
PostDomOnlyViewer() :
- GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
+ DOTGraphTraitsViewer<PostDominatorTree, true>("postdomonly", &ID){}
};
} // end anonymous namespace
@@ -155,67 +154,30 @@ RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
"(with no function bodies)");
namespace {
-template <class Analysis, bool OnlyBBS>
-struct GenericGraphPrinter : public FunctionPass {
-
- std::string Name;
-
- GenericGraphPrinter(std::string GraphName, const void *ID)
- : FunctionPass(ID) {
- Name = GraphName;
- }
-
- virtual bool runOnFunction(Function &F) {
- Analysis *Graph;
- std::string Filename = Name + "." + F.getNameStr() + ".dot";
- errs() << "Writing '" << Filename << "'...";
-
- std::string ErrorInfo;
- raw_fd_ostream File(Filename.c_str(), ErrorInfo);
- Graph = &getAnalysis<Analysis>();
-
- std::string Title, GraphName;
- GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
- Title = GraphName + " for '" + F.getNameStr() + "' function";
-
- if (ErrorInfo.empty())
- WriteGraph(File, Graph, OnlyBBS, Name, Title);
- else
- errs() << " error opening file for writing!";
- errs() << "\n";
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AU.addRequired<Analysis>();
- }
-};
-
struct DomPrinter
- : public GenericGraphPrinter<DominatorTree, false> {
+ : public DOTGraphTraitsPrinter<DominatorTree, false> {
static char ID;
- DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {}
+ DomPrinter() : DOTGraphTraitsPrinter<DominatorTree, false>("dom", &ID) {}
};
struct DomOnlyPrinter
- : public GenericGraphPrinter<DominatorTree, true> {
+ : public DOTGraphTraitsPrinter<DominatorTree, true> {
static char ID;
- DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {}
+ DomOnlyPrinter() : DOTGraphTraitsPrinter<DominatorTree, true>("domonly", &ID) {}
};
struct PostDomPrinter
- : public GenericGraphPrinter<PostDominatorTree, false> {
+ : public DOTGraphTraitsPrinter<PostDominatorTree, false> {
static char ID;
PostDomPrinter() :
- GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {}
+ DOTGraphTraitsPrinter<PostDominatorTree, false>("postdom", &ID) {}
};
struct PostDomOnlyPrinter
- : public GenericGraphPrinter<PostDominatorTree, true> {
+ : public DOTGraphTraitsPrinter<PostDominatorTree, true> {
static char ID;
PostDomOnlyPrinter() :
- GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {}
+ DOTGraphTraitsPrinter<PostDominatorTree, true>("postdomonly", &ID) {}
};
} // end anonymous namespace
diff --git a/lib/Analysis/IPA/Andersens.cpp b/lib/Analysis/IPA/Andersens.cpp
index 28c66af..4180206 100644
--- a/lib/Analysis/IPA/Andersens.cpp
+++ b/lib/Analysis/IPA/Andersens.cpp
@@ -475,6 +475,16 @@ namespace {
AU.setPreservesAll(); // Does not transform code
}
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
//------------------------------------------------
// Implement the AliasAnalysis API
//
diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp
index a826177..8c43aa1 100644
--- a/lib/Analysis/IPA/CallGraph.cpp
+++ b/lib/Analysis/IPA/CallGraph.cpp
@@ -26,7 +26,7 @@ namespace {
//===----------------------------------------------------------------------===//
// BasicCallGraph class definition
//
-class BasicCallGraph : public CallGraph, public ModulePass {
+class BasicCallGraph : public ModulePass, public CallGraph {
// Root is root of the call graph, or the external node if a 'main' function
// couldn't be found.
//
@@ -82,6 +82,16 @@ public:
destroy();
}
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it should
+ /// override this to adjust the this pointer as needed for the specified pass
+ /// info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&CallGraph::ID))
+ return (CallGraph*)this;
+ return this;
+ }
+
CallGraphNode* getExternalCallingNode() const { return ExternalCallingNode; }
CallGraphNode* getCallsExternalNode() const { return CallsExternalNode; }
diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp
index 5504b9b..0e333d1 100644
--- a/lib/Analysis/IPA/CallGraphSCCPass.cpp
+++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp
@@ -57,6 +57,9 @@ public:
return "CallGraph Pass Manager";
}
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
// Print passes managed by this manager
void dumpPassStructure(unsigned Offset) {
errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n";
@@ -90,7 +93,10 @@ char CGPassManager::ID = 0;
bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
CallGraph &CG, bool &CallGraphUpToDate) {
bool Changed = false;
- if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass*>(P)) {
+ PMDataManager *PM = P->getAsPMDataManager();
+
+ if (PM == 0) {
+ CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P;
if (!CallGraphUpToDate) {
RefreshCallGraph(CurSCC, CG, false);
CallGraphUpToDate = true;
@@ -110,8 +116,10 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
return Changed;
}
- FPPassManager *FPP = dynamic_cast<FPPassManager *>(P);
- assert(FPP && "Invalid CGPassManager member");
+
+ assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
+ "Invalid CGPassManager member");
+ FPPassManager *FPP = (FPPassManager*)P;
// Run pass P on all functions in the current SCC.
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
@@ -360,14 +368,13 @@ bool CGPassManager::runOnModule(Module &M) {
/// Initialize CG
bool CGPassManager::doInitialization(CallGraph &CG) {
bool Changed = false;
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) {
- Changed |= CGSP->doInitialization(CG);
+ for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
+ if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
+ assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
+ "Invalid CGPassManager member");
+ Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule());
} else {
- FPPassManager *FP = dynamic_cast<FPPassManager *>(P);
- assert (FP && "Invalid CGPassManager member");
- Changed |= FP->doInitialization(CG.getModule());
+ Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG);
}
}
return Changed;
@@ -376,14 +383,13 @@ bool CGPassManager::doInitialization(CallGraph &CG) {
/// Finalize CG
bool CGPassManager::doFinalization(CallGraph &CG) {
bool Changed = false;
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) {
- Changed |= CGSP->doFinalization(CG);
+ for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
+ if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
+ assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
+ "Invalid CGPassManager member");
+ Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule());
} else {
- FPPassManager *FP = dynamic_cast<FPPassManager *>(P);
- assert (FP && "Invalid CGPassManager member");
- Changed |= FP->doFinalization(CG.getModule());
+ Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG);
}
}
return Changed;
@@ -397,13 +403,14 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS,
PMS.top()->getPassManagerType() > PMT_CallGraphPassManager)
PMS.pop();
- assert (!PMS.empty() && "Unable to handle Call Graph Pass");
- CGPassManager *CGP = dynamic_cast<CGPassManager *>(PMS.top());
-
- // Create new Call Graph SCC Pass Manager if it does not exist.
- if (!CGP) {
-
- assert (!PMS.empty() && "Unable to create Call Graph Pass Manager");
+ assert(!PMS.empty() && "Unable to handle Call Graph Pass");
+ CGPassManager *CGP;
+
+ if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager)
+ CGP = (CGPassManager*)PMS.top();
+ else {
+ // Create new Call Graph SCC Pass Manager if it does not exist.
+ assert(!PMS.empty() && "Unable to create Call Graph Pass Manager");
PMDataManager *PMD = PMS.top();
// [1] Create new Call Graph Pass Manager
@@ -415,7 +422,7 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS,
// [3] Assign manager to manage this new manager. This may create
// and push new managers into PMS
- Pass *P = dynamic_cast<Pass *>(CGP);
+ Pass *P = CGP;
TPM->schedulePass(P);
// [4] Push new manager into PMS
diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp
index a979a99..e803a48 100644
--- a/lib/Analysis/IPA/GlobalsModRef.cpp
+++ b/lib/Analysis/IPA/GlobalsModRef.cpp
@@ -145,6 +145,16 @@ namespace {
virtual void deleteValue(Value *V);
virtual void copyValue(Value *From, Value *To);
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
private:
/// getFunctionInfo - Return the function info for the function, or null if
/// we don't have anything useful to say about it.
diff --git a/lib/Analysis/IPA/Makefile b/lib/Analysis/IPA/Makefile
index adacb16..da719ba 100644
--- a/lib/Analysis/IPA/Makefile
+++ b/lib/Analysis/IPA/Makefile
@@ -10,5 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMipa
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
+
include $(LEVEL)/Makefile.common
diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp
index 26c0c9e..38611cc 100644
--- a/lib/Analysis/IVUsers.cpp
+++ b/lib/Analysis/IVUsers.cpp
@@ -324,12 +324,19 @@ const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const {
// the actual replacement value.
if (U.isUseOfPostIncrementedValue())
RetVal = SE->getAddExpr(RetVal, U.getParent()->Stride);
- // Evaluate the expression out of the loop, if possible.
- if (!L->contains(U.getUser())) {
- const SCEV *ExitVal = SE->getSCEVAtScope(RetVal, L->getParentLoop());
- if (ExitVal->isLoopInvariant(L))
- RetVal = ExitVal;
- }
+ return RetVal;
+}
+
+/// getCanonicalExpr - Return a SCEV expression which computes the
+/// value of the SCEV of the given IVStrideUse, ignoring the
+/// isUseOfPostIncrementedValue flag.
+const SCEV *IVUsers::getCanonicalExpr(const IVStrideUse &U) const {
+ // Start with zero.
+ const SCEV *RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType());
+ // Create the basic add recurrence.
+ RetVal = SE->getAddRecExpr(RetVal, U.getParent()->Stride, L);
+ // Add the offset in a separate step, because it may be loop-variant.
+ RetVal = SE->getAddExpr(RetVal, U.getOffset());
return RetVal;
}
diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp
index 43463cd..2d613f6 100644
--- a/lib/Analysis/LoopPass.cpp
+++ b/lib/Analysis/LoopPass.cpp
@@ -147,8 +147,7 @@ void LPPassManager::redoLoop(Loop *L) {
void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From,
BasicBlock *To, Loop *L) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- LoopPass *LP = dynamic_cast<LoopPass *>(P);
+ LoopPass *LP = (LoopPass *)getContainedPass(Index);
LP->cloneBasicBlockAnalysis(From, To, L);
}
}
@@ -163,8 +162,7 @@ void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) {
}
}
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- LoopPass *LP = dynamic_cast<LoopPass *>(P);
+ LoopPass *LP = (LoopPass *)getContainedPass(Index);
LP->deleteAnalysisValue(V, L);
}
}
@@ -206,10 +204,8 @@ bool LPPassManager::runOnFunction(Function &F) {
I != E; ++I) {
Loop *L = *I;
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- LoopPass *LP = dynamic_cast<LoopPass *>(P);
- if (LP)
- Changed |= LP->doInitialization(L, *this);
+ LoopPass *P = (LoopPass*)getContainedPass(Index);
+ Changed |= P->doInitialization(L, *this);
}
}
@@ -222,7 +218,7 @@ bool LPPassManager::runOnFunction(Function &F) {
// Run all passes on the current Loop.
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
+ LoopPass *P = (LoopPass*)getContainedPass(Index);
dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG,
CurrentLoop->getHeader()->getNameStr());
@@ -230,12 +226,10 @@ bool LPPassManager::runOnFunction(Function &F) {
initializeAnalysisImpl(P);
- LoopPass *LP = dynamic_cast<LoopPass *>(P);
- assert(LP && "Invalid LPPassManager member");
{
- PassManagerPrettyStackEntry X(LP, *CurrentLoop->getHeader());
+ PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());
Timer *T = StartPassTimer(P);
- Changed |= LP->runOnLoop(CurrentLoop, *this);
+ Changed |= P->runOnLoop(CurrentLoop, *this);
StopPassTimer(P, T);
}
@@ -256,7 +250,7 @@ bool LPPassManager::runOnFunction(Function &F) {
StopPassTimer(LI, T);
// Then call the regular verifyAnalysis functions.
- verifyPreservedAnalysis(LP);
+ verifyPreservedAnalysis(P);
}
removeNotPreservedAnalysis(P);
@@ -289,10 +283,8 @@ bool LPPassManager::runOnFunction(Function &F) {
// Finalization
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- Pass *P = getContainedPass(Index);
- LoopPass *LP = dynamic_cast <LoopPass *>(P);
- if (LP)
- Changed |= LP->doFinalization();
+ LoopPass *P = (LoopPass *)getContainedPass(Index);
+ Changed |= P->doFinalization();
}
return Changed;
@@ -325,12 +317,11 @@ void LoopPass::preparePassManager(PMStack &PMS) {
PMS.top()->getPassManagerType() > PMT_LoopPassManager)
PMS.pop();
- LPPassManager *LPPM = dynamic_cast<LPPassManager *>(PMS.top());
-
// If this pass is destroying high level information that is used
// by other passes that are managed by LPM then do not insert
// this pass in current LPM. Use new LPPassManager.
- if (LPPM && !LPPM->preserveHigherLevelAnalysis(this))
+ if (PMS.top()->getPassManagerType() == PMT_LoopPassManager &&
+ !PMS.top()->preserveHigherLevelAnalysis(this))
PMS.pop();
}
@@ -342,11 +333,11 @@ void LoopPass::assignPassManager(PMStack &PMS,
PMS.top()->getPassManagerType() > PMT_LoopPassManager)
PMS.pop();
- LPPassManager *LPPM = dynamic_cast<LPPassManager *>(PMS.top());
-
- // Create new Loop Pass Manager if it does not exist.
- if (!LPPM) {
-
+ LPPassManager *LPPM;
+ if (PMS.top()->getPassManagerType() == PMT_LoopPassManager)
+ LPPM = (LPPassManager*)PMS.top();
+ else {
+ // Create new Loop Pass Manager if it does not exist.
assert (!PMS.empty() && "Unable to create Loop Pass Manager");
PMDataManager *PMD = PMS.top();
@@ -360,7 +351,7 @@ void LoopPass::assignPassManager(PMStack &PMS,
// [3] Assign manager to manage this new manager. This may create
// and push new managers into PMS
- Pass *P = dynamic_cast<Pass *>(LPPM);
+ Pass *P = LPPM->getAsPass();
TPM->schedulePass(P);
// [4] Push new manager into PMS
diff --git a/lib/Analysis/Makefile b/lib/Analysis/Makefile
index 4af6d35..f61b8aa 100644
--- a/lib/Analysis/Makefile
+++ b/lib/Analysis/Makefile
@@ -11,6 +11,7 @@ LEVEL = ../..
LIBRARYNAME = LLVMAnalysis
DIRS = IPA
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Analysis/ProfileEstimatorPass.cpp b/lib/Analysis/ProfileEstimatorPass.cpp
index cf9311a..bce6b31 100644
--- a/lib/Analysis/ProfileEstimatorPass.cpp
+++ b/lib/Analysis/ProfileEstimatorPass.cpp
@@ -55,6 +55,16 @@ namespace {
/// run - Estimate the profile information from the specified file.
virtual bool runOnFunction(Function &F);
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&ProfileInfo::ID))
+ return (ProfileInfo*)this;
+ return this;
+ }
+
virtual void recurseBasicBlock(BasicBlock *BB);
void inline printEdgeWeight(Edge);
diff --git a/lib/Analysis/ProfileInfo.cpp b/lib/Analysis/ProfileInfo.cpp
index afd86b1..85531be 100644
--- a/lib/Analysis/ProfileInfo.cpp
+++ b/lib/Analysis/ProfileInfo.cpp
@@ -1079,6 +1079,20 @@ namespace {
struct NoProfileInfo : public ImmutablePass, public ProfileInfo {
static char ID; // Class identification, replacement for typeinfo
NoProfileInfo() : ImmutablePass(&ID) {}
+
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&ProfileInfo::ID))
+ return (ProfileInfo*)this;
+ return this;
+ }
+
+ virtual const char *getPassName() const {
+ return "NoProfileInfo";
+ }
};
} // End of anonymous namespace
diff --git a/lib/Analysis/ProfileInfoLoaderPass.cpp b/lib/Analysis/ProfileInfoLoaderPass.cpp
index d8c511f..ac9ed52 100644
--- a/lib/Analysis/ProfileInfoLoaderPass.cpp
+++ b/lib/Analysis/ProfileInfoLoaderPass.cpp
@@ -63,6 +63,16 @@ namespace {
virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &);
virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&);
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&ProfileInfo::ID))
+ return (ProfileInfo*)this;
+ return this;
+ }
+
/// run - Load the profile information from the specified file.
virtual bool runOnModule(Module &M);
};
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 4d85ce4..2f44913 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -1089,6 +1089,15 @@ const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op,
if (!isa<SCEVSignExtendExpr>(SExt))
return SExt;
+ // Force the cast to be folded into the operands of an addrec.
+ if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op)) {
+ SmallVector<const SCEV *, 4> Ops;
+ for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end();
+ I != E; ++I)
+ Ops.push_back(getAnyExtendExpr(*I, Ty));
+ return getAddRecExpr(Ops, AR->getLoop());
+ }
+
// If the expression is obviously signed, use the sext cast value.
if (isa<SCEVSMaxExpr>(Op))
return SExt;
@@ -1204,6 +1213,17 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
"SCEVAddExpr operand types don't match!");
#endif
+ // If HasNSW is true and all the operands are non-negative, infer HasNUW.
+ if (!HasNUW && HasNSW) {
+ bool All = true;
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i)
+ if (!isKnownNonNegative(Ops[i])) {
+ All = false;
+ break;
+ }
+ if (All) HasNUW = true;
+ }
+
// Sort by complexity, this groups all similar expression types together.
GroupByComplexity(Ops, LI);
@@ -1521,21 +1541,24 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
ID.AddPointer(Ops[i]);
void *IP = 0;
- if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
- SCEVAddExpr *S = SCEVAllocator.Allocate<SCEVAddExpr>();
- new (S) SCEVAddExpr(ID, Ops);
- UniqueSCEVs.InsertNode(S, IP);
+ SCEVAddExpr *S =
+ static_cast<SCEVAddExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
+ if (!S) {
+ S = SCEVAllocator.Allocate<SCEVAddExpr>();
+ new (S) SCEVAddExpr(ID, Ops);
+ UniqueSCEVs.InsertNode(S, IP);
+ }
if (HasNUW) S->setHasNoUnsignedWrap(true);
if (HasNSW) S->setHasNoSignedWrap(true);
return S;
}
-
/// getMulExpr - Get a canonical multiply expression, or something simpler if
/// possible.
const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
bool HasNUW, bool HasNSW) {
assert(!Ops.empty() && "Cannot get empty mul!");
+ if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
for (unsigned i = 1, e = Ops.size(); i != e; ++i)
assert(getEffectiveSCEVType(Ops[i]->getType()) ==
@@ -1543,6 +1566,17 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
"SCEVMulExpr operand types don't match!");
#endif
+ // If HasNSW is true and all the operands are non-negative, infer HasNUW.
+ if (!HasNUW && HasNSW) {
+ bool All = true;
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i)
+ if (!isKnownNonNegative(Ops[i])) {
+ All = false;
+ break;
+ }
+ if (All) HasNUW = true;
+ }
+
// Sort by complexity, this groups all similar expression types together.
GroupByComplexity(Ops, LI);
@@ -1558,7 +1592,6 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)),
getMulExpr(LHSC, Add->getOperand(1)));
-
++Idx;
while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
// We found two constants, fold them together!
@@ -1578,6 +1611,22 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
} else if (cast<SCEVConstant>(Ops[0])->getValue()->isZero()) {
// If we have a multiply of zero, it will always be zero.
return Ops[0];
+ } else if (Ops[0]->isAllOnesValue()) {
+ // If we have a mul by -1 of an add, try distributing the -1 among the
+ // add operands.
+ if (Ops.size() == 2)
+ if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) {
+ SmallVector<const SCEV *, 4> NewOps;
+ bool AnyFolded = false;
+ for (SCEVAddRecExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
+ I != E; ++I) {
+ const SCEV *Mul = getMulExpr(Ops[0], *I);
+ if (!isa<SCEVMulExpr>(Mul)) AnyFolded = true;
+ NewOps.push_back(Mul);
+ }
+ if (AnyFolded)
+ return getAddExpr(NewOps);
+ }
}
}
@@ -1644,7 +1693,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// It's tempting to propagate the NSW flag here, but nsw multiplication
// is not associative so this isn't necessarily safe.
- const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop());
+ const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop(),
+ HasNUW && AddRec->hasNoUnsignedWrap(),
+ /*HasNSW=*/false);
// If all of the other operands were loop invariant, we are done.
if (Ops.size() == 1) return NewRec;
@@ -1698,10 +1749,13 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
ID.AddPointer(Ops[i]);
void *IP = 0;
- if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
- SCEVMulExpr *S = SCEVAllocator.Allocate<SCEVMulExpr>();
- new (S) SCEVMulExpr(ID, Ops);
- UniqueSCEVs.InsertNode(S, IP);
+ SCEVMulExpr *S =
+ static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
+ if (!S) {
+ S = SCEVAllocator.Allocate<SCEVMulExpr>();
+ new (S) SCEVMulExpr(ID, Ops);
+ UniqueSCEVs.InsertNode(S, IP);
+ }
if (HasNUW) S->setHasNoUnsignedWrap(true);
if (HasNSW) S->setHasNoSignedWrap(true);
return S;
@@ -1844,10 +1898,24 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X
}
+ // If HasNSW is true and all the operands are non-negative, infer HasNUW.
+ if (!HasNUW && HasNSW) {
+ bool All = true;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (!isKnownNonNegative(Operands[i])) {
+ All = false;
+ break;
+ }
+ if (All) HasNUW = true;
+ }
+
// Canonicalize nested AddRecs in by nesting them in order of loop depth.
if (const SCEVAddRecExpr *NestedAR = dyn_cast<SCEVAddRecExpr>(Operands[0])) {
const Loop *NestedLoop = NestedAR->getLoop();
- if (L->getLoopDepth() < NestedLoop->getLoopDepth()) {
+ if (L->contains(NestedLoop->getHeader()) ?
+ (L->getLoopDepth() < NestedLoop->getLoopDepth()) :
+ (!NestedLoop->contains(L->getHeader()) &&
+ DT->dominates(L->getHeader(), NestedLoop->getHeader()))) {
SmallVector<const SCEV *, 4> NestedOperands(NestedAR->op_begin(),
NestedAR->op_end());
Operands[0] = NestedAR->getStart();
@@ -1877,6 +1945,8 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
}
}
+ // Okay, it looks like we really DO need an addrec expr. Check to see if we
+ // already have one, otherwise create a new one.
FoldingSetNodeID ID;
ID.AddInteger(scAddRecExpr);
ID.AddInteger(Operands.size());
@@ -1884,10 +1954,13 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
ID.AddPointer(Operands[i]);
ID.AddPointer(L);
void *IP = 0;
- if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
- SCEVAddRecExpr *S = SCEVAllocator.Allocate<SCEVAddRecExpr>();
- new (S) SCEVAddRecExpr(ID, Operands, L);
- UniqueSCEVs.InsertNode(S, IP);
+ SCEVAddRecExpr *S =
+ static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
+ if (!S) {
+ S = SCEVAllocator.Allocate<SCEVAddRecExpr>();
+ new (S) SCEVAddRecExpr(ID, Operands, L);
+ UniqueSCEVs.InsertNode(S, IP);
+ }
if (HasNUW) S->setHasNoUnsignedWrap(true);
if (HasNSW) S->setHasNoSignedWrap(true);
return S;
@@ -2525,31 +2598,28 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
if (Accum->isLoopInvariant(L) ||
(isa<SCEVAddRecExpr>(Accum) &&
cast<SCEVAddRecExpr>(Accum)->getLoop() == L)) {
+ bool HasNUW = false;
+ bool HasNSW = false;
+
+ // If the increment doesn't overflow, then neither the addrec nor
+ // the post-increment will overflow.
+ if (const AddOperator *OBO = dyn_cast<AddOperator>(BEValueV)) {
+ if (OBO->hasNoUnsignedWrap())
+ HasNUW = true;
+ if (OBO->hasNoSignedWrap())
+ HasNSW = true;
+ }
+
const SCEV *StartVal =
getSCEV(PN->getIncomingValue(IncomingEdge));
- const SCEVAddRecExpr *PHISCEV =
- cast<SCEVAddRecExpr>(getAddRecExpr(StartVal, Accum, L));
-
- // If the increment doesn't overflow, then neither the addrec nor the
- // post-increment will overflow.
- if (const AddOperator *OBO = dyn_cast<AddOperator>(BEValueV))
- if (OBO->getOperand(0) == PN &&
- getSCEV(OBO->getOperand(1)) ==
- PHISCEV->getStepRecurrence(*this)) {
- const SCEVAddRecExpr *PostInc = PHISCEV->getPostIncExpr(*this);
- if (OBO->hasNoUnsignedWrap()) {
- const_cast<SCEVAddRecExpr *>(PHISCEV)
- ->setHasNoUnsignedWrap(true);
- const_cast<SCEVAddRecExpr *>(PostInc)
- ->setHasNoUnsignedWrap(true);
- }
- if (OBO->hasNoSignedWrap()) {
- const_cast<SCEVAddRecExpr *>(PHISCEV)
- ->setHasNoSignedWrap(true);
- const_cast<SCEVAddRecExpr *>(PostInc)
- ->setHasNoSignedWrap(true);
- }
- }
+ const SCEV *PHISCEV =
+ getAddRecExpr(StartVal, Accum, L, HasNUW, HasNSW);
+
+ // Since the no-wrap flags are on the increment, they apply to the
+ // post-incremented value as well.
+ if (Accum->isLoopInvariant(L))
+ (void)getAddRecExpr(getAddExpr(StartVal, Accum),
+ Accum, L, HasNUW, HasNSW);
// Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and purge all of the
@@ -2781,26 +2851,29 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) {
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
const SCEV *T = getBackedgeTakenCount(AddRec->getLoop());
const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
- if (!Trip) return FullSet;
+ ConstantRange ConservativeResult = FullSet;
+
+ // If there's no unsigned wrap, the value will never be less than its
+ // initial value.
+ if (AddRec->hasNoUnsignedWrap())
+ if (const SCEVConstant *C = dyn_cast<SCEVConstant>(AddRec->getStart()))
+ ConservativeResult =
+ ConstantRange(C->getValue()->getValue(),
+ APInt(getTypeSizeInBits(C->getType()), 0));
// TODO: non-affine addrec
- if (AddRec->isAffine()) {
+ if (Trip && AddRec->isAffine()) {
const Type *Ty = AddRec->getType();
const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop());
if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) {
MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty);
const SCEV *Start = AddRec->getStart();
- const SCEV *Step = AddRec->getStepRecurrence(*this);
const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this);
// Check for overflow.
- // TODO: This is very conservative.
- if (!(Step->isOne() &&
- isKnownPredicate(ICmpInst::ICMP_ULT, Start, End)) &&
- !(Step->isAllOnesValue() &&
- isKnownPredicate(ICmpInst::ICMP_UGT, Start, End)))
- return FullSet;
+ if (!AddRec->hasNoUnsignedWrap())
+ return ConservativeResult;
ConstantRange StartRange = getUnsignedRange(Start);
ConstantRange EndRange = getUnsignedRange(End);
@@ -2809,10 +2882,12 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) {
APInt Max = APIntOps::umax(StartRange.getUnsignedMax(),
EndRange.getUnsignedMax());
if (Min.isMinValue() && Max.isMaxValue())
- return FullSet;
+ return ConservativeResult;
return ConstantRange(Min, Max+1);
}
}
+
+ return ConservativeResult;
}
if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
@@ -2891,26 +2966,39 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
const SCEV *T = getBackedgeTakenCount(AddRec->getLoop());
const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
- if (!Trip) return FullSet;
+ ConstantRange ConservativeResult = FullSet;
+
+ // If there's no signed wrap, and all the operands have the same sign or
+ // zero, the value won't ever change sign.
+ if (AddRec->hasNoSignedWrap()) {
+ bool AllNonNeg = true;
+ bool AllNonPos = true;
+ for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
+ if (!isKnownNonNegative(AddRec->getOperand(i))) AllNonNeg = false;
+ if (!isKnownNonPositive(AddRec->getOperand(i))) AllNonPos = false;
+ }
+ unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
+ if (AllNonNeg)
+ ConservativeResult = ConstantRange(APInt(BitWidth, 0),
+ APInt::getSignedMinValue(BitWidth));
+ else if (AllNonPos)
+ ConservativeResult = ConstantRange(APInt::getSignedMinValue(BitWidth),
+ APInt(BitWidth, 1));
+ }
// TODO: non-affine addrec
- if (AddRec->isAffine()) {
+ if (Trip && AddRec->isAffine()) {
const Type *Ty = AddRec->getType();
const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop());
if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) {
MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty);
const SCEV *Start = AddRec->getStart();
- const SCEV *Step = AddRec->getStepRecurrence(*this);
const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this);
// Check for overflow.
- // TODO: This is very conservative.
- if (!(Step->isOne() &&
- isKnownPredicate(ICmpInst::ICMP_SLT, Start, End)) &&
- !(Step->isAllOnesValue() &&
- isKnownPredicate(ICmpInst::ICMP_SGT, Start, End)))
- return FullSet;
+ if (!AddRec->hasNoSignedWrap())
+ return ConservativeResult;
ConstantRange StartRange = getSignedRange(Start);
ConstantRange EndRange = getSignedRange(End);
@@ -2919,15 +3007,19 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
APInt Max = APIntOps::smax(StartRange.getSignedMax(),
EndRange.getSignedMax());
if (Min.isMinSignedValue() && Max.isMaxSignedValue())
- return FullSet;
+ return ConservativeResult;
return ConstantRange(Min, Max+1);
}
}
+
+ return ConservativeResult;
}
if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
// For a SCEVUnknown, ask ValueTracking.
unsigned BitWidth = getTypeSizeInBits(U->getType());
+ if (!U->getValue()->getType()->isInteger() && !TD)
+ return FullSet;
unsigned NS = ComputeNumSignBits(U->getValue(), TD);
if (NS == 1)
return FullSet;
@@ -5167,6 +5259,7 @@ ScalarEvolution::ScalarEvolution()
bool ScalarEvolution::runOnFunction(Function &F) {
this->F = &F;
LI = &getAnalysis<LoopInfo>();
+ DT = &getAnalysis<DominatorTree>();
TD = getAnalysisIfAvailable<TargetData>();
return false;
}
@@ -5183,6 +5276,7 @@ void ScalarEvolution::releaseMemory() {
void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequiredTransitive<LoopInfo>();
+ AU.addRequiredTransitive<DominatorTree>();
}
bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) {
diff --git a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index ef0e97b..498c4a8 100644
--- a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -32,6 +32,16 @@ namespace {
static char ID; // Class identification, replacement for typeinfo
ScalarEvolutionAliasAnalysis() : FunctionPass(&ID), SE(0) {}
+ /// getAdjustedAnalysisPointer - This method is used when a pass implements
+ /// an analysis interface through multiple inheritance. If needed, it
+ /// should override this to adjust the this pointer as needed for the
+ /// specified pass info.
+ virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) {
+ if (PI->isPassID(&AliasAnalysis::ID))
+ return (AliasAnalysis*)this;
+ return this;
+ }
+
private:
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnFunction(Function &F);
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index 7157d47..a72f58f 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -81,7 +81,7 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) {
Instruction *I = CastInst::Create(Op, V, Ty, V->getName(),
A->getParent()->getEntryBlock().begin());
- InsertedValues.insert(I);
+ rememberInstruction(I);
return I;
}
@@ -98,14 +98,16 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) {
It = cast<InvokeInst>(I)->getNormalDest()->begin();
while (isa<PHINode>(It)) ++It;
if (It != BasicBlock::iterator(CI)) {
- // Recreate the cast at the beginning of the entry block.
+ // Recreate the cast after the user.
// The old cast is left in place in case it is being used
// as an insert point.
Instruction *NewCI = CastInst::Create(Op, V, Ty, "", It);
NewCI->takeName(CI);
CI->replaceAllUsesWith(NewCI);
+ rememberInstruction(NewCI);
return NewCI;
}
+ rememberInstruction(CI);
return CI;
}
}
@@ -114,7 +116,7 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) {
IP = II->getNormalDest()->begin();
while (isa<PHINode>(IP)) ++IP;
Instruction *CI = CastInst::Create(Op, V, Ty, V->getName(), IP);
- InsertedValues.insert(CI);
+ rememberInstruction(CI);
return CI;
}
@@ -144,7 +146,7 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode,
// If we haven't found this binop, insert it.
Value *BO = Builder.CreateBinOp(Opcode, LHS, RHS, "tmp");
- InsertedValues.insert(BO);
+ rememberInstruction(BO);
return BO;
}
@@ -323,7 +325,7 @@ static void SplitAddRecs(SmallVectorImpl<const SCEV *> &Ops,
/// http://llvm.org/docs/LangRef.html#pointeraliasing
/// for details.
///
-/// Design note: The correctness of using getelmeentptr here depends on
+/// Design note: The correctness of using getelementptr here depends on
/// ScalarEvolution not recognizing inttoptr and ptrtoint operators, as
/// they may introduce pointer arithmetic which may not be safely converted
/// into getelementptr.
@@ -491,22 +493,39 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin,
// Emit a GEP.
Value *GEP = Builder.CreateGEP(V, Idx, "uglygep");
- InsertedValues.insert(GEP);
+ rememberInstruction(GEP);
return GEP;
}
// Insert a pretty getelementptr. Note that this GEP is not marked inbounds,
// because ScalarEvolution may have changed the address arithmetic to
// compute a value which is beyond the end of the allocated object.
- Value *GEP = Builder.CreateGEP(V,
+ Value *Casted = V;
+ if (V->getType() != PTy)
+ Casted = InsertNoopCastOfTo(Casted, PTy);
+ Value *GEP = Builder.CreateGEP(Casted,
GepIndices.begin(),
GepIndices.end(),
"scevgep");
Ops.push_back(SE.getUnknown(GEP));
- InsertedValues.insert(GEP);
+ rememberInstruction(GEP);
return expand(SE.getAddExpr(Ops));
}
+/// isNonConstantNegative - Return true if the specified scev is negated, but
+/// not a constant.
+static bool isNonConstantNegative(const SCEV *F) {
+ const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(F);
+ if (!Mul) return false;
+
+ // If there is a constant factor, it will be first.
+ const SCEVConstant *SC = dyn_cast<SCEVConstant>(Mul->getOperand(0));
+ if (!SC) return false;
+
+ // Return true if the value is negative, this matches things like (-42 * V).
+ return SC->getValue()->getValue().isNegative();
+}
+
Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
int NumOperands = S->getNumOperands();
const Type *Ty = SE.getEffectiveSCEVType(S->getType());
@@ -539,8 +558,14 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
// Emit a bunch of add instructions
for (int i = NumOperands-1; i >= 0; --i) {
if (i == PIdx) continue;
- Value *W = expandCodeFor(S->getOperand(i), Ty);
- V = InsertBinop(Instruction::Add, V, W);
+ const SCEV *Op = S->getOperand(i);
+ if (isNonConstantNegative(Op)) {
+ Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty);
+ V = InsertBinop(Instruction::Sub, V, W);
+ } else {
+ Value *W = expandCodeFor(Op, Ty);
+ V = InsertBinop(Instruction::Add, V, W);
+ }
}
return V;
}
@@ -603,7 +628,175 @@ static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest,
}
}
+/// getAddRecExprPHILiterally - Helper for expandAddRecExprLiterally. Expand
+/// the base addrec, which is the addrec without any non-loop-dominating
+/// values, and return the PHI.
+PHINode *
+SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
+ const Loop *L,
+ const Type *ExpandTy,
+ const Type *IntTy) {
+ // Reuse a previously-inserted PHI, if present.
+ for (BasicBlock::iterator I = L->getHeader()->begin();
+ PHINode *PN = dyn_cast<PHINode>(I); ++I)
+ if (isInsertedInstruction(PN) && SE.getSCEV(PN) == Normalized)
+ return PN;
+
+ // Save the original insertion point so we can restore it when we're done.
+ BasicBlock *SaveInsertBB = Builder.GetInsertBlock();
+ BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();
+
+ // Expand code for the start value.
+ Value *StartV = expandCodeFor(Normalized->getStart(), ExpandTy,
+ L->getHeader()->begin());
+
+ // Expand code for the step value. Insert instructions right before the
+ // terminator corresponding to the back-edge. Do this before creating the PHI
+ // so that PHI reuse code doesn't see an incomplete PHI. If the stride is
+ // negative, insert a sub instead of an add for the increment (unless it's a
+ // constant, because subtracts of constants are canonicalized to adds).
+ const SCEV *Step = Normalized->getStepRecurrence(SE);
+ bool isPointer = isa<PointerType>(ExpandTy);
+ bool isNegative = !isPointer && isNonConstantNegative(Step);
+ if (isNegative)
+ Step = SE.getNegativeSCEV(Step);
+ Value *StepV = expandCodeFor(Step, IntTy, L->getHeader()->begin());
+
+ // Create the PHI.
+ Builder.SetInsertPoint(L->getHeader(), L->getHeader()->begin());
+ PHINode *PN = Builder.CreatePHI(ExpandTy, "lsr.iv");
+ rememberInstruction(PN);
+
+ // Create the step instructions and populate the PHI.
+ BasicBlock *Header = L->getHeader();
+ for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header);
+ HPI != HPE; ++HPI) {
+ BasicBlock *Pred = *HPI;
+
+ // Add a start value.
+ if (!L->contains(Pred)) {
+ PN->addIncoming(StartV, Pred);
+ continue;
+ }
+
+ // Create a step value and add it to the PHI. If IVIncInsertLoop is
+ // non-null and equal to the addrec's loop, insert the instructions
+ // at IVIncInsertPos.
+ Instruction *InsertPos = L == IVIncInsertLoop ?
+ IVIncInsertPos : Pred->getTerminator();
+ Builder.SetInsertPoint(InsertPos->getParent(), InsertPos);
+ Value *IncV;
+ // If the PHI is a pointer, use a GEP, otherwise use an add or sub.
+ if (isPointer) {
+ const PointerType *GEPPtrTy = cast<PointerType>(ExpandTy);
+ // If the step isn't constant, don't use an implicitly scaled GEP, because
+ // that would require a multiply inside the loop.
+ if (!isa<ConstantInt>(StepV))
+ GEPPtrTy = PointerType::get(Type::getInt1Ty(SE.getContext()),
+ GEPPtrTy->getAddressSpace());
+ const SCEV *const StepArray[1] = { SE.getSCEV(StepV) };
+ IncV = expandAddToGEP(StepArray, StepArray+1, GEPPtrTy, IntTy, PN);
+ if (IncV->getType() != PN->getType()) {
+ IncV = Builder.CreateBitCast(IncV, PN->getType(), "tmp");
+ rememberInstruction(IncV);
+ }
+ } else {
+ IncV = isNegative ?
+ Builder.CreateSub(PN, StepV, "lsr.iv.next") :
+ Builder.CreateAdd(PN, StepV, "lsr.iv.next");
+ rememberInstruction(IncV);
+ }
+ PN->addIncoming(IncV, Pred);
+ }
+
+ // Restore the original insert point.
+ if (SaveInsertBB)
+ Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);
+
+ // Remember this PHI, even in post-inc mode.
+ InsertedValues.insert(PN);
+
+ return PN;
+}
+
+Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) {
+ const Type *STy = S->getType();
+ const Type *IntTy = SE.getEffectiveSCEVType(STy);
+ const Loop *L = S->getLoop();
+
+ // Determine a normalized form of this expression, which is the expression
+ // before any post-inc adjustment is made.
+ const SCEVAddRecExpr *Normalized = S;
+ if (L == PostIncLoop) {
+ const SCEV *Step = S->getStepRecurrence(SE);
+ Normalized = cast<SCEVAddRecExpr>(SE.getMinusSCEV(S, Step));
+ }
+
+ // Strip off any non-loop-dominating component from the addrec start.
+ const SCEV *Start = Normalized->getStart();
+ const SCEV *PostLoopOffset = 0;
+ if (!Start->properlyDominates(L->getHeader(), SE.DT)) {
+ PostLoopOffset = Start;
+ Start = SE.getIntegerSCEV(0, Normalized->getType());
+ Normalized =
+ cast<SCEVAddRecExpr>(SE.getAddRecExpr(Start,
+ Normalized->getStepRecurrence(SE),
+ Normalized->getLoop()));
+ }
+
+ // Strip off any non-loop-dominating component from the addrec step.
+ const SCEV *Step = Normalized->getStepRecurrence(SE);
+ const SCEV *PostLoopScale = 0;
+ if (!Step->hasComputableLoopEvolution(L) &&
+ !Step->dominates(L->getHeader(), SE.DT)) {
+ PostLoopScale = Step;
+ Step = SE.getIntegerSCEV(1, Normalized->getType());
+ Normalized =
+ cast<SCEVAddRecExpr>(SE.getAddRecExpr(Start, Step,
+ Normalized->getLoop()));
+ }
+
+ // Expand the core addrec. If we need post-loop scaling, force it to
+ // expand to an integer type to avoid the need for additional casting.
+ const Type *ExpandTy = PostLoopScale ? IntTy : STy;
+ PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy);
+
+ // Accomodate post-inc mode, if necessary.
+ Value *Result;
+ if (L != PostIncLoop)
+ Result = PN;
+ else {
+ // In PostInc mode, use the post-incremented value.
+ BasicBlock *LatchBlock = L->getLoopLatch();
+ assert(LatchBlock && "PostInc mode requires a unique loop latch!");
+ Result = PN->getIncomingValueForBlock(LatchBlock);
+ }
+
+ // Re-apply any non-loop-dominating scale.
+ if (PostLoopScale) {
+ Result = Builder.CreateMul(Result,
+ expandCodeFor(PostLoopScale, IntTy));
+ rememberInstruction(Result);
+ }
+
+ // Re-apply any non-loop-dominating offset.
+ if (PostLoopOffset) {
+ if (const PointerType *PTy = dyn_cast<PointerType>(ExpandTy)) {
+ const SCEV *const OffsetArray[1] = { PostLoopOffset };
+ Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result);
+ } else {
+ Result = Builder.CreateAdd(Result,
+ expandCodeFor(PostLoopOffset, IntTy));
+ rememberInstruction(Result);
+ }
+ }
+
+ return Result;
+}
+
Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
+ if (!CanonicalMode) return expandAddRecExprLiterally(S);
+
const Type *Ty = SE.getEffectiveSCEVType(S->getType());
const Loop *L = S->getLoop();
@@ -681,17 +874,17 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
// specified loop.
BasicBlock *Header = L->getHeader();
PHINode *PN = PHINode::Create(Ty, "indvar", Header->begin());
- InsertedValues.insert(PN);
+ rememberInstruction(PN);
Constant *One = ConstantInt::get(Ty, 1);
for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header);
HPI != HPE; ++HPI)
if (L->contains(*HPI)) {
- // Insert a unit add instruction right before the terminator corresponding
- // to the back-edge.
+ // Insert a unit add instruction right before the terminator
+ // corresponding to the back-edge.
Instruction *Add = BinaryOperator::CreateAdd(PN, One, "indvar.next",
(*HPI)->getTerminator());
- InsertedValues.insert(Add);
+ rememberInstruction(Add);
PN->addIncoming(Add, *HPI);
} else {
PN->addIncoming(Constant::getNullValue(Ty), *HPI);
@@ -738,7 +931,7 @@ Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) {
Value *V = expandCodeFor(S->getOperand(),
SE.getEffectiveSCEVType(S->getOperand()->getType()));
Value *I = Builder.CreateTrunc(V, Ty, "tmp");
- InsertedValues.insert(I);
+ rememberInstruction(I);
return I;
}
@@ -747,7 +940,7 @@ Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) {
Value *V = expandCodeFor(S->getOperand(),
SE.getEffectiveSCEVType(S->getOperand()->getType()));
Value *I = Builder.CreateZExt(V, Ty, "tmp");
- InsertedValues.insert(I);
+ rememberInstruction(I);
return I;
}
@@ -756,7 +949,7 @@ Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) {
Value *V = expandCodeFor(S->getOperand(),
SE.getEffectiveSCEVType(S->getOperand()->getType()));
Value *I = Builder.CreateSExt(V, Ty, "tmp");
- InsertedValues.insert(I);
+ rememberInstruction(I);
return I;
}
@@ -772,9 +965,9 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) {
}
Value *RHS = expandCodeFor(S->getOperand(i), Ty);
Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp");
- InsertedValues.insert(ICmp);
+ rememberInstruction(ICmp);
Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smax");
- InsertedValues.insert(Sel);
+ rememberInstruction(Sel);
LHS = Sel;
}
// In the case of mixed integer and pointer types, cast the
@@ -796,9 +989,9 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) {
}
Value *RHS = expandCodeFor(S->getOperand(i), Ty);
Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp");
- InsertedValues.insert(ICmp);
+ rememberInstruction(ICmp);
Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umax");
- InsertedValues.insert(Sel);
+ rememberInstruction(Sel);
LHS = Sel;
}
// In the case of mixed integer and pointer types, cast the
@@ -863,7 +1056,8 @@ Value *SCEVExpander::expand(const SCEV *S) {
Value *V = visit(S);
// Remember the expanded value for this SCEV at this location.
- InsertedExpressions[std::make_pair(S, InsertPt)] = V;
+ if (!PostIncLoop)
+ InsertedExpressions[std::make_pair(S, InsertPt)] = V;
Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);
return V;
diff --git a/lib/Archive/Makefile b/lib/Archive/Makefile
index da97804..1256e1c 100644
--- a/lib/Archive/Makefile
+++ b/lib/Archive/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../..
LIBRARYNAME = LLVMArchive
+CXXFLAGS = -fno-rtti
# We only want an archive so only those modules actually used by a tool are
# included.
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 8ad658d..2a926d2 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -558,7 +558,6 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(readnone);
KEYWORD(readonly);
- KEYWORD(inlinehint);
KEYWORD(noinline);
KEYWORD(alwaysinline);
KEYWORD(optsize);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index e4039ab..04a5263c 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -947,7 +947,6 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) {
case lltok::kw_noinline: Attrs |= Attribute::NoInline; break;
case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break;
case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break;
- case lltok::kw_inlinehint: Attrs |= Attribute::InlineHint; break;
case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break;
case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break;
case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break;
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index bea0593..85c07ff 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -29,7 +29,6 @@ namespace llvm {
class Instruction;
class Constant;
class GlobalValue;
- class MetadataBase;
class MDString;
class MDNode;
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 7f1807c..80eb194 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -85,7 +85,6 @@ namespace lltok {
kw_readnone,
kw_readonly,
- kw_inlinehint,
kw_noinline,
kw_alwaysinline,
kw_optsize,
diff --git a/lib/AsmParser/Makefile b/lib/AsmParser/Makefile
index 995bb0e..7b53a87 100644
--- a/lib/AsmParser/Makefile
+++ b/lib/AsmParser/Makefile
@@ -10,5 +10,6 @@
LEVEL = ../..
LIBRARYNAME := LLVMAsmParser
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/AsmParser/Parser.cpp b/lib/AsmParser/Parser.cpp
index 331a233..aac4027 100644
--- a/lib/AsmParser/Parser.cpp
+++ b/lib/AsmParser/Parser.cpp
@@ -45,7 +45,8 @@ Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err,
MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
if (F == 0) {
Err = SMDiagnostic("", -1, -1,
- "Could not open input file '" + Filename + "'", "");
+ "Could not open input file '" + Filename + "': " +
+ ErrorStr, "");
return 0;
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index aabbc90..2549a51 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1167,7 +1167,7 @@ bool BitcodeReader::ParseConstants() {
Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
- if (OpTy->isFloatingPoint())
+ if (OpTy->isFPOrFPVector())
V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
else
V = ConstantExpr::getICmp(Record[3], Op0, Op1);
diff --git a/lib/Bitcode/Reader/Makefile b/lib/Bitcode/Reader/Makefile
index 59af8d53..0aae3bf 100644
--- a/lib/Bitcode/Reader/Makefile
+++ b/lib/Bitcode/Reader/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMBitReader
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Bitcode/Writer/Makefile b/lib/Bitcode/Writer/Makefile
index 7b0bd72..5f9742e 100644
--- a/lib/Bitcode/Writer/Makefile
+++ b/lib/Bitcode/Writer/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMBitWriter
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index cb139e5..c46d735 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -140,7 +140,7 @@ void ValueEnumerator::setInstructionID(const Instruction *I) {
}
unsigned ValueEnumerator::getValueID(const Value *V) const {
- if (isa<MetadataBase>(V)) {
+ if (isa<MDNode>(V) || isa<MDString>(V)) {
ValueMapType::const_iterator I = MDValueMap.find(V);
assert(I != MDValueMap.end() && "Value not in slotcalculator!");
return I->second-1;
@@ -229,7 +229,8 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) {
MDValueMap[MD] = Values.size();
}
-void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) {
+void ValueEnumerator::EnumerateMetadata(const Value *MD) {
+ assert((isa<MDNode>(MD) || isa<MDString>(MD)) && "Invalid metadata kind");
// Check to see if it's already in!
unsigned &MDValueID = MDValueMap[MD];
if (MDValueID) {
@@ -262,8 +263,8 @@ void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) {
void ValueEnumerator::EnumerateValue(const Value *V) {
assert(!V->getType()->isVoidTy() && "Can't insert void values!");
- if (const MetadataBase *MB = dyn_cast<MetadataBase>(V))
- return EnumerateMetadata(MB);
+ if (isa<MDNode>(V) || isa<MDString>(V))
+ return EnumerateMetadata(V);
else if (const NamedMDNode *NMD = dyn_cast<NamedMDNode>(V))
return EnumerateNamedMDNode(NMD);
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index c50fe9c..4f8ebf5 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -127,7 +127,7 @@ public:
private:
void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
- void EnumerateMetadata(const MetadataBase *MD);
+ void EnumerateMetadata(const Value *MD);
void EnumerateNamedMDNode(const NamedMDNode *NMD);
void EnumerateValue(const Value *V);
void EnumerateType(const Type *T);
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 876f628..f4d8864 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -16,6 +16,7 @@
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
+#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -23,18 +24,19 @@
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
@@ -43,7 +45,6 @@
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
#include <cerrno>
using namespace llvm;
@@ -51,6 +52,15 @@ static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
cl::init(cl::BOU_UNSET));
+static bool getVerboseAsm(bool VDef) {
+ switch (AsmVerbose) {
+ default:
+ case cl::BOU_UNSET: return VDef;
+ case cl::BOU_TRUE: return true;
+ case cl::BOU_FALSE: return false;
+ }
+}
+
char AsmPrinter::ID = 0;
AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
const MCAsmInfo *T, bool VDef)
@@ -59,16 +69,13 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
OutContext(*new MCContext()),
// FIXME: Pass instprinter to streamer.
- OutStreamer(*createAsmStreamer(OutContext, O, *T, 0)),
+ OutStreamer(*createAsmStreamer(OutContext, O, *T,
+ TM.getTargetData()->isLittleEndian(),
+ getVerboseAsm(VDef), 0)),
- LastMI(0), LastFn(0), Counter(~0U),
- PrevDLT(0, 0, ~0U, ~0U) {
+ LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
DW = 0; MMI = 0;
- switch (AsmVerbose) {
- case cl::BOU_UNSET: VerboseAsm = VDef; break;
- case cl::BOU_TRUE: VerboseAsm = true; break;
- case cl::BOU_FALSE: VerboseAsm = false; break;
- }
+ VerboseAsm = getVerboseAsm(VDef);
}
AsmPrinter::~AsmPrinter() {
@@ -103,22 +110,15 @@ bool AsmPrinter::doInitialization(Module &M) {
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- Mang = new Mangler(M, MAI->getGlobalPrefix(), MAI->getPrivateGlobalPrefix(),
- MAI->getLinkerPrivateGlobalPrefix());
-
- if (MAI->doesAllowQuotesInName())
- Mang->setUseQuotes(true);
-
- if (MAI->doesAllowNameToStartWithDigit())
- Mang->setSymbolsCanStartWithDigit(true);
+ Mang = new Mangler(*MAI);
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
if (MAI->hasSingleParameterDotFile()) {
- /* Very minimal debug info. It is ignored if we emit actual
- debug info. If we don't, this at least helps the user find where
- a function came from. */
+ // Very minimal debug info. It is ignored if we emit actual
+ // debug info. If we don't, this at least helps the user find where
+ // a function came from.
O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n";
}
@@ -144,11 +144,148 @@ bool AsmPrinter::doInitialization(Module &M) {
return false;
}
+/// EmitGlobalVariable - Emit the specified global variable to the .s file.
+void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ if (!GV->hasInitializer()) // External globals require no code.
+ return;
+
+ // Check to see if this is a special global used by LLVM, if so, emit it.
+ if (EmitSpecialLLVMGlobal(GV))
+ return;
+
+ MCSymbol *GVSym = GetGlobalValueSymbol(GV);
+ printVisibility(GVSym, GV->getVisibility());
+
+ if (MAI->hasDotTypeDotSizeDirective()) {
+ O << "\t.type\t" << *GVSym;
+ if (MAI->getCommentString()[0] != '@')
+ O << ",@object\n";
+ else
+ O << ",%object\n";
+ }
+
+ SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
+
+ const TargetData *TD = TM.getTargetData();
+ unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType());
+ unsigned AlignLog = TD->getPreferredAlignmentLog(GV);
+
+ // Handle common and BSS local symbols (.lcomm).
+ if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+
+ if (VerboseAsm) {
+ WriteAsOperand(OutStreamer.GetCommentOS(), GV,
+ /*PrintType=*/false, GV->getParent());
+ OutStreamer.GetCommentOS() << '\n';
+ }
+
+ // Handle common symbols.
+ if (GVKind.isCommon()) {
+ // .comm _foo, 42, 4
+ OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog);
+ return;
+ }
+
+ // Handle local BSS symbols.
+ if (MAI->hasMachoZeroFillDirective()) {
+ const MCSection *TheSection =
+ getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+ // .zerofill __DATA, __bss, _foo, 400, 5
+ OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
+ return;
+ }
+
+ if (MAI->hasLCOMMDirective()) {
+ // .lcomm _foo, 42
+ OutStreamer.EmitLocalCommonSymbol(GVSym, Size);
+ return;
+ }
+
+ // .local _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Local);
+ // .comm _foo, 42, 4
+ OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog);
+ return;
+ }
+
+ const MCSection *TheSection =
+ getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+
+ // Handle the zerofill directive on darwin, which is a special form of BSS
+ // emission.
+ if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+ // .zerofill __DATA, __common, _foo, 400, 5
+ OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
+ return;
+ }
+
+ OutStreamer.SwitchSection(TheSection);
+
+ // TODO: Factor into an 'emit linkage' thing that is shared with function
+ // bodies.
+ switch (GV->getLinkage()) {
+ case GlobalValue::CommonLinkage:
+ case GlobalValue::LinkOnceAnyLinkage:
+ case GlobalValue::LinkOnceODRLinkage:
+ case GlobalValue::WeakAnyLinkage:
+ case GlobalValue::WeakODRLinkage:
+ case GlobalValue::LinkerPrivateLinkage:
+ if (MAI->getWeakDefDirective() != 0) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+ // .weak_definition _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
+ } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+ // .linkonce same_size
+ O << LinkOnce;
+ } else {
+ // .weak _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
+ }
+ break;
+ case GlobalValue::DLLExportLinkage:
+ case GlobalValue::AppendingLinkage:
+ // FIXME: appending linkage variables should go into a section of
+ // their name or something. For now, just emit them as external.
+ case GlobalValue::ExternalLinkage:
+ // If external or appending, declare as a global symbol.
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+ break;
+ case GlobalValue::PrivateLinkage:
+ case GlobalValue::InternalLinkage:
+ break;
+ default:
+ llvm_unreachable("Unknown linkage type!");
+ }
+
+ EmitAlignment(AlignLog, GV);
+ if (VerboseAsm) {
+ WriteAsOperand(OutStreamer.GetCommentOS(), GV,
+ /*PrintType=*/false, GV->getParent());
+ OutStreamer.GetCommentOS() << '\n';
+ }
+ OutStreamer.EmitLabel(GVSym);
+
+ EmitGlobalConstant(GV->getInitializer());
+
+ if (MAI->hasDotTypeDotSizeDirective())
+ O << "\t.size\t" << *GVSym << ", " << Size << '\n';
+
+ OutStreamer.AddBlankLine();
+}
+
+
bool AsmPrinter::doFinalization(Module &M) {
// Emit global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
- PrintGlobalVariable(I);
+ EmitGlobalVariable(I);
// Emit final debug information.
if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling())
@@ -164,35 +301,37 @@ bool AsmPrinter::doFinalization(Module &M) {
// Print out module-level global variables here.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
- if (I->hasExternalWeakLinkage())
- O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n';
+ if (!I->hasExternalWeakLinkage()) continue;
+ OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I),
+ MCSA_WeakReference);
}
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
- if (I->hasExternalWeakLinkage())
- O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n';
+ if (!I->hasExternalWeakLinkage()) continue;
+ OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I),
+ MCSA_WeakReference);
}
}
if (MAI->getSetDirective()) {
- O << '\n';
+ OutStreamer.AddBlankLine();
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) {
- std::string Name = Mang->getMangledName(I);
+ MCSymbol *Name = GetGlobalValueSymbol(I);
const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal());
- std::string Target = Mang->getMangledName(GV);
+ MCSymbol *Target = GetGlobalValueSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
- O << "\t.globl\t" << Name << '\n';
+ OutStreamer.EmitSymbolAttribute(Name, MCSA_Global);
else if (I->hasWeakLinkage())
- O << MAI->getWeakRefDirective() << Name << '\n';
- else if (!I->hasLocalLinkage())
- llvm_unreachable("Invalid alias linkage");
+ OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference);
+ else
+ assert(I->hasLocalLinkage() && "Invalid alias linkage");
printVisibility(Name, I->getVisibility());
- O << MAI->getSetDirective() << ' ' << Name << ", " << Target << '\n';
+ O << MAI->getSetDirective() << ' ' << *Name << ", " << *Target << '\n';
}
}
@@ -206,9 +345,8 @@ bool AsmPrinter::doFinalization(Module &M) {
// to be executable. Some targets have a directive to declare this.
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
- if (MAI->getNonexecutableStackDirective())
- O << MAI->getNonexecutableStackDirective() << '\n';
-
+ if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
+ OutStreamer.SwitchSection(S);
// Allow the target to emit any magic that it wants at the end of the file,
// after everything else has gone out.
@@ -222,8 +360,8 @@ bool AsmPrinter::doFinalization(Module &M) {
}
void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
- // What's my mangled name?
- CurrentFnName = Mang->getMangledName(MF.getFunction());
+ // Get the function symbol.
+ CurrentFnSym = GetGlobalValueSymbol(MF.getFunction());
IncrementFunctionNumber();
if (VerboseAsm)
@@ -307,19 +445,20 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
// Emit inter-object padding for alignment.
unsigned AlignMask = CPE.getAlignment() - 1;
unsigned NewOffset = (Offset + AlignMask) & ~AlignMask;
- EmitZeros(NewOffset - Offset);
+ OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/);
const Type *Ty = CPE.getType();
Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty);
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
- << CPI << ':';
+ // Emit the label with a comment on it.
if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " constant ";
- WriteTypeSymbolic(O, CPE.getType(), MF->getFunction()->getParent());
+ OutStreamer.GetCommentOS() << "constant pool ";
+ WriteTypeSymbolic(OutStreamer.GetCommentOS(), CPE.getType(),
+ MF->getFunction()->getParent());
+ OutStreamer.GetCommentOS() << '\n';
}
- O << '\n';
+ OutStreamer.EmitLabel(GetCPISymbol(CPI));
+
if (CPE.isMachineConstantPoolEntry())
EmitMachineConstantPoolValue(CPE.Val.MachineCPVal);
else
@@ -381,14 +520,11 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
// before each jump table. The first label is never referenced, but tells
// the assembler and linker the extents of the jump table object. The
// second label is actually referenced by the code.
- if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) {
- O << MAI->getLinkerPrivateGlobalPrefix()
- << "JTI" << getFunctionNumber() << '_' << i << ":\n";
- }
-
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << i << ":\n";
-
+ if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0])
+ OutStreamer.EmitLabel(GetJTISymbol(i, true));
+
+ OutStreamer.EmitLabel(GetJTISymbol(i));
+
for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
printPICJumpTableEntry(MJTI, JTBBs[ii], i);
O << '\n';
@@ -418,17 +554,16 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
// If we're emitting non-PIC code, then emit the entries as direct
// references to the target basic blocks.
if (!isPIC) {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MBB->getNumber());
} else if (MAI->getSetDirective()) {
O << MAI->getPrivateGlobalPrefix() << getFunctionNumber()
<< '_' << uid << "_set_" << MBB->getNumber();
} else {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MBB->getNumber());
// If the arch uses custom Jump Table directives, don't calc relative to
- // JT
+ // JT.
if (!HadJTEntryDirective)
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI"
- << getFunctionNumber() << '_' << uid;
+ O << '-' << *GetJTISymbol(uid);
}
}
@@ -438,7 +573,7 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
/// do nothing and return false.
bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
if (GV->getName() == "llvm.used") {
- if (MAI->getUsedDirective() != 0) // No need to emit this at all.
+ if (MAI->hasNoDeadStrip()) // No need to emit this at all.
EmitLLVMUsedList(GV->getInitializer());
return true;
}
@@ -458,6 +593,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection());
EmitAlignment(Align, 0);
EmitXXStructorList(GV->getInitializer());
+
+ if (TM.getRelocationModel() == Reloc::Static &&
+ MAI->hasStaticCtorDtorReferenceInStaticMode()) {
+ StringRef Sym(".constructors_used");
+ OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym),
+ MCSA_Reference);
+ }
return true;
}
@@ -465,6 +607,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection());
EmitAlignment(Align, 0);
EmitXXStructorList(GV->getInitializer());
+
+ if (TM.getRelocationModel() == Reloc::Static &&
+ MAI->hasStaticCtorDtorReferenceInStaticMode()) {
+ StringRef Sym(".destructors_used");
+ OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym),
+ MCSA_Reference);
+ }
return true;
}
@@ -475,8 +624,6 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
/// global in the specified llvm.used list for which emitUsedDirectiveFor
/// is true, as being used with this directive.
void AsmPrinter::EmitLLVMUsedList(Constant *List) {
- const char *Directive = MAI->getUsedDirective();
-
// Should be an array of 'i8*'.
ConstantArray *InitList = dyn_cast<ConstantArray>(List);
if (InitList == 0) return;
@@ -484,11 +631,9 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) {
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
- if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) {
- O << Directive;
- EmitConstantValueOnly(InitList->getOperand(i));
- O << '\n';
- }
+ if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang))
+ OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(GV),
+ MCSA_NoDeadStrip);
}
}
@@ -510,189 +655,35 @@ void AsmPrinter::EmitXXStructorList(Constant *List) {
}
}
-
-//===----------------------------------------------------------------------===//
-/// LEB 128 number encoding.
-
-/// PrintULEB128 - Print a series of hexadecimal values (separated by commas)
-/// representing an unsigned leb128 value.
-void AsmPrinter::PrintULEB128(unsigned Value) const {
- char Buffer[20];
- do {
- unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
- Value >>= 7;
- if (Value) Byte |= 0x80;
- O << "0x" << utohex_buffer(Byte, Buffer+20);
- if (Value) O << ", ";
- } while (Value);
-}
-
-/// PrintSLEB128 - Print a series of hexadecimal values (separated by commas)
-/// representing a signed leb128 value.
-void AsmPrinter::PrintSLEB128(int Value) const {
- int Sign = Value >> (8 * sizeof(Value) - 1);
- bool IsMore;
- char Buffer[20];
-
- do {
- unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
- Value >>= 7;
- IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
- if (IsMore) Byte |= 0x80;
- O << "0x" << utohex_buffer(Byte, Buffer+20);
- if (IsMore) O << ", ";
- } while (IsMore);
-}
-
//===--------------------------------------------------------------------===//
// Emission and print routines
//
-/// PrintHex - Print a value as a hexadecimal value.
-///
-void AsmPrinter::PrintHex(int Value) const {
- char Buffer[20];
- O << "0x" << utohex_buffer(static_cast<unsigned>(Value), Buffer+20);
-}
-
-/// 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 AsmPrinter::EOL() const {
- O << '\n';
-}
-
-void AsmPrinter::EOL(const std::string &Comment) const {
- if (VerboseAsm && !Comment.empty()) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << ' '
- << Comment;
- }
- O << '\n';
-}
-
-void AsmPrinter::EOL(const char* Comment) const {
- if (VerboseAsm && *Comment) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << ' '
- << Comment;
- }
- O << '\n';
-}
-
-static const char *DecodeDWARFEncoding(unsigned Encoding) {
- switch (Encoding) {
- case dwarf::DW_EH_PE_absptr:
- return "absptr";
- case dwarf::DW_EH_PE_omit:
- return "omit";
- case dwarf::DW_EH_PE_pcrel:
- return "pcrel";
- case dwarf::DW_EH_PE_udata4:
- return "udata4";
- case dwarf::DW_EH_PE_udata8:
- return "udata8";
- case dwarf::DW_EH_PE_sdata4:
- return "sdata4";
- case dwarf::DW_EH_PE_sdata8:
- return "sdata8";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
- return "pcrel udata4";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
- return "pcrel sdata4";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
- return "pcrel udata8";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
- return "pcrel sdata8";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
- return "indirect pcrel udata4";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
- return "indirect pcrel sdata4";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
- return "indirect pcrel udata8";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
- return "indirect pcrel sdata8";
- }
-
- return 0;
-}
-
-void AsmPrinter::EOL(const char *Comment, unsigned Encoding) const {
- if (VerboseAsm && *Comment) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << ' '
- << Comment;
-
- if (const char *EncStr = DecodeDWARFEncoding(Encoding))
- O << " (" << EncStr << ')';
- }
- O << '\n';
-}
-
-/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
-/// unsigned leb128 value.
-void AsmPrinter::EmitULEB128Bytes(unsigned Value) const {
- if (MAI->hasLEB128()) {
- O << "\t.uleb128\t"
- << Value;
- } else {
- O << MAI->getData8bitsDirective();
- PrintULEB128(Value);
- }
-}
-
-/// EmitSLEB128Bytes - print an assembler byte data directive to compose a
-/// signed leb128 value.
-void AsmPrinter::EmitSLEB128Bytes(int Value) const {
- if (MAI->hasLEB128()) {
- O << "\t.sleb128\t"
- << Value;
- } else {
- O << MAI->getData8bitsDirective();
- PrintSLEB128(Value);
- }
-}
-
/// EmitInt8 - Emit a byte directive and value.
///
void AsmPrinter::EmitInt8(int Value) const {
- O << MAI->getData8bitsDirective();
- PrintHex(Value & 0xFF);
+ OutStreamer.EmitIntValue(Value, 1, 0/*addrspace*/);
}
/// EmitInt16 - Emit a short directive and value.
///
void AsmPrinter::EmitInt16(int Value) const {
- O << MAI->getData16bitsDirective();
- PrintHex(Value & 0xFFFF);
+ OutStreamer.EmitIntValue(Value, 2, 0/*addrspace*/);
}
/// EmitInt32 - Emit a long directive and value.
///
void AsmPrinter::EmitInt32(int Value) const {
- O << MAI->getData32bitsDirective();
- PrintHex(Value);
+ OutStreamer.EmitIntValue(Value, 4, 0/*addrspace*/);
}
/// EmitInt64 - Emit a long long directive and value.
///
void AsmPrinter::EmitInt64(uint64_t Value) const {
- if (MAI->getData64bitsDirective()) {
- O << MAI->getData64bitsDirective();
- PrintHex(Value);
- } else {
- if (TM.getTargetData()->isBigEndian()) {
- EmitInt32(unsigned(Value >> 32)); O << '\n';
- EmitInt32(unsigned(Value));
- } else {
- EmitInt32(unsigned(Value)); O << '\n';
- EmitInt32(unsigned(Value >> 32));
- }
- }
+ OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/);
}
+
/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
@@ -725,31 +716,8 @@ static void printStringChar(formatted_raw_ostream &O, unsigned char C) {
}
}
-/// EmitString - Emit a string with quotes and a null terminator.
-/// Special characters are emitted properly.
-/// \literal (Eg. '\t') \endliteral
-void AsmPrinter::EmitString(const StringRef String) const {
- EmitString(String.data(), String.size());
-}
-
-void AsmPrinter::EmitString(const char *String, unsigned Size) const {
- const char* AscizDirective = MAI->getAscizDirective();
- if (AscizDirective)
- O << AscizDirective;
- else
- O << MAI->getAsciiDirective();
- O << '\"';
- for (unsigned i = 0; i < Size; ++i)
- printStringChar(O, String[i]);
- if (AscizDirective)
- O << '\"';
- else
- O << "\\0\"";
-}
-
-
/// EmitFile - Emit a .file directive.
-void AsmPrinter::EmitFile(unsigned Number, const std::string &Name) const {
+void AsmPrinter::EmitFile(unsigned Number, StringRef Name) const {
O << "\t.file\t" << Number << " \"";
for (unsigned i = 0, N = Name.size(); i < N; ++i)
printStringChar(O, Name[i]);
@@ -788,52 +756,26 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV,
OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0);
}
-/// EmitZeros - Emit a block of zeros.
+/// LowerConstant - Lower the specified LLVM Constant to an MCExpr.
///
-void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const {
- if (NumZeros) {
- if (MAI->getZeroDirective()) {
- O << MAI->getZeroDirective() << NumZeros;
- if (MAI->getZeroDirectiveSuffix())
- O << MAI->getZeroDirectiveSuffix();
- O << '\n';
- } else {
- for (; NumZeros; --NumZeros)
- O << MAI->getData8bitsDirective(AddrSpace) << "0\n";
- }
- }
-}
-
-// Print out the specified constant, without a storage class. Only the
-// constants valid in constant expressions can occur here.
-void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
- if (CV->isNullValue() || isa<UndefValue>(CV)) {
- O << '0';
- return;
- }
-
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- O << CI->getZExtValue();
- return;
- }
+static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
+ MCContext &Ctx = AP.OutContext;
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
- // This is a constant address for a global variable or function. Use the
- // name of the variable or function as the address value.
- O << Mang->getMangledName(GV);
- return;
- }
+ if (CV->isNullValue() || isa<UndefValue>(CV))
+ return MCConstantExpr::Create(0, Ctx);
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
+ return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
- if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
- GetBlockAddressSymbol(BA)->print(O, MAI);
- return;
- }
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
+ return MCSymbolRefExpr::Create(AP.GetGlobalValueSymbol(GV), Ctx);
+ if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
+ return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
if (CE == 0) {
- llvm_unreachable("Unknown constant value!");
- O << '0';
- return;
+ llvm_unreachable("Unknown constant value to lower!");
+ return MCConstantExpr::Create(0, Ctx);
}
switch (CE->getOpcode()) {
@@ -845,406 +787,214 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
- default:
- llvm_unreachable("FIXME: Don't support this constant cast expr");
+ default: llvm_unreachable("FIXME: Don't support this constant cast expr");
case Instruction::GetElementPtr: {
- // generate a symbolic expression for the byte address
- const TargetData *TD = TM.getTargetData();
- const Constant *ptrVal = CE->getOperand(0);
- SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
- int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
- idxVec.size());
+ const TargetData &TD = *AP.TM.getTargetData();
+ // Generate a symbolic expression for the byte address
+ const Constant *PtrVal = CE->getOperand(0);
+ SmallVector<Value*, 8> IdxVec(CE->op_begin()+1, CE->op_end());
+ int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0],
+ IdxVec.size());
+
+ const MCExpr *Base = LowerConstant(CE->getOperand(0), AP);
if (Offset == 0)
- return EmitConstantValueOnly(ptrVal);
+ return Base;
// Truncate/sext the offset to the pointer size.
- if (TD->getPointerSizeInBits() != 64) {
- int SExtAmount = 64-TD->getPointerSizeInBits();
+ if (TD.getPointerSizeInBits() != 64) {
+ int SExtAmount = 64-TD.getPointerSizeInBits();
Offset = (Offset << SExtAmount) >> SExtAmount;
}
- if (Offset)
- O << '(';
- EmitConstantValueOnly(ptrVal);
- if (Offset > 0)
- O << ") + " << Offset;
- else
- O << ") - " << -Offset;
- return;
+ return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx),
+ Ctx);
}
+
+ case Instruction::Trunc:
+ // We emit the value and depend on the assembler to truncate the generated
+ // expression properly. This is important for differences between
+ // blockaddress labels. Since the two labels are in the same function, it
+ // is reasonable to treat their delta as a 32-bit value.
+ // FALL THROUGH.
case Instruction::BitCast:
- return EmitConstantValueOnly(CE->getOperand(0));
+ return LowerConstant(CE->getOperand(0), AP);
case Instruction::IntToPtr: {
+ const TargetData &TD = *AP.TM.getTargetData();
// Handle casts to pointers by changing them into casts to the appropriate
// integer type. This promotes constant folding and simplifies this code.
- const TargetData *TD = TM.getTargetData();
Constant *Op = CE->getOperand(0);
- Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()),
+ Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()),
false/*ZExt*/);
- return EmitConstantValueOnly(Op);
+ return LowerConstant(Op, AP);
}
case Instruction::PtrToInt: {
+ const TargetData &TD = *AP.TM.getTargetData();
// Support only foldable casts to/from pointers that can be eliminated by
// changing the pointer to the appropriately sized integer type.
Constant *Op = CE->getOperand(0);
const Type *Ty = CE->getType();
- const TargetData *TD = TM.getTargetData();
+
+ const MCExpr *OpExpr = LowerConstant(Op, AP);
// We can emit the pointer value into this slot if the slot is an
- // integer slot greater or equal to the size of the pointer.
- if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType()))
- return EmitConstantValueOnly(Op);
-
- O << "((";
- EmitConstantValueOnly(Op);
- APInt ptrMask =
- APInt::getAllOnesValue(TD->getTypeAllocSizeInBits(Op->getType()));
-
- SmallString<40> S;
- ptrMask.toStringUnsigned(S);
- O << ") & " << S.str() << ')';
- return;
+ // integer slot equal to the size of the pointer.
+ if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType()))
+ return OpExpr;
+
+ // Otherwise the pointer is smaller than the resultant integer, mask off
+ // the high bits so we are sure to get a proper truncation if the input is
+ // a constant expr.
+ unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType());
+ const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx);
+ return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
}
- case Instruction::Trunc:
- // We emit the value and depend on the assembler to truncate the generated
- // expression properly. This is important for differences between
- // blockaddress labels. Since the two labels are in the same function, it
- // is reasonable to treat their delta as a 32-bit value.
- return EmitConstantValueOnly(CE->getOperand(0));
-
case Instruction::Add:
case Instruction::Sub:
case Instruction::And:
case Instruction::Or:
- case Instruction::Xor:
- O << '(';
- EmitConstantValueOnly(CE->getOperand(0));
- O << ')';
+ case Instruction::Xor: {
+ const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP);
+ const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP);
switch (CE->getOpcode()) {
- case Instruction::Add:
- O << " + ";
- break;
- case Instruction::Sub:
- O << " - ";
- break;
- case Instruction::And:
- O << " & ";
- break;
- case Instruction::Or:
- O << " | ";
- break;
- case Instruction::Xor:
- O << " ^ ";
- break;
- default:
- break;
+ default: llvm_unreachable("Unknown binary operator constant cast expr");
+ case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx);
+ case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
+ case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx);
+ case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx);
+ case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx);
}
- O << '(';
- EmitConstantValueOnly(CE->getOperand(1));
- O << ')';
- break;
}
-}
-
-/// printAsCString - Print the specified array as a C compatible string, only if
-/// the predicate isString is true.
-///
-static void printAsCString(formatted_raw_ostream &O, const ConstantArray *CVA,
- unsigned LastElt) {
- assert(CVA->isString() && "Array is not string compatible!");
-
- O << '\"';
- for (unsigned i = 0; i != LastElt; ++i) {
- unsigned char C =
- (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getZExtValue();
- printStringChar(O, C);
}
- O << '\"';
}
-/// EmitString - Emit a zero-byte-terminated string constant.
-///
-void AsmPrinter::EmitString(const ConstantArray *CVA) const {
- unsigned NumElts = CVA->getNumOperands();
- if (MAI->getAscizDirective() && NumElts &&
- cast<ConstantInt>(CVA->getOperand(NumElts-1))->getZExtValue() == 0) {
- O << MAI->getAscizDirective();
- printAsCString(O, CVA, NumElts-1);
- } else {
- O << MAI->getAsciiDirective();
- printAsCString(O, CVA, NumElts);
+static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace,
+ AsmPrinter &AP) {
+ if (AddrSpace != 0 || !CA->isString()) {
+ // Not a string. Print the values in successive locations
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
+ AP.EmitGlobalConstant(CA->getOperand(i), AddrSpace);
+ return;
}
- O << '\n';
-}
+
+ // Otherwise, it can be emitted as .ascii.
+ SmallVector<char, 128> TmpVec;
+ TmpVec.reserve(CA->getNumOperands());
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
+ TmpVec.push_back(cast<ConstantInt>(CA->getOperand(i))->getZExtValue());
-void AsmPrinter::EmitGlobalConstantArray(const ConstantArray *CVA,
- unsigned AddrSpace) {
- if (CVA->isString()) {
- EmitString(CVA);
- } else { // Not a string. Print the values in successive locations
- for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
- EmitGlobalConstant(CVA->getOperand(i), AddrSpace);
- }
+ AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace);
}
-void AsmPrinter::EmitGlobalConstantVector(const ConstantVector *CP) {
- const VectorType *PTy = CP->getType();
-
- for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
- EmitGlobalConstant(CP->getOperand(I));
+static void EmitGlobalConstantVector(const ConstantVector *CV,
+ unsigned AddrSpace, AsmPrinter &AP) {
+ for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
+ AP.EmitGlobalConstant(CV->getOperand(i), AddrSpace);
}
-void AsmPrinter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
- unsigned AddrSpace) {
+static void EmitGlobalConstantStruct(const ConstantStruct *CS,
+ unsigned AddrSpace, AsmPrinter &AP) {
// Print the fields in successive locations. Pad to align if needed!
- const TargetData *TD = TM.getTargetData();
- unsigned Size = TD->getTypeAllocSize(CVS->getType());
- const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType());
- uint64_t sizeSoFar = 0;
- for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
- const Constant* field = CVS->getOperand(i);
+ const TargetData *TD = AP.TM.getTargetData();
+ unsigned Size = TD->getTypeAllocSize(CS->getType());
+ const StructLayout *Layout = TD->getStructLayout(CS->getType());
+ uint64_t SizeSoFar = 0;
+ for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
+ const Constant *Field = CS->getOperand(i);
// Check if padding is needed and insert one or more 0s.
- uint64_t fieldSize = TD->getTypeAllocSize(field->getType());
- uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1))
- - cvsLayout->getElementOffset(i)) - fieldSize;
- sizeSoFar += fieldSize + padSize;
+ uint64_t FieldSize = TD->getTypeAllocSize(Field->getType());
+ uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1))
+ - Layout->getElementOffset(i)) - FieldSize;
+ SizeSoFar += FieldSize + PadSize;
// Now print the actual field value.
- EmitGlobalConstant(field, AddrSpace);
+ AP.EmitGlobalConstant(Field, AddrSpace);
// Insert padding - this may include padding to increase the size of the
// current field up to the ABI size (if the struct is not packed) as well
// as padding to ensure that the next field starts at the right offset.
- EmitZeros(padSize, AddrSpace);
+ AP.OutStreamer.EmitZeros(PadSize, AddrSpace);
}
- assert(sizeSoFar == cvsLayout->getSizeInBytes() &&
+ assert(SizeSoFar == Layout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
-void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP,
- unsigned AddrSpace) {
+static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
+ AsmPrinter &AP) {
// FP Constants are printed as integer constants to avoid losing
- // precision...
- LLVMContext &Context = CFP->getContext();
- const TargetData *TD = TM.getTargetData();
+ // precision.
if (CFP->getType()->isDoubleTy()) {
- double Val = CFP->getValueAPF().convertToDouble(); // for comment only
- uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
- if (MAI->getData64bitsDirective(AddrSpace)) {
- O << MAI->getData64bitsDirective(AddrSpace) << i;
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " double " << Val;
- }
- O << '\n';
- } else if (TD->isBigEndian()) {
- O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant word of double " << Val;
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant word of double " << Val;
- }
- O << '\n';
- } else {
- O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant word of double " << Val;
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant word of double " << Val;
- }
- O << '\n';
+ if (AP.VerboseAsm) {
+ double Val = CFP->getValueAPF().convertToDouble();
+ AP.OutStreamer.GetCommentOS() << "double " << Val << '\n';
}
+
+ uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
+ AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
return;
}
if (CFP->getType()->isFloatTy()) {
- float Val = CFP->getValueAPF().convertToFloat(); // for comment only
- O << MAI->getData32bitsDirective(AddrSpace)
- << CFP->getValueAPF().bitcastToAPInt().getZExtValue();
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " float " << Val;
+ if (AP.VerboseAsm) {
+ float Val = CFP->getValueAPF().convertToFloat();
+ AP.OutStreamer.GetCommentOS() << "float " << Val << '\n';
}
- O << '\n';
+ uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
+ AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace);
return;
}
if (CFP->getType()->isX86_FP80Ty()) {
// all long double variants are printed as hex
// api needed to prevent premature destruction
- APInt api = CFP->getValueAPF().bitcastToAPInt();
- const uint64_t *p = api.getRawData();
- // Convert to double so we can print the approximate val as a comment.
- APFloat DoubleVal = CFP->getValueAPF();
- bool ignored;
- DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
- &ignored);
- if (TD->isBigEndian()) {
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant halfword of x86_fp80 ~"
- << DoubleVal.convertToDouble();
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant halfword";
- }
- O << '\n';
- } else {
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant halfword of x86_fp80 ~"
- << DoubleVal.convertToDouble();
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next halfword";
- }
- O << '\n';
- O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant halfword";
- }
- O << '\n';
+ APInt API = CFP->getValueAPF().bitcastToAPInt();
+ const uint64_t *p = API.getRawData();
+ if (AP.VerboseAsm) {
+ // Convert to double so we can print the approximate val as a comment.
+ APFloat DoubleVal = CFP->getValueAPF();
+ bool ignored;
+ DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
+ &ignored);
+ AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= "
+ << DoubleVal.convertToDouble() << '\n';
}
- EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) -
- TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace);
+
+ if (AP.TM.getTargetData()->isBigEndian()) {
+ AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
+ } else {
+ AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace);
+ }
+
+ // Emit the tail padding for the long double.
+ const TargetData &TD = *AP.TM.getTargetData();
+ AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
+ TD.getTypeStoreSize(CFP->getType()), AddrSpace);
return;
}
- if (CFP->getType()->isPPC_FP128Ty()) {
- // all long double variants are printed as hex
- // api needed to prevent premature destruction
- APInt api = CFP->getValueAPF().bitcastToAPInt();
- const uint64_t *p = api.getRawData();
- if (TD->isBigEndian()) {
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant word of ppc_fp128";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next word";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next word";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant word";
- }
- O << '\n';
- } else {
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " least significant word of ppc_fp128";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next word";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " next word";
- }
- O << '\n';
- O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << " most significant word";
- }
- O << '\n';
- }
- return;
- } else llvm_unreachable("Floating point constant type not handled");
+ assert(CFP->getType()->isPPC_FP128Ty() &&
+ "Floating point constant type not handled");
+ // All long double variants are printed as hex api needed to prevent
+ // premature destruction.
+ APInt API = CFP->getValueAPF().bitcastToAPInt();
+ const uint64_t *p = API.getRawData();
+ if (AP.TM.getTargetData()->isBigEndian()) {
+ AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
+ } else {
+ AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
+ }
}
-void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI,
- unsigned AddrSpace) {
- const TargetData *TD = TM.getTargetData();
+static void EmitGlobalConstantLargeInt(const ConstantInt *CI,
+ unsigned AddrSpace, AsmPrinter &AP) {
+ const TargetData *TD = AP.TM.getTargetData();
unsigned BitWidth = CI->getBitWidth();
assert((BitWidth & 63) == 0 && "only support multiples of 64-bits");
@@ -1253,100 +1003,58 @@ void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI,
// quantities at a time.
const uint64_t *RawData = CI->getValue().getRawData();
for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
- uint64_t Val;
- if (TD->isBigEndian())
- Val = RawData[e - i - 1];
- else
- Val = RawData[i];
-
- if (MAI->getData64bitsDirective(AddrSpace)) {
- O << MAI->getData64bitsDirective(AddrSpace) << Val << '\n';
- continue;
- }
-
- // Emit two 32-bit chunks, order depends on endianness.
- unsigned FirstChunk = unsigned(Val), SecondChunk = unsigned(Val >> 32);
- const char *FirstName = " least", *SecondName = " most";
- if (TD->isBigEndian()) {
- std::swap(FirstChunk, SecondChunk);
- std::swap(FirstName, SecondName);
- }
-
- O << MAI->getData32bitsDirective(AddrSpace) << FirstChunk;
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << FirstName << " significant half of i64 " << Val;
- }
- O << '\n';
-
- O << MAI->getData32bitsDirective(AddrSpace) << SecondChunk;
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString()
- << SecondName << " significant half of i64 " << Val;
- }
- O << '\n';
+ uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i];
+ AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
}
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
- const TargetData *TD = TM.getTargetData();
- const Type *type = CV->getType();
- unsigned Size = TD->getTypeAllocSize(type);
-
- if (CV->isNullValue() || isa<UndefValue>(CV)) {
- EmitZeros(Size, AddrSpace);
- return;
- }
-
- if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
- EmitGlobalConstantArray(CVA , AddrSpace);
- return;
- }
-
- if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
- EmitGlobalConstantStruct(CVS, AddrSpace);
- return;
+ if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) {
+ uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
+ return OutStreamer.EmitZeros(Size, AddrSpace);
}
- if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
- EmitGlobalConstantFP(CFP, AddrSpace);
- return;
- }
-
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- // If we can directly emit an 8-byte constant, do it.
- if (Size == 8)
- if (const char *Data64Dir = MAI->getData64bitsDirective(AddrSpace)) {
- O << Data64Dir << CI->getZExtValue() << '\n';
- return;
- }
-
- // Small integers are handled below; large integers are handled here.
- if (Size > 4) {
- EmitGlobalConstantLargeInt(CI, AddrSpace);
+ unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
+ switch (Size) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ if (VerboseAsm)
+ OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue());
+ OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace);
+ return;
+ default:
+ EmitGlobalConstantLargeInt(CI, AddrSpace, *this);
return;
}
}
- if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
- EmitGlobalConstantVector(CP);
- return;
- }
+ if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
+ return EmitGlobalConstantArray(CVA, AddrSpace, *this);
+
+ if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
+ return EmitGlobalConstantStruct(CVS, AddrSpace, *this);
- printDataDirective(type, AddrSpace);
- EmitConstantValueOnly(CV);
- if (VerboseAsm) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- SmallString<40> S;
- CI->getValue().toStringUnsigned(S, 16);
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " 0x" << S.str();
- }
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
+ return EmitGlobalConstantFP(CFP, AddrSpace, *this);
+
+ if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
+ return EmitGlobalConstantVector(V, AddrSpace, *this);
+
+ if (isa<ConstantPointerNull>(CV)) {
+ unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
+ OutStreamer.EmitIntValue(0, Size, AddrSpace);
+ return;
}
- O << '\n';
+
+ // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
+ // thread the streamer with EmitValue.
+ OutStreamer.EmitValue(LowerConstant(CV, *this),
+ TM.getTargetData()->getTypeAllocSize(CV->getType()),
+ AddrSpace);
}
void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
@@ -1397,22 +1105,21 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI,
DebugLoc DL = MI->getDebugLoc();
if (DL.isUnknown())
return;
- DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
- if (CurDLT.Scope == 0)
+ DILocation CurDLT = MF->getDILocation(DL);
+ if (CurDLT.getScope().isNull())
return;
- if (BeforePrintingInsn) {
- if (CurDLT != PrevDLT) {
- unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
- CurDLT.Scope);
- printLabel(L);
- O << '\n';
- DW->BeginScope(MI, L);
- PrevDLT = CurDLT;
- }
- } else {
+ 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';
+ DW->BeginScope(MI, L);
+ PrevDLT = CurDLT.getNode();
}
}
@@ -1587,9 +1294,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
unsigned OpFlags = MI->getOperand(OpNo).getImm();
++OpNo; // Skip over the ID number.
- if (Modifier[0]=='l') // labels are target independent
- GetMBBSymbol(MI->getOperand(OpNo).getMBB()
- ->getNumber())->print(O, MAI);
+ if (Modifier[0] == 'l') // labels are target independent
+ O << *GetMBBSymbol(MI->getOperand(OpNo).getMBB()->getNumber());
else {
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
if ((OpFlags & 7) == 4) {
@@ -1604,8 +1310,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
if (Error) {
std::string msg;
raw_string_ostream Msg(msg);
- Msg << "Invalid operand found in inline asm: '"
- << AsmStr << "'\n";
+ Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n";
MI->print(Msg);
llvm_report_error(Msg.str());
}
@@ -1694,10 +1399,121 @@ MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const {
SmallString<60> Name;
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB"
<< getFunctionNumber() << '_' << MBBID;
-
return OutContext.GetOrCreateSymbol(Name.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());
+}
+
+/// GetJTISymbol - Return the symbol for the specified jump table entry.
+MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
+ const char *Prefix = isLinkerPrivate ? MAI->getLinkerPrivateGlobalPrefix() :
+ MAI->getPrivateGlobalPrefix();
+ SmallString<60> Name;
+ raw_svector_ostream(Name) << Prefix << "JTI" << getFunctionNumber() << '_'
+ << JTID;
+ return OutContext.GetOrCreateSymbol(Name.str());
+}
+
+/// GetGlobalValueSymbol - Return the MCSymbol for the specified global
+/// value.
+MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const {
+ SmallString<60> NameStr;
+ Mang->getNameWithPrefix(NameStr, GV, false);
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+}
+
+/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
+/// global value name as its base, with the specified suffix, and where the
+/// symbol is forced to have private linkage if ForcePrivate is true.
+MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
+ StringRef Suffix,
+ bool ForcePrivate) const {
+ SmallString<60> NameStr;
+ Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
+ NameStr.append(Suffix.begin(), Suffix.end());
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+}
+
+/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
+/// ExternalSymbol.
+MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const {
+ SmallString<60> NameStr;
+ Mang->getNameWithPrefix(NameStr, Sym);
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+}
+
+
+
+/// PrintParentLoopComment - Print comments about parent loops of this one.
+static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop,
+ unsigned FunctionNumber) {
+ if (Loop == 0) return;
+ PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber);
+ OS.indent(Loop->getLoopDepth()*2)
+ << "Parent Loop BB" << FunctionNumber << "_"
+ << Loop->getHeader()->getNumber()
+ << " Depth=" << Loop->getLoopDepth() << '\n';
+}
+
+
+/// PrintChildLoopComment - Print comments about child loops within
+/// the loop for this basic block, with nesting.
+static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop,
+ unsigned FunctionNumber) {
+ // Add child loop information
+ for (MachineLoop::iterator CL = Loop->begin(), E = Loop->end();CL != E; ++CL){
+ OS.indent((*CL)->getLoopDepth()*2)
+ << "Child Loop BB" << FunctionNumber << "_"
+ << (*CL)->getHeader()->getNumber() << " Depth " << (*CL)->getLoopDepth()
+ << '\n';
+ PrintChildLoopComment(OS, *CL, FunctionNumber);
+ }
+}
+
+/// EmitComments - Pretty-print comments for basic blocks.
+static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB,
+ const MachineLoopInfo *LI,
+ const AsmPrinter &AP) {
+ // Add loop depth information
+ const MachineLoop *Loop = LI->getLoopFor(&MBB);
+ if (Loop == 0) return;
+
+ MachineBasicBlock *Header = Loop->getHeader();
+ assert(Header && "No header for loop");
+
+ // If this block is not a loop header, just print out what is the loop header
+ // and return.
+ if (Header != &MBB) {
+ AP.OutStreamer.AddComment(" in Loop: Header=BB" +
+ Twine(AP.getFunctionNumber())+"_" +
+ Twine(Loop->getHeader()->getNumber())+
+ " Depth="+Twine(Loop->getLoopDepth()));
+ return;
+ }
+
+ // Otherwise, it is a loop header. Print out information about child and
+ // parent loops.
+ raw_ostream &OS = AP.OutStreamer.GetCommentOS();
+
+ PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber());
+
+ OS << "=>";
+ OS.indent(Loop->getLoopDepth()*2-2);
+
+ OS << "This ";
+ if (Loop->empty())
+ OS << "Inner ";
+ OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n';
+
+ PrintChildLoopComment(OS, Loop, AP.getFunctionNumber());
+}
+
/// EmitBasicBlockStart - This method prints the label for the specified
/// MachineBasicBlock, an alignment (if present) and a comment describing
@@ -1713,38 +1529,33 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
// forward references to labels without knowing what their numbers
// will be.
if (MBB->hasAddressTaken()) {
- GetBlockAddressSymbol(MBB->getBasicBlock()->getParent(),
- MBB->getBasicBlock())->print(O, MAI);
- O << ':';
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " Address Taken";
- }
- O << '\n';
+ const BasicBlock *BB = MBB->getBasicBlock();
+ if (VerboseAsm)
+ OutStreamer.AddComment("Address Taken");
+ OutStreamer.EmitLabel(GetBlockAddressSymbol(BB->getParent(), BB));
}
// Print the main label for the block.
if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) {
- if (VerboseAsm)
+ if (VerboseAsm) {
+ // NOTE: Want this comment at start of line.
O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':';
+ if (const BasicBlock *BB = MBB->getBasicBlock())
+ if (BB->hasName())
+ OutStreamer.AddComment("%" + BB->getName());
+
+ PrintBasicBlockLoopComments(*MBB, LI, *this);
+ OutStreamer.AddBlankLine();
+ }
} else {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
- O << ':';
- if (!VerboseAsm)
- O << '\n';
- }
-
- // Print some comments to accompany the label.
- if (VerboseAsm) {
- if (const BasicBlock *BB = MBB->getBasicBlock())
- if (BB->hasName()) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, BB, /*PrintType=*/false);
- }
+ if (VerboseAsm) {
+ if (const BasicBlock *BB = MBB->getBasicBlock())
+ if (BB->hasName())
+ OutStreamer.AddComment("%" + BB->getName());
+ PrintBasicBlockLoopComments(*MBB, LI, *this);
+ }
- EmitComments(*MBB);
- O << '\n';
+ OutStreamer.EmitLabel(GetMBBSymbol(MBB->getNumber()));
}
}
@@ -1756,10 +1567,9 @@ void AsmPrinter::printPICJumpTableSetLabel(unsigned uid,
return;
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << uid << '\n';
+ << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','
+ << *GetMBBSymbol(MBB->getNumber())
+ << '-' << *GetJTISymbol(uid) << '\n';
}
void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
@@ -1769,64 +1579,27 @@ void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << '_' << uid2
- << "_set_" << MBB->getNumber() << ',';
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ << "_set_" << MBB->getNumber() << ','
+ << *GetMBBSymbol(MBB->getNumber())
+ << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << uid << '_' << uid2 << '\n';
}
-/// printDataDirective - This method prints the asm directive for the
-/// specified type.
-void AsmPrinter::printDataDirective(const Type *type, unsigned AddrSpace) {
- const TargetData *TD = TM.getTargetData();
- switch (type->getTypeID()) {
- case Type::FloatTyID: case Type::DoubleTyID:
- case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID:
- assert(0 && "Should have already output floating point constant.");
- default:
- assert(0 && "Can't handle printing this type of thing");
- case Type::IntegerTyID: {
- unsigned BitWidth = cast<IntegerType>(type)->getBitWidth();
- if (BitWidth <= 8)
- O << MAI->getData8bitsDirective(AddrSpace);
- else if (BitWidth <= 16)
- O << MAI->getData16bitsDirective(AddrSpace);
- else if (BitWidth <= 32)
- O << MAI->getData32bitsDirective(AddrSpace);
- else if (BitWidth <= 64) {
- assert(MAI->getData64bitsDirective(AddrSpace) &&
- "Target cannot handle 64-bit constant exprs!");
- O << MAI->getData64bitsDirective(AddrSpace);
- } else {
- llvm_unreachable("Target cannot handle given data directive width!");
- }
+void AsmPrinter::printVisibility(MCSymbol *Sym, unsigned Visibility) const {
+ MCSymbolAttr Attr = MCSA_Invalid;
+
+ switch (Visibility) {
+ default: break;
+ case GlobalValue::HiddenVisibility:
+ Attr = MAI->getHiddenVisibilityAttr();
break;
- }
- case Type::PointerTyID:
- if (TD->getPointerSize() == 8) {
- assert(MAI->getData64bitsDirective(AddrSpace) &&
- "Target cannot handle 64-bit pointer exprs!");
- O << MAI->getData64bitsDirective(AddrSpace);
- } else if (TD->getPointerSize() == 2) {
- O << MAI->getData16bitsDirective(AddrSpace);
- } else if (TD->getPointerSize() == 1) {
- O << MAI->getData8bitsDirective(AddrSpace);
- } else {
- O << MAI->getData32bitsDirective(AddrSpace);
- }
+ case GlobalValue::ProtectedVisibility:
+ Attr = MAI->getProtectedVisibilityAttr();
break;
}
-}
-void AsmPrinter::printVisibility(const std::string& Name,
- unsigned Visibility) const {
- if (Visibility == GlobalValue::HiddenVisibility) {
- if (const char *Directive = MAI->getHiddenDirective())
- O << Directive << Name << '\n';
- } else if (Visibility == GlobalValue::ProtectedVisibility) {
- if (const char *Directive = MAI->getProtectedDirective())
- O << Directive << Name << '\n';
- }
+ if (Attr != MCSA_Invalid)
+ OutStreamer.EmitSymbolAttribute(Sym, Attr);
}
void AsmPrinter::printOffset(int64_t Offset) const {
@@ -1856,8 +1629,8 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
return GMP;
}
- errs() << "no GCMetadataPrinter registered for GC: " << Name << "\n";
- llvm_unreachable(0);
+ llvm_report_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
+ return 0;
}
/// EmitComments - Pretty-print comments for instructions
@@ -1868,20 +1641,20 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const {
bool Newline = false;
if (!MI.getDebugLoc().isUnknown()) {
- DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
+ DILocation DLT = MF->getDILocation(MI.getDebugLoc());
// Print source line info.
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
- DIScope Scope(DLT.Scope);
+ DIScope Scope = DLT.getScope();
// Omit the directory, because it's likely to be long and uninteresting.
if (!Scope.isNull())
O << Scope.getFilename();
else
O << "<unknown>";
- O << ':' << DLT.Line;
- if (DLT.Col != 0)
- O << ':' << DLT.Col;
+ O << ':' << DLT.getLineNumber();
+ if (DLT.getColumnNumber() != 0)
+ O << ':' << DLT.getColumnNumber();
Newline = true;
}
@@ -1943,80 +1716,3 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const {
}
}
-/// PrintChildLoopComment - Print comments about child loops within
-/// the loop for this basic block, with nesting.
-///
-static void PrintChildLoopComment(formatted_raw_ostream &O,
- const MachineLoop *loop,
- const MCAsmInfo *MAI,
- int FunctionNumber) {
- // Add child loop information
- for(MachineLoop::iterator cl = loop->begin(),
- clend = loop->end();
- cl != clend;
- ++cl) {
- MachineBasicBlock *Header = (*cl)->getHeader();
- assert(Header && "No header for loop");
-
- O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
-
- O << MAI->getCommentString();
- O.indent(((*cl)->getLoopDepth()-1)*2)
- << " Child Loop BB" << FunctionNumber << "_"
- << Header->getNumber() << " Depth " << (*cl)->getLoopDepth();
-
- PrintChildLoopComment(O, *cl, MAI, FunctionNumber);
- }
-}
-
-/// EmitComments - Pretty-print comments for basic blocks
-void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const {
- if (VerboseAsm) {
- // Add loop depth information
- const MachineLoop *loop = LI->getLoopFor(&MBB);
-
- if (loop) {
- // Print a newline after bb# annotation.
- O << "\n";
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " Loop Depth " << loop->getLoopDepth()
- << '\n';
-
- O.PadToColumn(MAI->getCommentColumn());
-
- MachineBasicBlock *Header = loop->getHeader();
- assert(Header && "No header for loop");
-
- if (Header == &MBB) {
- O << MAI->getCommentString() << " Loop Header";
- PrintChildLoopComment(O, loop, MAI, getFunctionNumber());
- }
- else {
- O << MAI->getCommentString() << " Loop Header is BB"
- << getFunctionNumber() << "_" << loop->getHeader()->getNumber();
- }
-
- if (loop->empty()) {
- O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " Inner Loop";
- }
-
- // Add parent loop information
- for (const MachineLoop *CurLoop = loop->getParentLoop();
- CurLoop;
- CurLoop = CurLoop->getParentLoop()) {
- MachineBasicBlock *Header = CurLoop->getHeader();
- assert(Header && "No header for loop");
-
- O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString();
- O.indent((CurLoop->getLoopDepth()-1)*2)
- << " Inside Loop BB" << getFunctionNumber() << "_"
- << Header->getNumber() << " Depth " << CurLoop->getLoopDepth();
- }
- }
- }
-}
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index b85e11a..349e0ac 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -13,12 +13,16 @@
#include "DIE.h"
#include "DwarfPrinter.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/FormattedStream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -49,31 +53,33 @@ void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
/// Emit - Print the abbreviation using the specified asm printer.
///
-void DIEAbbrev::Emit(const AsmPrinter *Asm) const {
+void DIEAbbrev::Emit(const DwarfPrinter *DP) const {
// Emit its Dwarf tag type.
- Asm->EmitULEB128Bytes(Tag);
- Asm->EOL(dwarf::TagString(Tag));
+ // FIXME: Doing work even in non-asm-verbose runs.
+ DP->EmitULEB128(Tag, dwarf::TagString(Tag));
// Emit whether it has children DIEs.
- Asm->EmitULEB128Bytes(ChildrenFlag);
- Asm->EOL(dwarf::ChildrenString(ChildrenFlag));
+ // FIXME: Doing work even in non-asm-verbose runs.
+ DP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag));
// For each attribute description.
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
const DIEAbbrevData &AttrData = Data[i];
// Emit attribute type.
- Asm->EmitULEB128Bytes(AttrData.getAttribute());
- Asm->EOL(dwarf::AttributeString(AttrData.getAttribute()));
+ // FIXME: Doing work even in non-asm-verbose runs.
+ DP->EmitULEB128(AttrData.getAttribute(),
+ dwarf::AttributeString(AttrData.getAttribute()));
// Emit form type.
- Asm->EmitULEB128Bytes(AttrData.getForm());
- Asm->EOL(dwarf::FormEncodingString(AttrData.getForm()));
+ // FIXME: Doing work even in non-asm-verbose runs.
+ DP->EmitULEB128(AttrData.getForm(),
+ dwarf::FormEncodingString(AttrData.getForm()));
}
// Mark end of abbreviation.
- Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(1)");
- Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(2)");
+ DP->EmitULEB128(0, "EOM(1)");
+ DP->EmitULEB128(0, "EOM(2)");
}
#ifndef NDEBUG
@@ -182,22 +188,24 @@ void DIEValue::dump() {
/// EmitValue - Emit integer of appropriate size.
///
-void DIEInteger::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const {
const AsmPrinter *Asm = D->getAsm();
+ unsigned Size = ~0U;
switch (Form) {
case dwarf::DW_FORM_flag: // Fall thru
case dwarf::DW_FORM_ref1: // Fall thru
- case dwarf::DW_FORM_data1: Asm->EmitInt8(Integer); break;
+ case dwarf::DW_FORM_data1: Size = 1; break;
case dwarf::DW_FORM_ref2: // Fall thru
- case dwarf::DW_FORM_data2: Asm->EmitInt16(Integer); break;
+ case dwarf::DW_FORM_data2: Size = 2; break;
case dwarf::DW_FORM_ref4: // Fall thru
- case dwarf::DW_FORM_data4: Asm->EmitInt32(Integer); break;
+ case dwarf::DW_FORM_data4: Size = 4; break;
case dwarf::DW_FORM_ref8: // Fall thru
- case dwarf::DW_FORM_data8: Asm->EmitInt64(Integer); break;
- case dwarf::DW_FORM_udata: Asm->EmitULEB128Bytes(Integer); break;
- case dwarf::DW_FORM_sdata: Asm->EmitSLEB128Bytes(Integer); break;
+ case dwarf::DW_FORM_data8: Size = 8; break;
+ case dwarf::DW_FORM_udata: D->EmitULEB128(Integer); return;
+ case dwarf::DW_FORM_sdata: D->EmitSLEB128(Integer, ""); return;
default: llvm_unreachable("DIE Value form not supported yet");
}
+ Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/);
}
/// SizeOf - Determine size of integer value in bytes.
@@ -233,8 +241,10 @@ void DIEInteger::print(raw_ostream &O) {
/// EmitValue - Emit string value.
///
-void DIEString::EmitValue(Dwarf *D, unsigned Form) const {
- D->getAsm()->EmitString(Str);
+void DIEString::EmitValue(DwarfPrinter *D, unsigned Form) const {
+ D->getAsm()->OutStreamer.EmitBytes(Str, /*addrspace*/0);
+ // Emit nul terminator.
+ D->getAsm()->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0);
}
#ifndef NDEBUG
@@ -249,7 +259,7 @@ void DIEString::print(raw_ostream &O) {
/// EmitValue - Emit label value.
///
-void DIEDwarfLabel::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEDwarfLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
bool IsSmall = Form == dwarf::DW_FORM_data4;
D->EmitReference(Label, false, IsSmall);
}
@@ -274,9 +284,9 @@ void DIEDwarfLabel::print(raw_ostream &O) {
/// EmitValue - Emit label value.
///
-void DIEObjectLabel::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEObjectLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
bool IsSmall = Form == dwarf::DW_FORM_data4;
- D->EmitReference(Label, false, IsSmall);
+ D->EmitReference(Sym, false, IsSmall);
}
/// SizeOf - Determine size of label value in bytes.
@@ -288,7 +298,7 @@ unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const {
#ifndef NDEBUG
void DIEObjectLabel::print(raw_ostream &O) {
- O << "Obj: " << Label;
+ O << "Obj: " << Sym->getName();
}
#endif
@@ -298,7 +308,7 @@ void DIEObjectLabel::print(raw_ostream &O) {
/// EmitValue - Emit delta value.
///
-void DIESectionOffset::EmitValue(Dwarf *D, unsigned Form) const {
+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(),
@@ -328,7 +338,7 @@ void DIESectionOffset::print(raw_ostream &O) {
/// EmitValue - Emit delta value.
///
-void DIEDelta::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEDelta::EmitValue(DwarfPrinter *D, unsigned Form) const {
bool IsSmall = Form == dwarf::DW_FORM_data4;
D->EmitDifference(LabelHi, LabelLo, IsSmall);
}
@@ -355,7 +365,7 @@ void DIEDelta::print(raw_ostream &O) {
/// EmitValue - Emit debug information entry offset.
///
-void DIEEntry::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEEntry::EmitValue(DwarfPrinter *D, unsigned Form) const {
D->getAsm()->EmitInt32(Entry->getOffset());
}
@@ -383,19 +393,19 @@ unsigned DIEBlock::ComputeSize(const TargetData *TD) {
/// EmitValue - Emit block data.
///
-void DIEBlock::EmitValue(Dwarf *D, unsigned Form) const {
+void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const {
const AsmPrinter *Asm = D->getAsm();
switch (Form) {
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: Asm->EmitULEB128Bytes(Size); 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->EOL();
+ Asm->O << '\n';
Values[i]->EmitValue(D, AbbrevData[i].getForm());
}
}
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index a6dc9b6..af90289 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -23,8 +23,9 @@
namespace llvm {
class AsmPrinter;
- class Dwarf;
+ class DwarfPrinter;
class TargetData;
+ class MCSymbol;
//===--------------------------------------------------------------------===//
/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
@@ -100,7 +101,7 @@ namespace llvm {
/// Emit - Print the abbreviation using the specified asm printer.
///
- void Emit(const AsmPrinter *Asm) const;
+ void Emit(const DwarfPrinter *DP) const;
#ifndef NDEBUG
void print(raw_ostream &O);
@@ -221,7 +222,7 @@ namespace llvm {
/// EmitValue - Emit value via the Dwarf writer.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const = 0;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const = 0;
/// SizeOf - Return the size of a value in bytes.
///
@@ -261,7 +262,7 @@ namespace llvm {
/// EmitValue - Emit integer of appropriate size.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of integer value in bytes.
///
@@ -287,7 +288,7 @@ namespace llvm {
/// EmitValue - Emit string value.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of string value in bytes.
///
@@ -314,7 +315,7 @@ namespace llvm {
/// EmitValue - Emit label value.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of label value in bytes.
///
@@ -333,14 +334,14 @@ namespace llvm {
/// DIEObjectLabel - A label to an object in code or data.
//
class DIEObjectLabel : public DIEValue {
- const std::string Label;
+ const MCSymbol *Sym;
public:
- explicit DIEObjectLabel(const std::string &L)
- : DIEValue(isAsIsLabel), Label(L) {}
+ explicit DIEObjectLabel(const MCSymbol *S)
+ : DIEValue(isAsIsLabel), Sym(S) {}
/// EmitValue - Emit label value.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of label value in bytes.
///
@@ -373,7 +374,7 @@ namespace llvm {
/// EmitValue - Emit section offset.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of section offset value in bytes.
///
@@ -402,7 +403,7 @@ namespace llvm {
/// EmitValue - Emit delta value.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of delta value in bytes.
///
@@ -431,7 +432,7 @@ namespace llvm {
/// EmitValue - Emit debug information entry offset.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of debug information entry in bytes.
///
@@ -473,7 +474,7 @@ namespace llvm {
/// EmitValue - Emit block data.
///
- virtual void EmitValue(Dwarf *D, unsigned Form) const;
+ virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
/// SizeOf - Determine size of block data in bytes.
///
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 15f37ae..513987f 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -18,6 +18,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -25,7 +26,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
#include "llvm/System/Path.h"
using namespace llvm;
@@ -56,12 +57,12 @@ class CompileUnit {
/// GVToDieMap - Tracks the mapping of unit level debug informaton
/// variables to debug information entries.
/// FIXME : Rename GVToDieMap -> NodeToDieMap
- ValueMap<MDNode *, DIE *> GVToDieMap;
+ DenseMap<MDNode *, DIE *> GVToDieMap;
/// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton
/// descriptors to debug information entries using a DIEEntry proxy.
/// FIXME : Rename
- ValueMap<MDNode *, DIEEntry *> GVToDIEEntryMap;
+ DenseMap<MDNode *, DIEEntry *> GVToDIEEntryMap;
/// Globals - A map of globally visible named entities for this unit.
///
@@ -108,7 +109,7 @@ public:
/// getDIEEntry - Returns the debug information entry for the speciefied
/// debug variable.
DIEEntry *getDIEEntry(MDNode *N) {
- ValueMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
+ DenseMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
if (I == GVToDIEEntryMap.end())
return NULL;
return I->second;
@@ -165,7 +166,7 @@ public:
class DbgScope {
DbgScope *Parent; // Parent to this scope.
DIDescriptor Desc; // Debug info descriptor for scope.
- WeakVH InlinedAtLocation; // Location at which scope is inlined.
+ MDNode * InlinedAtLocation; // Location at which scope is inlined.
bool AbstractScope; // Abstract Scope
unsigned StartLabelID; // Label ID of the beginning of scope.
unsigned EndLabelID; // Label ID of the end of scope.
@@ -274,7 +275,7 @@ DbgScope::~DbgScope() {
} // end llvm namespace
DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
- : Dwarf(OS, A, T, "dbg"), ModuleCU(0),
+ : DwarfPrinter(OS, A, T, "dbg"), ModuleCU(0),
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
DIEValues(), StringPool(),
SectionSourceLines(), didInitial(false), shouldEmit(false),
@@ -343,7 +344,7 @@ void DwarfDebug::addSInt(DIE *Die, unsigned Attribute,
/// addString - Add a string attribute data and value. DIEString only
/// keeps string reference.
void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
- const StringRef String) {
+ StringRef String) {
DIEValue *Value = new DIEString(String);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
@@ -361,8 +362,8 @@ void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
/// addObjectLabel - Add an non-Dwarf label attribute data and value.
///
void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const std::string &Label) {
- DIEValue *Value = new DIEObjectLabel(Label);
+ const MCSymbol *Sym) {
+ DIEValue *Value = new DIEObjectLabel(Sym);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
}
@@ -1162,7 +1163,8 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
addUInt(Block, 0, dwarf::DW_FORM_data1, SP.getVirtualIndex());
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block);
- ContainingTypeMap.insert(std::make_pair(SPDie, WeakVH(SP.getContainingType().getNode())));
+ ContainingTypeMap.insert(std::make_pair(SPDie,
+ SP.getContainingType().getNode()));
}
if (MakeDecl || !SP.isDefinition()) {
@@ -1379,7 +1381,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
InlinedSubprogramDIEs.insert(OriginDIE);
// Track the start label for this inlined function.
- ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
+ DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
I = InlineInfo.find(InlinedSP.getNode());
if (I == InlineInfo.end()) {
@@ -1665,14 +1667,14 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
- Asm->Mang->getMangledName(DI_GV.getGlobal()));
+ Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
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->Mang->getMangledName(DI_GV.getGlobal()));
+ Asm->GetGlobalValueSymbol(DI_GV.getGlobal()));
addBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
}
addToContextOwner(VariableDie, GVContext);
@@ -1770,13 +1772,15 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
// Remember source id starts at 1.
std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
+ // FIXME: don't use sys::path for this! This should not depend on the
+ // host.
sys::Path FullPath(getSourceDirectoryName(Id.first));
bool AppendOk =
FullPath.appendComponent(getSourceFileName(Id.second));
assert(AppendOk && "Could not append filename to directory!");
AppendOk = false;
Asm->EmitFile(i, FullPath.str());
- Asm->EOL();
+ Asm->O << '\n';
}
}
@@ -1808,7 +1812,7 @@ void DwarfDebug::endModule() {
TE = TopLevelDIEsVector.end(); TI != TE; ++TI)
ModuleCU->getCUDie()->addChild(*TI);
- for (DenseMap<DIE *, WeakVH>::iterator CI = ContainingTypeMap.begin(),
+ for (DenseMap<DIE *, MDNode *>::iterator CI = ContainingTypeMap.begin(),
CE = ContainingTypeMap.end(); CI != CE; ++CI) {
DIE *SPDie = CI->first;
MDNode *N = dyn_cast_or_null<MDNode>(CI->second);
@@ -1906,8 +1910,7 @@ void DwarfDebug::collectVariableInfo() {
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
- MetadataBase *MB = VI->first;
- MDNode *Var = dyn_cast_or_null<MDNode>(MB);
+ MDNode *Var = VI->first;
if (!Var) continue;
DIVariable DV (Var);
std::pair< unsigned, MDNode *> VP = VI->second;
@@ -2000,13 +2003,14 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) {
MIIndexMap[MInsn] = MIIndex++;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
- DebugLocTuple DLT = MF->getDebugLocTuple(DL);
- if (!DLT.Scope) 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.
- if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
- createDbgScope(DLT.Scope, DLT.InlinedAtLoc);
+ if (DLTScope.isCompileUnit()) continue;
+ createDbgScope(DLTScope.getNode(), DLT.getOrigLocation().getNode());
}
}
@@ -2019,13 +2023,15 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) {
const MachineInstr *MInsn = II;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
- DebugLocTuple DLT = MF->getDebugLocTuple(DL);
- if (!DLT.Scope) 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.
- if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
- DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
+ if (DLTScope.isCompileUnit()) continue;
+ DbgScope *Scope = getUpdatedDbgScope(DLTScope.getNode(), MInsn,
+ DLT.getOrigLocation().getNode());
Scope->setLastInsn(MInsn);
}
}
@@ -2038,10 +2044,18 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) {
// Each scope has first instruction and last instruction to mark beginning
// and end of a scope respectively. Create an inverse map that list scopes
// starts (and ends) with an instruction. One instruction may start (or end)
- // multiple scopes.
- for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
- DE = DbgScopeMap.end(); DI != DE; ++DI) {
- DbgScope *S = DI->second;
+ // multiple scopes. Ignore scopes that are not reachable.
+ SmallVector<DbgScope *, 4> WorkList;
+ WorkList.push_back(CurrentFnDbgScope);
+ while (!WorkList.empty()) {
+ DbgScope *S = WorkList.back(); WorkList.pop_back();
+
+ SmallVector<DbgScope *, 4> &Children = S->getScopes();
+ if (!Children.empty())
+ for (SmallVector<DbgScope *, 4>::iterator SI = Children.begin(),
+ SE = Children.end(); SI != SE; ++SI)
+ WorkList.push_back(*SI);
+
if (S->isAbstractScope())
continue;
const MachineInstr *MI = S->getFirstInsn();
@@ -2090,13 +2104,16 @@ void DwarfDebug::beginFunction(MachineFunction *MF) {
// function.
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
- DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
+ DILocation DLT = MF->getDILocation(FDL);
unsigned LabelID = 0;
- DISubprogram SP = getDISubprogram(DLT.Scope);
+ DISubprogram SP = getDISubprogram(DLT.getScope().getNode());
if (!SP.isNull())
- LabelID = recordSourceLine(SP.getLineNumber(), 0, DLT.Scope);
+ LabelID = recordSourceLine(SP.getLineNumber(), 0,
+ DLT.getScope().getNode());
else
- LabelID = recordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
+ LabelID = recordSourceLine(DLT.getLineNumber(),
+ DLT.getColumnNumber(),
+ DLT.getScope().getNode());
Asm->printLabel(LabelID);
O << '\n';
}
@@ -2142,14 +2159,12 @@ void DwarfDebug::endFunction(MachineFunction *MF) {
}
// Clear debug info
- if (CurrentFnDbgScope) {
- CurrentFnDbgScope = NULL;
- DbgScopeMap.clear();
- DbgScopeBeginMap.clear();
- DbgScopeEndMap.clear();
- ConcreteScopes.clear();
- AbstractScopesList.clear();
- }
+ CurrentFnDbgScope = NULL;
+ DbgScopeMap.clear();
+ DbgScopeBeginMap.clear();
+ DbgScopeEndMap.clear();
+ ConcreteScopes.clear();
+ AbstractScopesList.clear();
Lines.clear();
if (TimePassesIsEnabled)
@@ -2332,19 +2347,15 @@ void DwarfDebug::emitDIE(DIE *Die) {
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
- Asm->EOL();
+ Asm->O << '\n';
// Emit the code (index) for the abbreviation.
- Asm->EmitULEB128Bytes(AbbrevNumber);
-
- if (Asm->isVerbose())
- Asm->EOL(std::string("Abbrev [" +
- utostr(AbbrevNumber) +
- "] 0x" + utohexstr(Die->getOffset()) +
- ":0x" + utohexstr(Die->getSize()) + " " +
- dwarf::TagString(Abbrev->getTag())));
- else
- Asm->EOL();
+ if (Asm->VerboseAsm)
+ Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
+ Twine::utohexstr(Die->getOffset()) + ":0x" +
+ Twine::utohexstr(Die->getSize()) + " " +
+ dwarf::TagString(Abbrev->getTag()));
+ EmitULEB128(AbbrevNumber);
SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
@@ -2372,7 +2383,7 @@ void DwarfDebug::emitDIE(DIE *Die) {
break;
}
- Asm->EOL(dwarf::AttributeString(Attr));
+ EOL(dwarf::AttributeString(Attr));
}
// Emit the DIE children if any.
@@ -2382,7 +2393,7 @@ void DwarfDebug::emitDIE(DIE *Die) {
for (unsigned j = 0, M = Children.size(); j < M; ++j)
emitDIE(Children[j]);
- Asm->EmitInt8(0); Asm->EOL("End Of Children Mark");
+ Asm->EmitInt8(0); EOL("End Of Children Mark");
}
}
@@ -2404,21 +2415,20 @@ void DwarfDebug::emitDebugInfo() {
sizeof(int8_t) + // Pointer Size (in bytes)
sizeof(int32_t); // FIXME - extra pad for gdb bug.
- Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info");
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
+ 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);
- Asm->EOL("Offset Into Abbrev. Section");
- Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
+ EOL("Offset Into Abbrev. Section");
+ Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
emitDIE(Die);
// FIXME - extra padding for gdb bug.
- Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
- Asm->EmitInt8(0); Asm->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");
+ Asm->EmitInt8(0); EOL("Extra Pad For GDB");
EmitLabel("info_end", ModuleCU->getID());
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// emitAbbreviations - Emit the abbreviation section.
@@ -2438,20 +2448,18 @@ void DwarfDebug::emitAbbreviations() const {
const DIEAbbrev *Abbrev = Abbreviations[i];
// Emit the abbrevations code (base 1 index.)
- Asm->EmitULEB128Bytes(Abbrev->getNumber());
- Asm->EOL("Abbreviation Code");
+ EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
// Emit the abbreviations data.
- Abbrev->Emit(Asm);
-
- Asm->EOL();
+ Abbrev->Emit(this);
+ Asm->O << '\n';
}
// Mark end of abbreviations.
- Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
+ EmitULEB128(0, "EOM(3)");
EmitLabel("abbrev_end", 0);
- Asm->EOL();
+ Asm->O << '\n';
}
}
@@ -2460,15 +2468,15 @@ void DwarfDebug::emitAbbreviations() const {
///
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
// Define last address of section.
- Asm->EmitInt8(0); Asm->EOL("Extended Op");
- Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
- Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
- EmitReference("section_end", SectionEnd); Asm->EOL("Section end label");
+ 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");
// Mark end of matrix.
- Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
- Asm->EmitULEB128Bytes(1); Asm->EOL();
- Asm->EmitInt8(1); Asm->EOL();
+ Asm->EmitInt8(0); EOL("DW_LNE_end_sequence");
+ Asm->EmitInt8(1);
+ Asm->EmitInt8(1);
}
/// emitDebugLines - Emit source line information.
@@ -2490,59 +2498,55 @@ void DwarfDebug::emitDebugLines() {
// Construct the section header.
EmitDifference("line_end", 0, "line_begin", 0, true);
- Asm->EOL("Length of Source Line Info");
+ EOL("Length of Source Line Info");
EmitLabel("line_begin", 0);
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
+ Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
- Asm->EOL("Prolog Length");
+ EOL("Prolog Length");
EmitLabel("line_prolog_begin", 0);
- Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
-
- Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
-
- Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
-
- Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
-
- Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
+ 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");
// Line number standard opcode encodings argument count
- Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count");
- Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count");
- Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count");
- Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count");
- Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count");
- Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count");
- Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count");
- Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count");
- Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg 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");
// Emit directories.
for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
- Asm->EmitString(getSourceDirectoryName(DI));
- Asm->EOL("Directory");
+ const std::string &Dir = getSourceDirectoryName(DI);
+ if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory");
+ Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
}
- Asm->EmitInt8(0); Asm->EOL("End of directories");
+ Asm->EmitInt8(0); EOL("End of directories");
// Emit files.
for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
// Remember source id starts at 1.
std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
- Asm->EmitString(getSourceFileName(Id.second));
- Asm->EOL("Source");
- Asm->EmitULEB128Bytes(Id.first);
- Asm->EOL("Directory #");
- Asm->EmitULEB128Bytes(0);
- Asm->EOL("Mod date");
- Asm->EmitULEB128Bytes(0);
- Asm->EOL("File size");
+ const std::string &FN = getSourceFileName(Id.second);
+ if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source");
+ Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0);
+
+ EmitULEB128(Id.first, "Directory #");
+ EmitULEB128(0, "Mod date");
+ EmitULEB128(0, "File size");
}
- Asm->EmitInt8(0); Asm->EOL("End of files");
+ Asm->EmitInt8(0); EOL("End of files");
EmitLabel("line_prolog_end", 0);
@@ -2558,7 +2562,7 @@ void DwarfDebug::emitDebugLines() {
O << '\t' << MAI->getCommentString() << " Section"
<< S->getName() << '\n';
}*/
- Asm->EOL();
+ Asm->O << '\n';
// Dwarf assumes we start with first line of first source file.
unsigned Source = 1;
@@ -2573,7 +2577,7 @@ void DwarfDebug::emitDebugLines() {
if (LineInfo.getLine() == 0) continue;
if (!Asm->isVerbose())
- Asm->EOL();
+ Asm->O << '\n';
else {
std::pair<unsigned, unsigned> SourceID =
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
@@ -2584,16 +2588,16 @@ void DwarfDebug::emitDebugLines() {
}
// Define the line address.
- Asm->EmitInt8(0); Asm->EOL("Extended Op");
- Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
- Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
- EmitReference("label", LabelID); Asm->EOL("Location label");
+ 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");
// If change of source, then switch to the new source.
if (Source != LineInfo.getSourceID()) {
Source = LineInfo.getSourceID();
- Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file");
- Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source");
+ Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file");
+ EmitULEB128(Source, "New Source");
}
// If change of line.
@@ -2608,17 +2612,17 @@ 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); Asm->EOL("Line Delta");
+ Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
} else {
// ... otherwise use long hand.
Asm->EmitInt8(dwarf::DW_LNS_advance_line);
- Asm->EOL("DW_LNS_advance_line");
- Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset");
- Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
+ EOL("DW_LNS_advance_line");
+ EmitSLEB128(Offset, "Line Offset");
+ Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
}
} else {
// Copy the previous row (different address or source)
- Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
+ Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
}
}
@@ -2632,7 +2636,7 @@ void DwarfDebug::emitDebugLines() {
emitEndOfLineMatrix(1);
EmitLabel("line_end", 0);
- Asm->EOL();
+ Asm->O << '\n';
}
/// emitCommonDebugFrame - Emit common frame info into a debug frame section.
@@ -2653,21 +2657,19 @@ void DwarfDebug::emitCommonDebugFrame() {
EmitLabel("debug_frame_common", 0);
EmitDifference("debug_frame_common_end", 0,
"debug_frame_common_begin", 0, true);
- Asm->EOL("Length of Common Information Entry");
+ EOL("Length of Common Information Entry");
EmitLabel("debug_frame_common_begin", 0);
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
- Asm->EOL("CIE Identifier Tag");
+ EOL("CIE Identifier Tag");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
- Asm->EOL("CIE Version");
- Asm->EmitString("");
- Asm->EOL("CIE Augmentation");
- Asm->EmitULEB128Bytes(1);
- Asm->EOL("CIE Code Alignment Factor");
- Asm->EmitSLEB128Bytes(stackGrowth);
- Asm->EOL("CIE Data Alignment Factor");
+ EOL("CIE Version");
+ 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->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
- Asm->EOL("CIE RA Column");
+ EOL("CIE RA Column");
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
@@ -2676,8 +2678,7 @@ void DwarfDebug::emitCommonDebugFrame() {
Asm->EmitAlignment(2, 0, 0, false);
EmitLabel("debug_frame_common_end", 0);
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
@@ -2693,27 +2694,26 @@ DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
EmitDifference("debug_frame_end", DebugFrameInfo.Number,
"debug_frame_begin", DebugFrameInfo.Number, true);
- Asm->EOL("Length of Frame Information Entry");
+ EOL("Length of Frame Information Entry");
EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
EmitSectionOffset("debug_frame_common", "section_debug_frame",
0, 0, true, false);
- Asm->EOL("FDE CIE offset");
+ EOL("FDE CIE offset");
EmitReference("func_begin", DebugFrameInfo.Number);
- Asm->EOL("FDE initial location");
+ EOL("FDE initial location");
EmitDifference("func_end", DebugFrameInfo.Number,
"func_begin", DebugFrameInfo.Number);
- Asm->EOL("FDE address range");
+ EOL("FDE address range");
EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
false);
Asm->EmitAlignment(2, 0, 0, false);
EmitLabel("debug_frame_end", DebugFrameInfo.Number);
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
@@ -2725,19 +2725,19 @@ void DwarfDebug::emitDebugPubNames() {
EmitDifference("pubnames_end", ModuleCU->getID(),
"pubnames_begin", ModuleCU->getID(), true);
- Asm->EOL("Length of Public Names Info");
+ EOL("Length of Public Names Info");
EmitLabel("pubnames_begin", ModuleCU->getID());
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version");
EmitSectionOffset("info_begin", "section_info",
ModuleCU->getID(), 0, true, false);
- Asm->EOL("Offset of Compilation Unit Info");
+ EOL("Offset of Compilation Unit Info");
EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
true);
- Asm->EOL("Compilation Unit Length");
+ EOL("Compilation Unit Length");
const StringMap<DIE*> &Globals = ModuleCU->getGlobals();
for (StringMap<DIE*>::const_iterator
@@ -2745,14 +2745,16 @@ void DwarfDebug::emitDebugPubNames() {
const char *Name = GI->getKeyData();
DIE * Entity = GI->second;
- Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
- Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
+ Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset");
+
+ if (Asm->VerboseAsm)
+ Asm->OutStreamer.AddComment("External Name");
+ Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
}
- Asm->EmitInt32(0); Asm->EOL("End Mark");
+ Asm->EmitInt32(0); EOL("End Mark");
EmitLabel("pubnames_end", ModuleCU->getID());
-
- Asm->EOL();
+ Asm->O << '\n';
}
void DwarfDebug::emitDebugPubTypes() {
@@ -2761,19 +2763,19 @@ void DwarfDebug::emitDebugPubTypes() {
Asm->getObjFileLowering().getDwarfPubTypesSection());
EmitDifference("pubtypes_end", ModuleCU->getID(),
"pubtypes_begin", ModuleCU->getID(), true);
- Asm->EOL("Length of Public Types Info");
+ EOL("Length of Public Types Info");
EmitLabel("pubtypes_begin", ModuleCU->getID());
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version");
EmitSectionOffset("info_begin", "section_info",
ModuleCU->getID(), 0, true, false);
- Asm->EOL("Offset of Compilation ModuleCU Info");
+ EOL("Offset of Compilation ModuleCU Info");
EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
true);
- Asm->EOL("Compilation ModuleCU Length");
+ EOL("Compilation ModuleCU Length");
const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes();
for (StringMap<DIE*>::const_iterator
@@ -2781,14 +2783,15 @@ void DwarfDebug::emitDebugPubTypes() {
const char *Name = GI->getKeyData();
DIE * Entity = GI->second;
- Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
- Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
+ Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset");
+
+ if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name");
+ Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)), 0);
}
- Asm->EmitInt32(0); Asm->EOL("End Mark");
+ Asm->EmitInt32(0); EOL("End Mark");
EmitLabel("pubtypes_end", ModuleCU->getID());
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// emitDebugStr - Emit visible names into a debug str section.
@@ -2808,10 +2811,10 @@ void DwarfDebug::emitDebugStr() {
// Emit the string itself.
const std::string &String = StringPool[StringID];
- Asm->EmitString(String); Asm->EOL();
+ Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0);
}
- Asm->EOL();
+ Asm->O << '\n';
}
}
@@ -2821,7 +2824,6 @@ void DwarfDebug::emitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
- Asm->EOL();
}
/// EmitDebugARanges - Emit visible names into a debug aranges section.
@@ -2836,29 +2838,27 @@ void DwarfDebug::EmitDebugARanges() {
CompileUnit *Unit = GetBaseCompileUnit();
// Don't include size of length
- Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info");
+ Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info");
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
EmitReference("info_begin", Unit->getID());
- Asm->EOL("Offset of Compilation Unit Info");
+ EOL("Offset of Compilation Unit Info");
- Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
+ Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address");
- Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
+ Asm->EmitInt8(0); EOL("Size of Segment Descriptor");
- Asm->EmitInt16(0); Asm->EOL("Pad (1)");
- Asm->EmitInt16(0); Asm->EOL("Pad (2)");
+ Asm->EmitInt16(0); EOL("Pad (1)");
+ Asm->EmitInt16(0); EOL("Pad (2)");
// Range 1
- EmitReference("text_begin", 0); Asm->EOL("Address");
- EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length");
+ EmitReference("text_begin", 0); EOL("Address");
+ EmitDifference("text_end", 0, "text_begin", 0, true); EOL("Length");
- Asm->EmitInt32(0); Asm->EOL("EOM (1)");
- Asm->EmitInt32(0); Asm->EOL("EOM (2)");
+ Asm->EmitInt32(0); EOL("EOM (1)");
+ Asm->EmitInt32(0); EOL("EOM (2)");
#endif
-
- Asm->EOL();
}
/// emitDebugRanges - Emit visible names into a debug ranges section.
@@ -2867,7 +2867,6 @@ void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
- Asm->EOL();
}
/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
@@ -2877,7 +2876,6 @@ void DwarfDebug::emitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
Asm->OutStreamer.SwitchSection(LineInfo);
- Asm->EOL();
}
}
@@ -2908,53 +2906,54 @@ void DwarfDebug::emitDebugInlineInfo() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
- Asm->EOL();
+
EmitDifference("debug_inlined_end", 1,
"debug_inlined_begin", 1, true);
- Asm->EOL("Length of Debug Inlined Information Entry");
+ EOL("Length of Debug Inlined Information Entry");
EmitLabel("debug_inlined_begin", 1);
- Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
- Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
+ Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
+ Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
MDNode *Node = *I;
- ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
+ DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
= InlineInfo.find(Node);
SmallVector<InlineInfoLabels, 4> &Labels = II->second;
DISubprogram SP(Node);
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
- if (LName.empty())
- Asm->EmitString(Name);
- else
+ 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);
+ StringPool.idFor(getRealLinkageName(LName)), false, true);
- Asm->EOL("MIPS linkage name");
+ EOL("MIPS linkage name");
EmitSectionOffset("string", "section_str",
StringPool.idFor(Name), false, true);
- Asm->EOL("Function name");
- Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
+ EOL("Function name");
+ 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()); Asm->EOL("DIE offset");
+ Asm->EmitInt32(SP->getOffset()); EOL("DIE offset");
if (TD->getPointerSize() == sizeof(int32_t))
O << MAI->getData32bitsDirective();
else
O << MAI->getData64bitsDirective();
- PrintLabelName("label", LI->first); Asm->EOL("low_pc");
+ PrintLabelName("label", LI->first); EOL("low_pc");
}
}
EmitLabel("debug_inlined_end", 1);
- Asm->EOL();
+ Asm->O << '\n';
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 2b8164e..e723621 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -20,7 +20,7 @@
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/ValueMap.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
@@ -57,7 +57,7 @@ public:
unsigned getLabelID() const { return LabelID; }
};
-class DwarfDebug : public Dwarf {
+class DwarfDebug : public DwarfPrinter {
//===--------------------------------------------------------------------===//
// Attributes used to construct specific Dwarf sections.
//
@@ -136,25 +136,25 @@ class DwarfDebug : public Dwarf {
/// DbgScopeMap - Tracks the scopes in the current function.
///
- ValueMap<MDNode *, DbgScope *> DbgScopeMap;
+ DenseMap<MDNode *, DbgScope *> DbgScopeMap;
/// ConcreteScopes - Tracks the concrete scopees in the current function.
/// These scopes are also included in DbgScopeMap.
- ValueMap<MDNode *, DbgScope *> ConcreteScopes;
+ DenseMap<MDNode *, DbgScope *> ConcreteScopes;
/// AbstractScopes - Tracks the abstract scopes a module. These scopes are
/// not included DbgScopeMap.
- ValueMap<MDNode *, DbgScope *> AbstractScopes;
+ DenseMap<MDNode *, DbgScope *> AbstractScopes;
SmallVector<DbgScope *, 4>AbstractScopesList;
/// AbstractVariables - Collection on abstract variables.
- ValueMap<MDNode *, DbgVariable *> AbstractVariables;
+ DenseMap<MDNode *, DbgVariable *> AbstractVariables;
/// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
/// (at the end of the module) as DW_AT_inline.
SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
- DenseMap<DIE *, WeakVH> ContainingTypeMap;
+ DenseMap<DIE *, MDNode *> ContainingTypeMap;
/// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
@@ -176,7 +176,7 @@ class DwarfDebug : public Dwarf {
/// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section.
typedef std::pair<unsigned, DIE *> InlineInfoLabels;
- ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
+ DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
SmallVector<MDNode *, 4> InlinedSPNodes;
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
@@ -256,7 +256,7 @@ class DwarfDebug : public Dwarf {
/// addObjectLabel - Add an non-Dwarf label attribute data and value.
///
void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const std::string &Label);
+ const MCSymbol *Sym);
/// addSectionOffset - Add a section offset label attribute data and value.
///
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index d01f300..2ae16c0 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -22,22 +22,23 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/Mangler.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A,
const MCAsmInfo *T)
- : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false),
+ : DwarfPrinter(OS, A, T, "eh"), shouldEmitTable(false),shouldEmitMoves(false),
shouldEmitTableModule(false), shouldEmitMovesModule(false),
ExceptionTimer(0) {
if (TimePassesIsEnabled)
@@ -114,14 +115,14 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// Define the eh frame length.
EmitDifference("eh_frame_common_end", Index,
"eh_frame_common_begin", Index, true);
- Asm->EOL("Length of Common Information Entry");
+ EOL("Length of Common Information Entry");
// EH frame header.
EmitLabel("eh_frame_common_begin", Index);
- Asm->EmitInt32((int)0);
- Asm->EOL("CIE Identifier Tag");
- Asm->EmitInt8(dwarf::DW_CIE_VERSION);
- Asm->EOL("CIE Version");
+ if (Asm->VerboseAsm) 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.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/);
// The personality presence indicates that language specific information will
// show up in the eh frame. Find out how we are supposed to lower the
@@ -145,7 +146,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- char Augmentation[5] = { 0 };
+ char Augmentation[6] = { 0 };
unsigned AugmentationSize = 0;
char *APtr = Augmentation + 1;
@@ -170,22 +171,17 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
if (APtr != Augmentation + 1)
Augmentation[0] = 'z';
- Asm->EmitString(Augmentation);
- Asm->EOL("CIE Augmentation");
+ Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0);
+ EOL("CIE Augmentation");
// Round out reader.
- Asm->EmitULEB128Bytes(1);
- Asm->EOL("CIE Code Alignment Factor");
- Asm->EmitSLEB128Bytes(stackGrowth);
- Asm->EOL("CIE Data Alignment Factor");
+ EmitULEB128(1, "CIE Code Alignment Factor");
+ EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
- Asm->EOL("CIE Return Address Column");
+ EOL("CIE Return Address Column");
- Asm->EmitULEB128Bytes(AugmentationSize);
- Asm->EOL("Augmentation Size");
-
- Asm->EmitInt8(PerEncoding);
- Asm->EOL("Personality", PerEncoding);
+ EmitULEB128(AugmentationSize, "Augmentation Size");
+ EmitEncodingByte(PerEncoding, "Personality");
// If there is a personality, we need to indicate the function's location.
if (PersonalityRef) {
@@ -193,15 +189,11 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr",
Index);
- O << MAI->getData32bitsDirective();
- PersonalityRef->print(O, MAI);
- Asm->EOL("Personality");
-
- Asm->EmitInt8(LSDAEncoding);
- Asm->EOL("LSDA Encoding", LSDAEncoding);
+ O << MAI->getData32bitsDirective() << *PersonalityRef;
+ EOL("Personality");
- Asm->EmitInt8(FDEEncoding);
- Asm->EOL("FDE Encoding", FDEEncoding);
+ EmitEncodingByte(LSDAEncoding, "LSDA");
+ EmitEncodingByte(FDEEncoding, "FDE");
}
// Indicate locations of general callee saved registers in frame.
@@ -214,8 +206,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// holes which confuse readers of eh_frame.
Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false);
EmitLabel("eh_frame_common_end", Index);
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// EmitFDE - Emit the Frame Description Entry (FDE) for the function.
@@ -231,16 +222,17 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
// corresponding function is static, this should not be externally visible.
if (!TheFunc->hasLocalLinkage())
if (const char *GlobalEHDirective = MAI->getGlobalEHDirective())
- O << GlobalEHDirective << EHFrameInfo.FnName << '\n';
+ O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n';
// If corresponding function is weak definition, this should be too.
if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective())
- O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << '\n';
+ O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n';
// If corresponding function is hidden, this should be too.
if (TheFunc->hasHiddenVisibility())
- if (const char *HiddenDirective = MAI->getHiddenDirective())
- O << HiddenDirective << EHFrameInfo.FnName << '\n' ;
+ if (MCSymbolAttr HiddenAttr = MAI->getHiddenVisibilityAttr())
+ Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
+ HiddenAttr);
// If there are no calls then you can't unwind. This may mean we can omit the
// EH Frame, but some environments do not handle weak absolute symbols. If
@@ -250,19 +242,20 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
(!TheFunc->isWeakForLinker() ||
!MAI->getWeakDefDirective() ||
MAI->getSupportsWeakOmittedEHFrame())) {
- O << EHFrameInfo.FnName << " = 0\n";
+ O << *EHFrameInfo.FunctionEHSym << " = 0\n";
// This name has no connection to the function, so it might get
// dead-stripped when the function is not, erroneously. Prohibit
// dead-stripping unconditionally.
- if (const char *UsedDirective = MAI->getUsedDirective())
- O << UsedDirective << EHFrameInfo.FnName << "\n\n";
+ if (MAI->hasNoDeadStrip())
+ Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
+ MCSA_NoDeadStrip);
} else {
- O << EHFrameInfo.FnName << ":\n";
+ O << *EHFrameInfo.FunctionEHSym << ":\n";
// EH frame header.
EmitDifference("eh_frame_end", EHFrameInfo.Number,
"eh_frame_begin", EHFrameInfo.Number, true);
- Asm->EOL("Length of Frame Information Entry");
+ EOL("Length of Frame Information Entry");
EmitLabel("eh_frame_begin", EHFrameInfo.Number);
@@ -270,34 +263,39 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
true, true, false);
- Asm->EOL("FDE CIE offset");
+ EOL("FDE CIE offset");
EmitReference("eh_func_begin", EHFrameInfo.Number, true, true);
- Asm->EOL("FDE initial location");
+ EOL("FDE initial location");
EmitDifference("eh_func_end", EHFrameInfo.Number,
"eh_func_begin", EHFrameInfo.Number, true);
- Asm->EOL("FDE address range");
+ EOL("FDE address range");
// If there is a personality and landing pads then point to the language
// specific data area in the exception table.
if (MMI->getPersonalities()[0] != NULL) {
- bool is4Byte = TD->getPointerSize() == sizeof(int32_t);
- Asm->EmitULEB128Bytes(is4Byte ? 4 : 8);
- Asm->EOL("Augmentation size");
+ if (Asm->TM.getLSDAEncoding() != DwarfLSDAEncoding::EightByte) {
+ EmitULEB128(4, "Augmentation size");
- if (EHFrameInfo.hasLandingPads)
- EmitReference("exception", EHFrameInfo.Number, true, false);
- else {
- if (is4Byte)
- Asm->EmitInt32((int)0);
+ if (EHFrameInfo.hasLandingPads)
+ EmitReference("exception", EHFrameInfo.Number, true, true);
else
- Asm->EmitInt64((int)0);
+ Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
+ } else {
+ EmitULEB128(TD->getPointerSize(), "Augmentation size");
+
+ if (EHFrameInfo.hasLandingPads) {
+ EmitReference("exception", EHFrameInfo.Number, true, false);
+ } else {
+ Asm->OutStreamer.EmitIntValue(0, TD->getPointerSize(),
+ 0/*addrspace*/);
+ }
}
- Asm->EOL("Language Specific Data Area");
+
+ EOL("Language Specific Data Area");
} else {
- Asm->EmitULEB128Bytes(0);
- Asm->EOL("Augmentation size");
+ EmitULEB128(0, "Augmentation size");
}
// Indicate locations of function specific callee saved registers in frame.
@@ -317,11 +315,11 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
// on unused functions (calling undefined externals) being dead-stripped to
// link correctly. Yes, there really is.
if (MMI->isUsedFunction(EHFrameInfo.function))
- if (const char *UsedDirective = MAI->getUsedDirective())
- O << UsedDirective << EHFrameInfo.FnName << "\n\n";
+ if (MAI->hasNoDeadStrip())
+ Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
+ MCSA_NoDeadStrip);
}
-
- Asm->EOL();
+ Asm->O << '\n';
}
/// SharedTypeIds - How many leading type ids two landing pads have in common.
@@ -765,7 +763,7 @@ void DwarfException::EmitExceptionTable() {
for (unsigned i = 0; i != SizeAlign; ++i) {
Asm->EmitInt8(0);
- Asm->EOL("Padding");
+ EOL("Padding");
}
EmitLabel("exception", SubprogramCount);
@@ -778,23 +776,16 @@ void DwarfException::EmitExceptionTable() {
}
// Emit the header.
- Asm->EmitInt8(dwarf::DW_EH_PE_omit);
- Asm->EOL("@LPStart format", dwarf::DW_EH_PE_omit);
+ EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
+ EmitEncodingByte(TTypeFormat, "@TType");
- Asm->EmitInt8(TTypeFormat);
- Asm->EOL("@TType format", TTypeFormat);
-
- if (HaveTTData) {
- Asm->EmitULEB128Bytes(TyOffset);
- Asm->EOL("@TType base offset");
- }
+ if (HaveTTData)
+ EmitULEB128(TyOffset, "@TType base offset");
// SjLj Exception handling
if (IsSJLJ) {
- Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
- Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4);
- Asm->EmitULEB128Bytes(SizeSites);
- Asm->EOL("Call site table length");
+ EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
+ EmitULEB128(SizeSites, "Call site table length");
// Emit the landing pad site information.
unsigned idx = 0;
@@ -804,14 +795,12 @@ void DwarfException::EmitExceptionTable() {
// Offset of the landing pad, counted in 16-byte bundles relative to the
// @LPStart address.
- Asm->EmitULEB128Bytes(idx);
- Asm->EOL("Landing pad");
+ EmitULEB128(idx, "Landing pad");
// Offset of the first associated action record, relative to the start of
// the action table. This value is biased by 1 (1 indicates the start of
// the action table), and 0 indicates that there are no actions.
- Asm->EmitULEB128Bytes(S.Action);
- Asm->EOL("Action");
+ EmitULEB128(S.Action, "Action");
}
} else {
// DWARF Exception handling
@@ -836,10 +825,8 @@ void DwarfException::EmitExceptionTable() {
// supposed to throw.
// Emit the landing pad call site table.
- Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
- Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4);
- Asm->EmitULEB128Bytes(SizeSites);
- Asm->EOL("Call site table size");
+ EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
+ EmitULEB128(SizeSites, "Call site table size");
for (SmallVectorImpl<CallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
@@ -860,7 +847,7 @@ void DwarfException::EmitExceptionTable() {
// the start of the procedure fragment.
EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
true, true);
- Asm->EOL("Region start");
+ EOL("Region start");
if (!S.EndLabel)
EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
@@ -868,23 +855,22 @@ void DwarfException::EmitExceptionTable() {
else
EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
- Asm->EOL("Region length");
+ EOL("Region length");
// Offset of the landing pad, counted in 16-byte bundles relative to the
// @LPStart address.
if (!S.PadLabel)
- Asm->EmitInt32(0);
+ Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
else
EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
true, true);
- Asm->EOL("Landing pad");
+ EOL("Landing pad");
// Offset of the first associated action record, relative to the start of
// the action table. This value is biased by 1 (1 indicates the start of
// the action table), and 0 indicates that there are no actions.
- Asm->EmitULEB128Bytes(S.Action);
- Asm->EOL("Action");
+ EmitULEB128(S.Action, "Action");
}
}
@@ -897,17 +883,13 @@ void DwarfException::EmitExceptionTable() {
//
// Used by the runtime to match the type of the thrown exception to the
// type of the catch clauses or the types in the exception specification.
-
- Asm->EmitSLEB128Bytes(Action.ValueForTypeID);
- Asm->EOL("TypeInfo index");
+ EmitSLEB128(Action.ValueForTypeID, "TypeInfo index");
// Action Record
//
// Self-relative signed displacement in bytes of the next action record,
// or 0 if there is no next action record.
-
- Asm->EmitSLEB128Bytes(Action.NextAction);
- Asm->EOL("Next action");
+ EmitSLEB128(Action.NextAction, "Next action");
}
// Emit the Catch TypeInfos.
@@ -916,24 +898,19 @@ void DwarfException::EmitExceptionTable() {
const GlobalVariable *GV = *I;
PrintRelDirective();
- if (GV) {
- O << Asm->Mang->getMangledName(GV);
- } else {
+ if (GV)
+ O << *Asm->GetGlobalValueSymbol(GV);
+ else
O << "0x0";
- }
- Asm->EOL("TypeInfo");
+ EOL("TypeInfo");
}
// Emit the Exception Specifications.
for (std::vector<unsigned>::const_iterator
I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
unsigned TypeID = *I;
- Asm->EmitULEB128Bytes(TypeID);
- if (TypeID != 0)
- Asm->EOL("Exception specification");
- else
- Asm->EOL();
+ EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0);
}
Asm->EmitAlignment(2, 0, 0, false);
@@ -1008,12 +985,12 @@ void DwarfException::EndFunction() {
EmitLabel("eh_func_end", SubprogramCount);
EmitExceptionTable();
- std::string FunctionEHName =
- Asm->Mang->getMangledName(MF->getFunction(), ".eh",
- Asm->MAI->is_EHSymbolPrivate());
+ MCSymbol *FunctionEHSym =
+ Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh",
+ Asm->MAI->is_EHSymbolPrivate());
// Save EH frame information
- EHFrames.push_back(FunctionEHFrameInfo(FunctionEHName, SubprogramCount,
+ EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount,
MMI->getPersonalityIndex(),
MF->getFrameInfo()->hasCalls(),
!MMI->getLandingPads().empty(),
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index aa01c5b..3921e91 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -32,21 +32,21 @@ class raw_ostream;
//===----------------------------------------------------------------------===//
/// DwarfException - Emits Dwarf exception handling directives.
///
-class DwarfException : public Dwarf {
+class DwarfException : public DwarfPrinter {
struct FunctionEHFrameInfo {
- std::string FnName;
+ MCSymbol *FunctionEHSym; // L_foo.eh
unsigned Number;
unsigned PersonalityIndex;
bool hasCalls;
bool hasLandingPads;
std::vector<MachineMove> Moves;
- const Function * function;
+ const Function *function;
- FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P,
+ FunctionEHFrameInfo(MCSymbol *EHSym, unsigned Num, unsigned P,
bool hC, bool hL,
const std::vector<MachineMove> &M,
const Function *f):
- FnName(FN), Number(Num), PersonalityIndex(P),
+ FunctionEHSym(EHSym), Number(Num), PersonalityIndex(P),
hasCalls(hC), hasLandingPads(hL), Moves(M), function (f) { }
};
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
index 20b959b..d204bba 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
@@ -18,21 +18,22 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/ADT/StringExtras.h"
using namespace llvm;
-Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
- const char *flavor)
+DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
+ const char *flavor)
: 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) {}
-void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const {
+void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
if (isInSection && MAI->getDwarfSectionOffsetDirective())
O << MAI->getDwarfSectionOffsetDirective();
else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
@@ -41,14 +42,125 @@ void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const {
O << 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";
+ case dwarf::DW_EH_PE_omit: return "omit";
+ case dwarf::DW_EH_PE_pcrel: return "pcrel";
+ case dwarf::DW_EH_PE_udata4: return "udata4";
+ case dwarf::DW_EH_PE_udata8: return "udata8";
+ case dwarf::DW_EH_PE_sdata4: return "sdata4";
+ case dwarf::DW_EH_PE_sdata8: return "sdata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
+ return "indirect pcrel udata4";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
+ return "indirect pcrel sdata4";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
+ return "indirect pcrel udata8";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
+ return "indirect pcrel sdata8";
+ }
+
+ return "<unknown encoding>";
+}
+
+/// 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 an optional string saying what the
+/// encoding is specifying (e.g. "LSDA").
+void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) {
+ if (Asm->VerboseAsm) {
+ if (Desc != 0)
+ Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
+ Twine(DecodeDWARFEncoding(Val)));
+ else
+ Asm->OutStreamer.AddComment(Twine("Encoding = ") +
+ DecodeDWARFEncoding(Val));
+ }
+
+ Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
+}
+
+/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
+void DwarfPrinter::EmitCFAByte(unsigned Val) {
+ if (Asm->VerboseAsm) {
+ if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
+ Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" +
+ Twine(Val-dwarf::DW_CFA_offset) + ")");
+ else
+ Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val));
+ }
+ Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
+}
+
+/// EmitSLEB128 - emit the specified signed leb128 value.
+void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const {
+ if (Asm->VerboseAsm && Desc)
+ Asm->OutStreamer.AddComment(Desc);
+
+ if (MAI->hasLEB128()) {
+ O << "\t.sleb128\t" << Value;
+ Asm->OutStreamer.AddBlankLine();
+ return;
+ }
+
+ // If we don't have .sleb128, emit as .bytes.
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
+
+ do {
+ unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ if (IsMore) Byte |= 0x80;
+
+ Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
+ } while (IsMore);
+}
+
+/// EmitULEB128 - emit the specified signed leb128 value.
+void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const {
+ if (Asm->VerboseAsm && Desc)
+ Asm->OutStreamer.AddComment(Desc);
+
+ if (MAI->hasLEB128()) {
+ O << "\t.uleb128\t" << Value;
+ Asm->OutStreamer.AddBlankLine();
+ return;
+ }
+
+ // If we don't have .uleb128, emit as .bytes.
+ do {
+ unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
+ Value >>= 7;
+ if (Value) Byte |= 0x80;
+ Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
+ } while (Value);
+}
+
+
/// PrintLabelName - Print label name in form used by Dwarf writer.
///
-void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const {
+void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
O << MAI->getPrivateGlobalPrefix() << Tag;
if (Number) O << Number;
}
-void Dwarf::PrintLabelName(const char *Tag, unsigned Number,
- const char *Suffix) const {
+void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
+ const char *Suffix) const {
O << MAI->getPrivateGlobalPrefix() << Tag;
if (Number) O << Number;
O << Suffix;
@@ -56,32 +168,39 @@ void Dwarf::PrintLabelName(const char *Tag, unsigned Number,
/// EmitLabel - Emit location label for internal use by Dwarf.
///
-void Dwarf::EmitLabel(const char *Tag, unsigned Number) const {
+void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
PrintLabelName(Tag, Number);
O << ":\n";
}
/// EmitReference - Emit a reference to a label.
///
-void Dwarf::EmitReference(const char *Tag, unsigned Number,
- bool IsPCRelative, bool Force32Bit) const {
+void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
+ bool IsPCRelative, bool Force32Bit) const {
PrintRelDirective(Force32Bit);
PrintLabelName(Tag, Number);
if (IsPCRelative) O << "-" << MAI->getPCSymbol();
}
-void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative,
- bool Force32Bit) const {
+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();
+}
+
/// EmitDifference - Emit the difference between two labels. Some assemblers do
/// not behave with absolute expressions with data directives, so there is an
/// option (needsSet) to use an intermediary set expression.
-void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi,
- const char *TagLo, unsigned NumberLo,
- bool IsSmall) {
+void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
+ const char *TagLo, unsigned NumberLo,
+ bool IsSmall) {
if (MAI->needsSet()) {
O << "\t.set\t";
PrintLabelName("set", SetCounter, Flavor);
@@ -102,10 +221,11 @@ void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi,
}
}
-void Dwarf::EmitSectionOffset(const char* Label, const char* Section,
- unsigned LabelNumber, unsigned SectionNumber,
- bool IsSmall, bool isEH,
- bool useSet) {
+void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
+ unsigned LabelNumber,
+ unsigned SectionNumber,
+ bool IsSmall, bool isEH,
+ bool useSet) {
bool printAbsolute = false;
if (isEH)
printAbsolute = MAI->isAbsoluteEHSectionOffsets();
@@ -140,8 +260,9 @@ void Dwarf::EmitSectionOffset(const char* Label, const char* Section,
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
-void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
- const std::vector<MachineMove> &Moves, bool isEH) {
+void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
+ const std::vector<MachineMove> &Moves,
+ bool isEH) {
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
@@ -164,10 +285,9 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
// Advance row if new location.
if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
- Asm->EmitInt8(dwarf::DW_CFA_advance_loc4);
- Asm->EOL("DW_CFA_advance_loc4");
+ EmitCFAByte(dwarf::DW_CFA_advance_loc4);
EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
- Asm->EOL();
+ Asm->O << '\n';
BaseLabelID = LabelID;
BaseLabel = "label";
@@ -178,29 +298,22 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
if (!Src.isReg()) {
if (Src.getReg() == MachineLocation::VirtualFP) {
- Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset);
- Asm->EOL("DW_CFA_def_cfa_offset");
+ EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
} else {
- Asm->EmitInt8(dwarf::DW_CFA_def_cfa);
- Asm->EOL("DW_CFA_def_cfa");
- Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH));
- Asm->EOL("Register");
+ EmitCFAByte(dwarf::DW_CFA_def_cfa);
+ EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
}
int Offset = -Src.getOffset();
-
- Asm->EmitULEB128Bytes(Offset);
- Asm->EOL("Offset");
+ EmitULEB128(Offset, "Offset");
} else {
llvm_unreachable("Machine move not supported yet.");
}
} else if (Src.isReg() &&
Src.getReg() == MachineLocation::VirtualFP) {
if (Dst.isReg()) {
- Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register);
- Asm->EOL("DW_CFA_def_cfa_register");
- Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH));
- Asm->EOL("Register");
+ EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
+ EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
} else {
llvm_unreachable("Machine move not supported yet.");
}
@@ -209,27 +322,16 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
int Offset = Dst.getOffset() / stackGrowth;
if (Offset < 0) {
- Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf);
- Asm->EOL("DW_CFA_offset_extended_sf");
- Asm->EmitULEB128Bytes(Reg);
- Asm->EOL("Reg");
- Asm->EmitSLEB128Bytes(Offset);
- Asm->EOL("Offset");
+ EmitCFAByte(dwarf::DW_CFA_offset_extended_sf);
+ EmitULEB128(Reg, "Reg");
+ EmitSLEB128(Offset, "Offset");
} else if (Reg < 64) {
- Asm->EmitInt8(dwarf::DW_CFA_offset + Reg);
- if (Asm->isVerbose())
- Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")");
- else
- Asm->EOL();
- Asm->EmitULEB128Bytes(Offset);
- Asm->EOL("Offset");
+ EmitCFAByte(dwarf::DW_CFA_offset + Reg);
+ EmitULEB128(Offset, "Offset");
} else {
- Asm->EmitInt8(dwarf::DW_CFA_offset_extended);
- Asm->EOL("DW_CFA_offset_extended");
- Asm->EmitULEB128Bytes(Reg);
- Asm->EOL("Reg");
- Asm->EmitULEB128Bytes(Offset);
- Asm->EOL("Offset");
+ EmitCFAByte(dwarf::DW_CFA_offset_extended);
+ EmitULEB128(Reg, "Reg");
+ EmitULEB128(Offset, "Offset");
}
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
index dedd695..86fe2ab 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
@@ -17,135 +17,149 @@
#include "DwarfLabel.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormattedStream.h"
#include <vector>
namespace llvm {
- class AsmPrinter;
- class MachineFunction;
- class MachineModuleInfo;
- class Module;
- class MCAsmInfo;
- class TargetData;
- class TargetRegisterInfo;
-
- class Dwarf {
- protected:
- //===-------------------------------------------------------------==---===//
- // Core attributes used by the DWARF printer.
- //
-
- /// O - Stream to .s file.
- ///
- raw_ostream &O;
-
- /// Asm - Target of Dwarf emission.
- ///
- AsmPrinter *Asm;
-
- /// MAI - Target asm information.
- ///
- const MCAsmInfo *MAI;
-
- /// TD - Target data.
- ///
- const TargetData *TD;
-
- /// RI - Register Information.
- ///
- const TargetRegisterInfo *RI;
-
- /// M - Current module.
- ///
- Module *M;
-
- /// MF - Current machine function.
- ///
- MachineFunction *MF;
-
- /// MMI - Collected machine module information.
- ///
- MachineModuleInfo *MMI;
-
- /// 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;
-
- Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
- const char *flavor);
- public:
- //===------------------------------------------------------------------===//
- // Accessors.
- //
- const AsmPrinter *getAsm() const { return Asm; }
- MachineModuleInfo *getMMI() const { return MMI; }
- const MCAsmInfo *getMCAsmInfo() const { return MAI; }
- const TargetData *getTargetData() const { return TD; }
-
- void PrintRelDirective(bool Force32Bit = false,
- bool isInSection = false) 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;
-
- /// EmitDifference - Emit the difference between two labels. Some
- /// assemblers do not behave with absolute expressions with data directives,
- /// so there is an option (needsSet) to use an intermediary set expression.
- 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,
- bool IsSmall = false);
-
- void EmitSectionOffset(const char* Label, const char* Section,
- unsigned LabelNumber, unsigned SectionNumber,
- bool IsSmall = false, bool isEH = false,
- bool useSet = true);
-
- /// EmitFrameMoves - Emit frame instructions to describe the layout of the
- /// frame.
- void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
- const std::vector<MachineMove> &Moves, bool isEH);
+class AsmPrinter;
+class MachineFunction;
+class MachineModuleInfo;
+class Module;
+class MCAsmInfo;
+class TargetData;
+class TargetRegisterInfo;
+class MCSymbol;
+class Twine;
+
+class DwarfPrinter {
+protected:
+ //===-------------------------------------------------------------==---===//
+ // Core attributes used by the DWARF printer.
+ //
+
+ /// O - Stream to .s file.
+ raw_ostream &O;
+
+ /// Asm - Target of Dwarf emission.
+ AsmPrinter *Asm;
+
+ /// MAI - Target asm information.
+ const MCAsmInfo *MAI;
+
+ /// TD - Target data.
+ const TargetData *TD;
+
+ /// RI - Register Information.
+ const TargetRegisterInfo *RI;
+
+ /// M - Current module.
+ Module *M;
+
+ /// MF - Current machine function.
+ MachineFunction *MF;
+
+ /// MMI - Collected machine module information.
+ MachineModuleInfo *MMI;
+
+ /// 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);
+public:
+
+ //===------------------------------------------------------------------===//
+ // Accessors.
+ //
+ const AsmPrinter *getAsm() const { return Asm; }
+ MachineModuleInfo *getMMI() const { return MMI; }
+ const MCAsmInfo *getMCAsmInfo() const { return MAI; }
+ const TargetData *getTargetData() const { return TD; }
+
+ 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
+ /// specifying (e.g. "LSDA").
+ void EmitEncodingByte(unsigned Val, const char *Desc);
+
+ /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
+ void EmitCFAByte(unsigned Val);
+
+
+ /// EmitSLEB128 - emit the specified signed leb128 value.
+ void EmitSLEB128(int Value, const char *Desc) const;
+
+ /// EmitULEB128 - emit the specified unsigned leb128 value.
+ void EmitULEB128(unsigned Value, const char *Desc = 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;
+
+ /// EmitDifference - Emit the difference between two labels. Some
+ /// assemblers do not behave with absolute expressions with data directives,
+ /// so there is an option (needsSet) to use an intermediary set expression.
+ 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,
+ bool IsSmall = false);
+
+ void EmitSectionOffset(const char* Label, const char* Section,
+ unsigned LabelNumber, unsigned SectionNumber,
+ bool IsSmall = false, bool isEH = false,
+ bool useSet = true);
+
+ /// EmitFrameMoves - Emit frame instructions to describe the layout of the
+ /// frame.
+ void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
+ const std::vector<MachineMove> &Moves, bool isEH);
};
} // end llvm namespace
diff --git a/lib/CodeGen/AsmPrinter/Makefile b/lib/CodeGen/AsmPrinter/Makefile
index 8f65d8d..b0071d0 100644
--- a/lib/CodeGen/AsmPrinter/Makefile
+++ b/lib/CodeGen/AsmPrinter/Makefile
@@ -1,4 +1,4 @@
-##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===##
+##===- lib/CodeGen/AsmPrinter/Makefile ---------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -6,8 +6,9 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMAsmPrinter
-PARALLEL_DIRS =
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index 9286ad5..3531ed6 100644
--- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -21,7 +21,7 @@
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormattedStream.h"
using namespace llvm;
namespace {
@@ -105,8 +105,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection());
EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end");
- OS << AddressDirective << 0; // FIXME: Why does ocaml emit this??
- AP.EOL();
+ OS << AddressDirective << 0 << '\n'; // FIXME: Why does ocaml emit this??
AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection());
EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable");
@@ -140,14 +139,11 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
}
OS << AddressDirective
- << MAI.getPrivateGlobalPrefix() << "label" << J->Num;
- AP.EOL("call return address");
+ << MAI.getPrivateGlobalPrefix() << "label" << J->Num << '\n';
AP.EmitInt16(FrameSize);
- AP.EOL("stack frame size");
AP.EmitInt16(LiveCount);
- AP.EOL("live root count");
for (GCFunctionInfo::live_iterator K = FI.live_begin(J),
KE = FI.live_end(J); K != KE; ++K) {
@@ -155,8 +151,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
"GC root stack offset is outside of fixed stack frame and out "
"of range for ocaml GC!");
- OS << "\t.word\t" << K->StackOffset;
- AP.EOL("stack offset");
+ AP.EmitInt32(K->StackOffset);
}
AP.EmitAlignment(AddressAlignLog);
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 6bc808c..17072d3 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -21,7 +21,6 @@ add_llvm_library(LLVMCodeGen
LiveStackAnalysis.cpp
LiveVariables.cpp
LowerSubregs.cpp
- MachOCodeEmitter.cpp
MachOWriter.cpp
MachineBasicBlock.cpp
MachineDominators.cpp
@@ -38,7 +37,6 @@ add_llvm_library(LLVMCodeGen
MachineSSAUpdater.cpp
MachineSink.cpp
MachineVerifier.cpp
- MaxStackAlignment.cpp
ObjectCodeEmitter.cpp
OcamlGC.cpp
OptimizeExts.cpp
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 9b516ed..39fc85e 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -21,6 +21,7 @@
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
@@ -114,6 +115,9 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) {
bool DwarfEHPrepare::NormalizeLandingPads() {
bool Changed = false;
+ const MCAsmInfo *MAI = TLI->getTargetMachine().getMCAsmInfo();
+ bool usingSjLjEH = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
+
for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
TerminatorInst *TI = I->getTerminator();
if (!isa<InvokeInst>(TI))
@@ -125,9 +129,18 @@ bool DwarfEHPrepare::NormalizeLandingPads() {
// Check that only invoke unwind edges end at the landing pad.
bool OnlyUnwoundTo = true;
+ bool SwitchOK = usingSjLjEH;
for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad);
PI != PE; ++PI) {
TerminatorInst *PT = (*PI)->getTerminator();
+ // The SjLj dispatch block uses a switch instruction. This is effectively
+ // an unwind edge, so we can disregard it here. There will only ever
+ // be one dispatch, however, so if there are multiple switches, one
+ // of them truly is a normal edge, not an unwind edge.
+ if (SwitchOK && isa<SwitchInst>(PT)) {
+ SwitchOK = false;
+ continue;
+ }
if (!isa<InvokeInst>(PT) || LPad == PT->getSuccessor(0)) {
OnlyUnwoundTo = false;
break;
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 5e5f589..de45e09 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -45,6 +45,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetLowering.h"
@@ -52,9 +53,8 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
-
+#include "llvm/ADT/SmallString.h"
using namespace llvm;
char ELFWriter::ID = 0;
@@ -119,7 +119,7 @@ bool ELFWriter::doInitialization(Module &M) {
// Initialize TargetLoweringObjectFile.
const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(OutContext, TM);
- Mang = new Mangler(M);
+ Mang = new Mangler(*MAI);
// ELF Header
// ----------
@@ -703,10 +703,6 @@ bool ELFWriter::doFinalization(Module &M) {
I != E; ++I)
SymbolList.push_back(ELFSym::getExtSym(*I));
- // Emit non-executable stack note
- if (MAI->getNonexecutableStackDirective())
- getNonExecStackSection();
-
// Emit a symbol for each section created until now, skip null section
for (unsigned i = 1, e = SectionList.size(); i < e; ++i) {
ELFSection &ES = *SectionList[i];
@@ -906,9 +902,11 @@ void ELFWriter::EmitStringTable(const std::string &ModuleName) {
ELFSym &Sym = *(*I);
std::string Name;
- if (Sym.isGlobalValue())
- Name.append(Mang->getMangledName(Sym.getGlobalValue()));
- else if (Sym.isExternalSym())
+ if (Sym.isGlobalValue()) {
+ SmallString<40> NameStr;
+ Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false);
+ Name.append(NameStr.begin(), NameStr.end());
+ } else if (Sym.isExternalSym())
Name.append(Sym.getExternalSymbol());
else if (Sym.isFileType())
Name.append(ModuleName);
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 2b5fd2c..837e184 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -17,6 +17,7 @@
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/FileWriters.h"
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/Target/TargetOptions.h"
@@ -38,6 +39,8 @@ static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden,
cl::desc("Disable branch folding"));
static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden,
cl::desc("Disable tail duplication"));
+static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden,
+ cl::desc("Disable pre-register allocation tail duplication"));
static cl::opt<bool> DisableCodePlace("disable-code-place", cl::Hidden,
cl::desc("Disable code placement"));
static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden,
@@ -76,9 +79,6 @@ EnableFastISelOption("fast-isel", cl::Hidden,
static cl::opt<bool> EnableSplitGEPGVN("split-gep-gvn", cl::Hidden,
cl::desc("Split GEPs and run no-load GVN"));
-static cl::opt<bool> PreAllocTailDup("pre-regalloc-taildup", cl::Hidden,
- cl::desc("Pre-register allocation tail duplication"));
-
LLVMTargetMachine::LLVMTargetMachine(const Target &T,
const std::string &TargetTriple)
: TargetMachine(T) {
@@ -115,12 +115,11 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
return FileModel::Error;
return FileModel::AsmFile;
case TargetMachine::ObjectFile:
- if (getMachOWriterInfo())
+ if (!addObjectFileEmitter(PM, OptLevel, Out))
return FileModel::MachOFile;
else if (getELFWriterInfo())
- return FileModel::ElfFile;
+ return FileModel::ElfFile;
}
-
return FileModel::Error;
}
@@ -137,6 +136,17 @@ bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
return false;
}
+bool LLVMTargetMachine::addObjectFileEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ formatted_raw_ostream &Out) {
+ MCCodeEmitter *Emitter = getTarget().createCodeEmitter(*this);
+ if (!Emitter)
+ return true;
+
+ PM.add(createMachOWriter(Out, *this, getMCAsmInfo(), Emitter));
+ return false;
+}
+
/// addPassesToEmitFileFinish - If the passes to emit the specified file had to
/// be split up (e.g., to add an object writer pass), this method can be used to
/// finish up adding passes to emit the file, if necessary.
@@ -340,8 +350,7 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
}
// Pre-ra tail duplication.
- if (OptLevel != CodeGenOpt::None &&
- !DisableTailDuplicate && PreAllocTailDup) {
+ if (OptLevel != CodeGenOpt::None && !DisableEarlyTailDup) {
PM.add(createTailDuplicatePass(true));
printAndVerify(PM, "After Pre-RegAlloc TailDuplicate",
/* allowDoubleDefs= */ true);
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index e0e2ec8..8746bf9 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -140,7 +140,10 @@ void LiveIntervals::printInstrs(raw_ostream &OS) const {
<< ":\t\t# derived from " << mbbi->getName() << "\n";
for (MachineBasicBlock::iterator mii = mbbi->begin(),
mie = mbbi->end(); mii != mie; ++mii) {
- OS << getInstructionIndex(mii) << '\t' << *mii;
+ if (mii->getOpcode()==TargetInstrInfo::DEBUG_VALUE)
+ OS << SlotIndex::getEmptyKey() << '\t' << *mii;
+ else
+ OS << getInstructionIndex(mii) << '\t' << *mii;
}
}
}
@@ -672,8 +675,6 @@ void LiveIntervals::computeIntervals() {
SlotIndex MIIndex = getMBBStartIdx(MBB);
DEBUG(dbgs() << MBB->getName() << ":\n");
- MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end();
-
// Create intervals for live-ins to this BB first.
for (MachineBasicBlock::const_livein_iterator LI = MBB->livein_begin(),
LE = MBB->livein_end(); LI != LE; ++LI) {
@@ -689,8 +690,11 @@ void LiveIntervals::computeIntervals() {
if (getInstructionFromIndex(MIIndex) == 0)
MIIndex = indexes_->getNextNonNullIndex(MIIndex);
- for (; MI != miEnd; ++MI) {
+ for (MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end();
+ MI != miEnd; ++MI) {
DEBUG(dbgs() << MIIndex << "\t" << *MI);
+ if (MI->getOpcode()==TargetInstrInfo::DEBUG_VALUE)
+ continue;
// Handle defs.
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
diff --git a/lib/CodeGen/MachO.h b/lib/CodeGen/MachO.h
deleted file mode 100644
index f2b40fe..0000000
--- a/lib/CodeGen/MachO.h
+++ /dev/null
@@ -1,412 +0,0 @@
-//=== MachO.h - Mach-O structures and constants -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines MachO .
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MACHO_H
-#define MACHO_H
-
-#include "llvm/CodeGen/BinaryObject.h"
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-class GlobalValue;
-class MCAsmInfo;
-
-/// MachOSym - This struct contains information about each symbol that is
-/// added to logical symbol table for the module. This is eventually
-/// turned into a real symbol table in the file.
-struct MachOSym {
- const GlobalValue *GV; // The global value this corresponds to.
- std::string GVName; // The mangled name of the global value.
- uint32_t n_strx; // index into the string table
- uint8_t n_type; // type flag
- uint8_t n_sect; // section number or NO_SECT
- int16_t n_desc; // see <mach-o/stab.h>
- uint64_t n_value; // value for this symbol (or stab offset)
-
- // Constants for the n_sect field
- // see <mach-o/nlist.h>
- enum { NO_SECT = 0 }; // symbol is not in any section
-
- // Constants for the n_type field
- // see <mach-o/nlist.h>
- enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT
- N_ABS = 0x2, // absolute, n_sect == NO_SECT
- N_SECT = 0xe, // defined in section number n_sect
- N_PBUD = 0xc, // prebound undefined (defined in a dylib)
- N_INDR = 0xa // indirect
- };
- // The following bits are OR'd into the types above. For example, a type
- // of 0x0f would be an external N_SECT symbol (0x0e | 0x01).
- enum { N_EXT = 0x01, // external symbol bit
- N_PEXT = 0x10 // private external symbol bit
- };
-
- // Constants for the n_desc field
- // see <mach-o/loader.h>
- enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
- REFERENCE_FLAG_UNDEFINED_LAZY = 1,
- REFERENCE_FLAG_DEFINED = 2,
- REFERENCE_FLAG_PRIVATE_DEFINED = 3,
- REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
- REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5
- };
- enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped
- N_WEAK_REF = 0x0040, // symbol is weak referenced
- N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition
- };
-
- MachOSym(const GlobalValue *gv, std::string name, uint8_t sect,
- const MCAsmInfo *MAI);
-
- struct SymCmp {
- // FIXME: this does not appear to be sorting 'f' after 'F'
- bool operator()(const MachOSym &LHS, const MachOSym &RHS) {
- return LHS.GVName < RHS.GVName;
- }
- };
-
-
- /// PartitionByLocal - Simple boolean predicate that returns true if Sym is
- /// a local symbol rather than an external symbol.
-
- static inline bool PartitionByLocal(const MachOSym &Sym) {
- return (Sym.n_type & (MachOSym::N_EXT | MachOSym::N_PEXT)) == 0;
- }
-
- /// PartitionByDefined - Simple boolean predicate that returns true if Sym is
- /// defined in this module.
-
- static inline bool PartitionByDefined(const MachOSym &Sym) {
- // FIXME: Do N_ABS or N_INDR count as defined?
- return (Sym.n_type & MachOSym::N_SECT) == MachOSym::N_SECT;
- }
-
-}; // end struct MachOSym
-
-/// MachOHeader - This struct contains the header information about a
-/// specific architecture type/subtype pair that is emitted to the file.
-
-struct MachOHeader {
- uint32_t magic; // mach magic number identifier
- uint32_t filetype; // type of file
- uint32_t ncmds; // number of load commands
- uint32_t sizeofcmds; // the size of all the load commands
- uint32_t flags; // flags
- uint32_t reserved; // 64-bit only
-
- /// HeaderData - The actual data for the header which we are building
- /// up for emission to the file.
- std::vector<unsigned char> HeaderData;
-
- // Constants for the filetype field
- // see <mach-o/loader.h> for additional info on the various types
- enum { MH_OBJECT = 1, // relocatable object file
- MH_EXECUTE = 2, // demand paged executable file
- MH_FVMLIB = 3, // fixed VM shared library file
- MH_CORE = 4, // core file
- MH_PRELOAD = 5, // preloaded executable file
- MH_DYLIB = 6, // dynamically bound shared library
- MH_DYLINKER = 7, // dynamic link editor
- MH_BUNDLE = 8, // dynamically bound bundle file
- MH_DYLIB_STUB = 9, // shared library stub for static linking only
- MH_DSYM = 10 // companion file wiht only debug sections
- };
-
- // Constants for the flags field
- enum { MH_NOUNDEFS = 1 << 0,
- // the object file has no undefined references
- MH_INCRLINK = 1 << 1,
- // the object file is the output of an incremental link against
- // a base file and cannot be link edited again
- MH_DYLDLINK = 1 << 2,
- // the object file is input for the dynamic linker and cannot be
- // statically link edited again.
- MH_BINDATLOAD = 1 << 3,
- // the object file's undefined references are bound by the
- // dynamic linker when loaded.
- MH_PREBOUND = 1 << 4,
- // the file has its dynamic undefined references prebound
- MH_SPLIT_SEGS = 1 << 5,
- // the file has its read-only and read-write segments split
- // see <mach/shared_memory_server.h>
- MH_LAZY_INIT = 1 << 6,
- // the shared library init routine is to be run lazily via
- // catching memory faults to its writable segments (obsolete)
- MH_TWOLEVEL = 1 << 7,
- // the image is using two-level namespace bindings
- MH_FORCE_FLAT = 1 << 8,
- // the executable is forcing all images to use flat namespace
- // bindings.
- MH_NOMULTIDEFS = 1 << 8,
- // this umbrella guarantees no multiple definitions of symbols
- // in its sub-images so the two-level namespace hints can
- // always be used.
- MH_NOFIXPREBINDING = 1 << 10,
- // do not have dyld notify the prebidning agent about this
- // executable.
- MH_PREBINDABLE = 1 << 11,
- // the binary is not prebound but can have its prebinding
- // redone. only used when MH_PREBOUND is not set.
- MH_ALLMODSBOUND = 1 << 12,
- // indicates that this binary binds to all two-level namespace
- // modules of its dependent libraries. Only used when
- // MH_PREBINDABLE and MH_TWOLEVEL are both set.
- MH_SUBSECTIONS_VIA_SYMBOLS = 1 << 13,
- // safe to divide up the sections into sub-sections via symbols
- // for dead code stripping.
- MH_CANONICAL = 1 << 14,
- // the binary has been canonicalized via the unprebind operation
- MH_WEAK_DEFINES = 1 << 15,
- // the final linked image contains external weak symbols
- MH_BINDS_TO_WEAK = 1 << 16,
- // the final linked image uses weak symbols
- MH_ALLOW_STACK_EXECUTION = 1 << 17
- // When this bit is set, all stacks in the task will be given
- // stack execution privilege. Only used in MH_EXECUTE filetype
- };
-
- MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0),
- reserved(0) {}
-
- /// cmdSize - This routine returns the size of the MachOSection as written
- /// to disk, depending on whether the destination is a 64 bit Mach-O file.
- unsigned cmdSize(bool is64Bit) const {
- if (is64Bit)
- return 8 * sizeof(uint32_t);
- else
- return 7 * sizeof(uint32_t);
- }
-
- /// setMagic - This routine sets the appropriate value for the 'magic'
- /// field based on pointer size and endianness.
- void setMagic(bool isLittleEndian, bool is64Bit) {
- if (isLittleEndian)
- if (is64Bit) magic = 0xcffaedfe;
- else magic = 0xcefaedfe;
- else
- if (is64Bit) magic = 0xfeedfacf;
- else magic = 0xfeedface;
- }
-
-}; // end struct MachOHeader
-
-/// MachOSegment - This struct contains the necessary information to
-/// emit the load commands for each section in the file.
-struct MachOSegment {
- uint32_t cmd; // LC_SEGMENT or LC_SEGMENT_64
- uint32_t cmdsize; // Total size of this struct and section commands
- std::string segname; // segment name
- uint64_t vmaddr; // address of this segment
- uint64_t vmsize; // size of this segment, may be larger than filesize
- uint64_t fileoff; // offset in file
- uint64_t filesize; // amount to read from file
- uint32_t maxprot; // maximum VM protection
- uint32_t initprot; // initial VM protection
- uint32_t nsects; // number of sections in this segment
- uint32_t flags; // flags
-
- // The following constants are getting pulled in by one of the
- // system headers, which creates a neat clash with the enum.
-#if !defined(VM_PROT_NONE)
-#define VM_PROT_NONE 0x00
-#endif
-#if !defined(VM_PROT_READ)
-#define VM_PROT_READ 0x01
-#endif
-#if !defined(VM_PROT_WRITE)
-#define VM_PROT_WRITE 0x02
-#endif
-#if !defined(VM_PROT_EXECUTE)
-#define VM_PROT_EXECUTE 0x04
-#endif
-#if !defined(VM_PROT_ALL)
-#define VM_PROT_ALL 0x07
-#endif
-
- // Constants for the vm protection fields
- // see <mach-o/vm_prot.h>
- enum { SEG_VM_PROT_NONE = VM_PROT_NONE,
- SEG_VM_PROT_READ = VM_PROT_READ, // read permission
- SEG_VM_PROT_WRITE = VM_PROT_WRITE, // write permission
- SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE,
- SEG_VM_PROT_ALL = VM_PROT_ALL
- };
-
- // Constants for the cmd field
- // see <mach-o/loader.h>
- enum { LC_SEGMENT = 0x01, // segment of this file to be mapped
- LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped
- };
-
- /// cmdSize - This routine returns the size of the MachOSection as written
- /// to disk, depending on whether the destination is a 64 bit Mach-O file.
- unsigned cmdSize(bool is64Bit) const {
- if (is64Bit)
- return 6 * sizeof(uint32_t) + 4 * sizeof(uint64_t) + 16;
- else
- return 10 * sizeof(uint32_t) + 16; // addresses only 32 bits
- }
-
- MachOSegment(const std::string &seg, bool is64Bit)
- : cmd(is64Bit ? LC_SEGMENT_64 : LC_SEGMENT), cmdsize(0), segname(seg),
- vmaddr(0), vmsize(0), fileoff(0), filesize(0), maxprot(VM_PROT_ALL),
- initprot(VM_PROT_ALL), nsects(0), flags(0) { }
-};
-
-/// MachOSection - This struct contains information about each section in a
-/// particular segment that is emitted to the file. This is eventually
-/// turned into the SectionCommand in the load command for a particlar
-/// segment.
-
-struct MachOSection : public BinaryObject {
- std::string sectname; // name of this section,
- std::string segname; // segment this section goes in
- uint64_t addr; // memory address of this section
- uint32_t offset; // file offset of this section
- uint32_t align; // section alignment (power of 2)
- uint32_t reloff; // file offset of relocation entries
- uint32_t nreloc; // number of relocation entries
- uint32_t flags; // flags (section type and attributes)
- uint32_t reserved1; // reserved (for offset or index)
- uint32_t reserved2; // reserved (for count or sizeof)
- uint32_t reserved3; // reserved (64 bit only)
-
- /// A unique number for this section, which will be used to match symbols
- /// to the correct section.
- uint32_t Index;
-
- /// RelocBuffer - A buffer to hold the mach-o relocations before we write
- /// them out at the appropriate location in the file.
- std::vector<unsigned char> RelocBuffer;
-
- // Constants for the section types (low 8 bits of flags field)
- // see <mach-o/loader.h>
- enum { S_REGULAR = 0,
- // regular section
- S_ZEROFILL = 1,
- // zero fill on demand section
- S_CSTRING_LITERALS = 2,
- // section with only literal C strings
- S_4BYTE_LITERALS = 3,
- // section with only 4 byte literals
- S_8BYTE_LITERALS = 4,
- // section with only 8 byte literals
- S_LITERAL_POINTERS = 5,
- // section with only pointers to literals
- S_NON_LAZY_SYMBOL_POINTERS = 6,
- // section with only non-lazy symbol pointers
- S_LAZY_SYMBOL_POINTERS = 7,
- // section with only lazy symbol pointers
- S_SYMBOL_STUBS = 8,
- // section with only symbol stubs
- // byte size of stub in the reserved2 field
- S_MOD_INIT_FUNC_POINTERS = 9,
- // section with only function pointers for initialization
- S_MOD_TERM_FUNC_POINTERS = 10,
- // section with only function pointers for termination
- S_COALESCED = 11,
- // section contains symbols that are coalesced
- S_GB_ZEROFILL = 12,
- // zero fill on demand section (that can be larger than 4GB)
- S_INTERPOSING = 13,
- // section with only pairs of function pointers for interposing
- S_16BYTE_LITERALS = 14
- // section with only 16 byte literals
- };
-
- // Constants for the section flags (high 24 bits of flags field)
- // see <mach-o/loader.h>
- enum { S_ATTR_PURE_INSTRUCTIONS = 1 << 31,
- // section contains only true machine instructions
- S_ATTR_NO_TOC = 1 << 30,
- // section contains coalesced symbols that are not to be in a
- // ranlib table of contents
- S_ATTR_STRIP_STATIC_SYMS = 1 << 29,
- // ok to strip static symbols in this section in files with the
- // MY_DYLDLINK flag
- S_ATTR_NO_DEAD_STRIP = 1 << 28,
- // no dead stripping
- S_ATTR_LIVE_SUPPORT = 1 << 27,
- // blocks are live if they reference live blocks
- S_ATTR_SELF_MODIFYING_CODE = 1 << 26,
- // used with i386 code stubs written on by dyld
- S_ATTR_DEBUG = 1 << 25,
- // a debug section
- S_ATTR_SOME_INSTRUCTIONS = 1 << 10,
- // section contains some machine instructions
- S_ATTR_EXT_RELOC = 1 << 9,
- // section has external relocation entries
- S_ATTR_LOC_RELOC = 1 << 8
- // section has local relocation entries
- };
-
- /// cmdSize - This routine returns the size of the MachOSection as written
- /// to disk, depending on whether the destination is a 64 bit Mach-O file.
- unsigned cmdSize(bool is64Bit) const {
- if (is64Bit)
- return 7 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 32;
- else
- return 9 * sizeof(uint32_t) + 32; // addresses only 32 bits
- }
-
- MachOSection(const std::string &seg, const std::string &sect)
- : BinaryObject(), sectname(sect), segname(seg), addr(0), offset(0),
- align(2), reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0),
- reserved3(0) { }
-
-}; // end struct MachOSection
-
-/// MachOSymTab - This struct contains information about the offsets and
-/// size of symbol table information.
-/// segment.
-struct MachODySymTab {
- uint32_t cmd; // LC_DYSYMTAB
- uint32_t cmdsize; // sizeof(MachODySymTab)
- uint32_t ilocalsym; // index to local symbols
- uint32_t nlocalsym; // number of local symbols
- uint32_t iextdefsym; // index to externally defined symbols
- uint32_t nextdefsym; // number of externally defined symbols
- uint32_t iundefsym; // index to undefined symbols
- uint32_t nundefsym; // number of undefined symbols
- uint32_t tocoff; // file offset to table of contents
- uint32_t ntoc; // number of entries in table of contents
- uint32_t modtaboff; // file offset to module table
- uint32_t nmodtab; // number of module table entries
- uint32_t extrefsymoff; // offset to referenced symbol table
- uint32_t nextrefsyms; // number of referenced symbol table entries
- uint32_t indirectsymoff; // file offset to the indirect symbol table
- uint32_t nindirectsyms; // number of indirect symbol table entries
- uint32_t extreloff; // offset to external relocation entries
- uint32_t nextrel; // number of external relocation entries
- uint32_t locreloff; // offset to local relocation entries
- uint32_t nlocrel; // number of local relocation entries
-
- // Constants for the cmd field
- // see <mach-o/loader.h>
- enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info
- };
-
- MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)),
- ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0),
- iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0),
- nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0),
- nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) {}
-
-}; // end struct MachODySymTab
-
-} // end namespace llvm
-
-#endif
-
diff --git a/lib/CodeGen/MachOCodeEmitter.cpp b/lib/CodeGen/MachOCodeEmitter.cpp
deleted file mode 100644
index 1318477..0000000
--- a/lib/CodeGen/MachOCodeEmitter.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-//===-- MachOEmitter.cpp - Target-independent Mach-O Emitter code --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MachO.h"
-#include "MachOWriter.h"
-#include "MachOCodeEmitter.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
-#include "llvm/CodeGen/MachineRelocation.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/OutputBuffer.h"
-#include <vector>
-
-//===----------------------------------------------------------------------===//
-// MachOCodeEmitter Implementation
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-
-MachOCodeEmitter::MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) :
- ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) {
- is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
- isLittleEndian = TM.getTargetData()->isLittleEndian();
- MAI = TM.getMCAsmInfo();
-}
-
-/// startFunction - This callback is invoked when a new machine function is
-/// about to be emitted.
-
-void MachOCodeEmitter::startFunction(MachineFunction &MF) {
- const TargetData *TD = TM.getTargetData();
- const Function *F = MF.getFunction();
-
- // Align the output buffer to the appropriate alignment, power of 2.
- unsigned FnAlign = F->getAlignment();
- unsigned TDAlign = TD->getPrefTypeAlignment(F->getType());
- unsigned Align = Log2_32(std::max(FnAlign, TDAlign));
- assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
-
- // Get the Mach-O Section that this function belongs in.
- MachOSection *MOS = MOW.getTextSection();
-
- // Upgrade the section alignment if required.
- if (MOS->align < Align) MOS->align = Align;
-
- MOS->emitAlignment(Align);
-
- // Create symbol for function entry
- const GlobalValue *FuncV = MF.getFunction();
- MachOSym FnSym(FuncV, MOW.Mang->getMangledName(FuncV), MOS->Index, MAI);
- FnSym.n_value = getCurrentPCOffset();
-
- // add it to the symtab.
- MOW.SymbolTable.push_back(FnSym);
-}
-
-/// finishFunction - This callback is invoked after the function is completely
-/// finished.
-
-bool MachOCodeEmitter::finishFunction(MachineFunction &MF) {
-
- // Get the Mach-O Section that this function belongs in.
- MachOSection *MOS = MOW.getTextSection();
-
- // Emit constant pool to appropriate section(s)
- emitConstantPool(MF.getConstantPool());
-
- // Emit jump tables to appropriate section
- emitJumpTables(MF.getJumpTableInfo());
-
- // If we have emitted any relocations to function-specific objects such as
- // basic blocks, constant pools entries, or jump tables, record their
- // addresses now so that we can rewrite them with the correct addresses
- // later.
- for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
- MachineRelocation &MR = Relocations[i];
- intptr_t Addr;
-
- if (MR.isBasicBlock()) {
- Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
- MR.setConstantVal(MOS->Index);
- MR.setResultPointer((void*)Addr);
- } else if (MR.isJumpTableIndex()) {
- Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
- MR.setConstantVal(MOW.getJumpTableSection()->Index);
- MR.setResultPointer((void*)Addr);
- } else if (MR.isConstantPoolIndex()) {
- Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
- MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
- MR.setResultPointer((void*)Addr);
- } else if (MR.isGlobalValue()) {
- // FIXME: This should be a set or something that uniques
- MOW.PendingGlobals.push_back(MR.getGlobalValue());
- } else {
- llvm_unreachable("Unhandled relocation type");
- }
- MOS->addRelocation(MR);
- }
- Relocations.clear();
-
- // Clear per-function data structures.
- CPLocations.clear();
- CPSections.clear();
- JTLocations.clear();
- MBBLocations.clear();
-
- return false;
-}
-
-/// emitConstantPool - For each constant pool entry, figure out which section
-/// the constant should live in, allocate space for it, and emit it to the
-/// Section data buffer.
-void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) {
- const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
- if (CP.empty()) return;
-
- // FIXME: handle PIC codegen
- assert(TM.getRelocationModel() != Reloc::PIC_ &&
- "PIC codegen not yet handled for mach-o jump tables!");
-
- // Although there is no strict necessity that I am aware of, we will do what
- // gcc for OS X does and put each constant pool entry in a section of constant
- // objects of a certain size. That means that float constants go in the
- // literal4 section, and double objects go in literal8, etc.
- //
- // FIXME: revisit this decision if we ever do the "stick everything into one
- // "giant object for PIC" optimization.
- for (unsigned i = 0, e = CP.size(); i != e; ++i) {
- const Type *Ty = CP[i].getType();
- unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty);
-
- MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal);
- OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian);
-
- CPLocations.push_back(Sec->size());
- CPSections.push_back(Sec->Index);
-
- // Allocate space in the section for the global.
- // FIXME: need alignment?
- // FIXME: share between here and AddSymbolToSection?
- for (unsigned j = 0; j < Size; ++j)
- SecDataOut.outbyte(0);
-
- MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i],
- TM.getTargetData(), Sec);
- }
-}
-
-/// emitJumpTables - Emit all the jump tables for a given jump table info
-/// record to the appropriate section.
-void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
- const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
- if (JT.empty()) return;
-
- // FIXME: handle PIC codegen
- assert(TM.getRelocationModel() != Reloc::PIC_ &&
- "PIC codegen not yet handled for mach-o jump tables!");
-
- MachOSection *Sec = MOW.getJumpTableSection();
- unsigned TextSecIndex = MOW.getTextSection()->Index;
- OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian);
-
- for (unsigned i = 0, e = JT.size(); i != e; ++i) {
- // For each jump table, record its offset from the start of the section,
- // reserve space for the relocations to the MBBs, and add the relocations.
- const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;
- JTLocations.push_back(Sec->size());
- for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
- MachineRelocation MR(MOW.GetJTRelocation(Sec->size(), MBBs[mi]));
- MR.setResultPointer((void *)JTLocations[i]);
- MR.setConstantVal(TextSecIndex);
- Sec->addRelocation(MR);
- SecDataOut.outaddr(0);
- }
- }
-}
-
-} // end namespace llvm
-
diff --git a/lib/CodeGen/MachOCodeEmitter.h b/lib/CodeGen/MachOCodeEmitter.h
deleted file mode 100644
index 4752446..0000000
--- a/lib/CodeGen/MachOCodeEmitter.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//===-- MachOEmitter.h - Target-independent Mach-O Emitter class ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MACHOCODEEMITTER_H
-#define MACHOCODEEMITTER_H
-
-#include "llvm/CodeGen/ObjectCodeEmitter.h"
-#include <map>
-
-namespace llvm {
-
-class MachOWriter;
-
-/// MachOCodeEmitter - This class is used by the MachOWriter to emit the code
-/// for functions to the Mach-O file.
-
-class MachOCodeEmitter : public ObjectCodeEmitter {
- MachOWriter &MOW;
-
- /// Target machine description.
- TargetMachine &TM;
-
- /// is64Bit/isLittleEndian - This information is inferred from the target
- /// machine directly, indicating what header values and flags to set.
- bool is64Bit, isLittleEndian;
-
- const MCAsmInfo *MAI;
-
- /// Relocations - These are the relocations that the function needs, as
- /// emitted.
- std::vector<MachineRelocation> Relocations;
-
- std::map<uint64_t, uintptr_t> Labels;
-
-public:
- MachOCodeEmitter(MachOWriter &mow, MachOSection &mos);
-
- virtual void startFunction(MachineFunction &MF);
- virtual bool finishFunction(MachineFunction &MF);
-
- virtual void addRelocation(const MachineRelocation &MR) {
- Relocations.push_back(MR);
- }
-
- void emitConstantPool(MachineConstantPool *MCP);
- void emitJumpTables(MachineJumpTableInfo *MJTI);
-
- virtual void emitLabel(uint64_t LabelID) {
- Labels[LabelID] = getCurrentPCOffset();
- }
-
- virtual uintptr_t getLabelAddress(uint64_t Label) const {
- return Labels.find(Label)->second;
- }
-
- virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
-
-}; // end class MachOCodeEmitter
-
-} // end namespace llvm
-
-#endif
-
diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp
index 337eab1..e8bbe21 100644
--- a/lib/CodeGen/MachOWriter.cpp
+++ b/lib/CodeGen/MachOWriter.cpp
@@ -22,33 +22,31 @@
//
//===----------------------------------------------------------------------===//
-#include "MachO.h"
#include "MachOWriter.h"
-#include "MachOCodeEmitter.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/FileWriters.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachOWriterInfo.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/OutputBuffer.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+using namespace llvm;
-namespace llvm {
-
-/// AddMachOWriter - Concrete function to add the Mach-O writer to the function
-/// pass manager.
-ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM,
- raw_ostream &O,
- TargetMachine &TM) {
- MachOWriter *MOW = new MachOWriter(O, TM);
- PM.add(MOW);
- return MOW->getObjectCodeEmitter();
+namespace llvm {
+MachineFunctionPass *createMachOWriter(formatted_raw_ostream &O,
+ TargetMachine &TM,
+ const MCAsmInfo *T,
+ MCCodeEmitter *MCE) {
+ return new MachOWriter(O, TM, T, MCE);
+}
}
//===----------------------------------------------------------------------===//
@@ -57,722 +55,71 @@ ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM,
char MachOWriter::ID = 0;
-MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm)
- : MachineFunctionPass(&ID), O(o), TM(tm) {
- is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
- isLittleEndian = TM.getTargetData()->isLittleEndian();
-
- MAI = TM.getMCAsmInfo();
-
- // Create the machine code emitter object for this target.
- MachOCE = new MachOCodeEmitter(*this, *getTextSection(true));
+MachOWriter::MachOWriter(formatted_raw_ostream &o, TargetMachine &tm,
+ const MCAsmInfo *T, MCCodeEmitter *MCE)
+ : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), MCCE(MCE),
+ OutContext(*new MCContext()),
+ OutStreamer(*createMachOStreamer(OutContext, O, MCCE)) {
}
MachOWriter::~MachOWriter() {
- delete MachOCE;
+ delete &OutStreamer;
+ delete &OutContext;
+ delete MCCE;
}
bool MachOWriter::doInitialization(Module &M) {
- // Set the magic value, now that we know the pointer size and endianness
- Header.setMagic(isLittleEndian, is64Bit);
-
- // Set the file type
- // FIXME: this only works for object files, we do not support the creation
- // of dynamic libraries or executables at this time.
- Header.filetype = MachOHeader::MH_OBJECT;
+ // Initialize TargetLoweringObjectFile.
+ TM.getTargetLowering()->getObjFileLowering().Initialize(OutContext, TM);
- Mang = new Mangler(M);
- return false;
-}
-
-bool MachOWriter::runOnMachineFunction(MachineFunction &MF) {
return false;
}
/// doFinalization - Now that the module has been completely processed, emit
/// the Mach-O file to 'O'.
bool MachOWriter::doFinalization(Module &M) {
- // FIXME: we don't handle debug info yet, we should probably do that.
- // Okay, the.text section has been completed, build the .data, .bss, and
- // "common" sections next.
-
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- EmitGlobal(I);
-
- // Emit the header and load commands.
- EmitHeaderAndLoadCommands();
-
- // Emit the various sections and their relocation info.
- EmitSections();
- EmitRelocations();
-
- // Write the symbol table and the string table to the end of the file.
- O.write((char*)&SymT[0], SymT.size());
- O.write((char*)&StrT[0], StrT.size());
-
- // We are done with the abstract symbols.
- SectionList.clear();
- SymbolTable.clear();
- DynamicSymbolTable.clear();
-
- // Release the name mangler object.
- delete Mang; Mang = 0;
+ OutStreamer.Finish();
return false;
}
-// getConstSection - Get constant section for Constant 'C'
-MachOSection *MachOWriter::getConstSection(Constant *C) {
- const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
- if (CVA && CVA->isCString())
- return getSection("__TEXT", "__cstring",
- MachOSection::S_CSTRING_LITERALS);
-
- const Type *Ty = C->getType();
- if (Ty->isPrimitiveType() || Ty->isInteger()) {
- unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty);
- switch(Size) {
- default: break; // Fall through to __TEXT,__const
- case 4:
- return getSection("__TEXT", "__literal4",
- MachOSection::S_4BYTE_LITERALS);
- case 8:
- return getSection("__TEXT", "__literal8",
- MachOSection::S_8BYTE_LITERALS);
- case 16:
- return getSection("__TEXT", "__literal16",
- MachOSection::S_16BYTE_LITERALS);
- }
- }
- return getSection("__TEXT", "__const");
-}
-
-// getJumpTableSection - Select the Jump Table section
-MachOSection *MachOWriter::getJumpTableSection() {
- if (TM.getRelocationModel() == Reloc::PIC_)
- return getTextSection(false);
- else
- return getSection("__TEXT", "__const");
-}
-
-// getSection - Return the section with the specified name, creating a new
-// section if one does not already exist.
-MachOSection *MachOWriter::getSection(const std::string &seg,
- const std::string &sect,
- unsigned Flags /* = 0 */ ) {
- MachOSection *MOS = SectionLookup[seg+sect];
- if (MOS) return MOS;
-
- MOS = new MachOSection(seg, sect);
- SectionList.push_back(MOS);
- MOS->Index = SectionList.size();
- MOS->flags = MachOSection::S_REGULAR | Flags;
- SectionLookup[seg+sect] = MOS;
- return MOS;
-}
-
-// getTextSection - Return text section with different flags for code/data
-MachOSection *MachOWriter::getTextSection(bool isCode /* = true */ ) {
- if (isCode)
- return getSection("__TEXT", "__text",
- MachOSection::S_ATTR_PURE_INSTRUCTIONS |
- MachOSection::S_ATTR_SOME_INSTRUCTIONS);
- else
- return getSection("__TEXT", "__text");
-}
-
-MachOSection *MachOWriter::getBSSSection() {
- return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL);
-}
-
-// GetJTRelocation - Get a relocation a new BB relocation based
-// on target information.
-MachineRelocation MachOWriter::GetJTRelocation(unsigned Offset,
- MachineBasicBlock *MBB) const {
- return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB);
-}
-
-// GetTargetRelocation - Returns the number of relocations.
-unsigned MachOWriter::GetTargetRelocation(MachineRelocation &MR,
- unsigned FromIdx, unsigned ToAddr,
- unsigned ToIndex, OutputBuffer &RelocOut,
- OutputBuffer &SecOut, bool Scattered,
- bool Extern) {
- return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr,
- ToIndex, RelocOut,
- SecOut, Scattered,
- Extern);
-}
-
-void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) {
- const Type *Ty = GV->getType()->getElementType();
- unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty);
- unsigned Align = TM.getTargetData()->getPreferredAlignment(GV);
-
- // Reserve space in the .bss section for this symbol while maintaining the
- // desired section alignment, which must be at least as much as required by
- // this symbol.
- OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian);
-
- if (Align) {
- Align = Log2_32(Align);
- Sec->align = std::max(unsigned(Sec->align), Align);
-
- Sec->emitAlignment(Sec->align);
- }
- // Globals without external linkage apparently do not go in the symbol table.
- if (!GV->hasLocalLinkage()) {
- MachOSym Sym(GV, Mang->getMangledName(GV), Sec->Index, MAI);
- Sym.n_value = Sec->size();
- SymbolTable.push_back(Sym);
- }
-
- // Record the offset of the symbol, and then allocate space for it.
- // FIXME: remove when we have unified size + output buffer
-
- // Now that we know what section the GlovalVariable is going to be emitted
- // into, update our mappings.
- // FIXME: We may also need to update this when outputting non-GlobalVariable
- // GlobalValues such as functions.
-
- GVSection[GV] = Sec;
- GVOffset[GV] = Sec->size();
-
- // Allocate space in the section for the global.
- for (unsigned i = 0; i < Size; ++i)
- SecDataOut.outbyte(0);
-}
-
-void MachOWriter::EmitGlobal(GlobalVariable *GV) {
- const Type *Ty = GV->getType()->getElementType();
- unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty);
- bool NoInit = !GV->hasInitializer();
-
- // If this global has a zero initializer, it is part of the .bss or common
- // section.
- if (NoInit || GV->getInitializer()->isNullValue()) {
- // If this global is part of the common block, add it now. Variables are
- // part of the common block if they are zero initialized and allowed to be
- // merged with other symbols.
- if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
- GV->hasCommonLinkage()) {
- MachOSym ExtOrCommonSym(GV, Mang->getMangledName(GV),
- MachOSym::NO_SECT, MAI);
- // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in
- // bytes of the symbol.
- ExtOrCommonSym.n_value = Size;
- SymbolTable.push_back(ExtOrCommonSym);
- // Remember that we've seen this symbol
- GVOffset[GV] = Size;
- return;
- }
- // Otherwise, this symbol is part of the .bss section.
- MachOSection *BSS = getBSSSection();
- AddSymbolToSection(BSS, GV);
- return;
- }
-
- // Scalar read-only data goes in a literal section if the scalar is 4, 8, or
- // 16 bytes, or a cstring. Other read only data goes into a regular const
- // section. Read-write data goes in the data section.
- MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) :
- getDataSection();
- AddSymbolToSection(Sec, GV);
- InitMem(GV->getInitializer(), GVOffset[GV], TM.getTargetData(), Sec);
-}
-
-
-
-void MachOWriter::EmitHeaderAndLoadCommands() {
- // Step #0: Fill in the segment load command size, since we need it to figure
- // out the rest of the header fields
-
- MachOSegment SEG("", is64Bit);
- SEG.nsects = SectionList.size();
- SEG.cmdsize = SEG.cmdSize(is64Bit) +
- SEG.nsects * SectionList[0]->cmdSize(is64Bit);
-
- // Step #1: calculate the number of load commands. We always have at least
- // one, for the LC_SEGMENT load command, plus two for the normal
- // and dynamic symbol tables, if there are any symbols.
- Header.ncmds = SymbolTable.empty() ? 1 : 3;
-
- // Step #2: calculate the size of the load commands
- Header.sizeofcmds = SEG.cmdsize;
- if (!SymbolTable.empty())
- Header.sizeofcmds += SymTab.cmdsize + DySymTab.cmdsize;
-
- // Step #3: write the header to the file
- // Local alias to shortenify coming code.
- std::vector<unsigned char> &FH = Header.HeaderData;
- OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
-
- FHOut.outword(Header.magic);
- FHOut.outword(TM.getMachOWriterInfo()->getCPUType());
- FHOut.outword(TM.getMachOWriterInfo()->getCPUSubType());
- FHOut.outword(Header.filetype);
- FHOut.outword(Header.ncmds);
- FHOut.outword(Header.sizeofcmds);
- FHOut.outword(Header.flags);
- if (is64Bit)
- FHOut.outword(Header.reserved);
-
- // Step #4: Finish filling in the segment load command and write it out
- for (std::vector<MachOSection*>::iterator I = SectionList.begin(),
- E = SectionList.end(); I != E; ++I)
- SEG.filesize += (*I)->size();
-
- SEG.vmsize = SEG.filesize;
- SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds;
-
- FHOut.outword(SEG.cmd);
- FHOut.outword(SEG.cmdsize);
- FHOut.outstring(SEG.segname, 16);
- FHOut.outaddr(SEG.vmaddr);
- FHOut.outaddr(SEG.vmsize);
- FHOut.outaddr(SEG.fileoff);
- FHOut.outaddr(SEG.filesize);
- FHOut.outword(SEG.maxprot);
- FHOut.outword(SEG.initprot);
- FHOut.outword(SEG.nsects);
- FHOut.outword(SEG.flags);
-
- // Step #5: Finish filling in the fields of the MachOSections
- uint64_t currentAddr = 0;
- for (std::vector<MachOSection*>::iterator I = SectionList.begin(),
- E = SectionList.end(); I != E; ++I) {
- MachOSection *MOS = *I;
- MOS->addr = currentAddr;
- MOS->offset = currentAddr + SEG.fileoff;
- // FIXME: do we need to do something with alignment here?
- currentAddr += MOS->size();
- }
-
- // Step #6: Emit the symbol table to temporary buffers, so that we know the
- // size of the string table when we write the next load command. This also
- // sorts and assigns indices to each of the symbols, which is necessary for
- // emitting relocations to externally-defined objects.
- BufferSymbolAndStringTable();
-
- // Step #7: Calculate the number of relocations for each section and write out
- // the section commands for each section
- currentAddr += SEG.fileoff;
- for (std::vector<MachOSection*>::iterator I = SectionList.begin(),
- E = SectionList.end(); I != E; ++I) {
- MachOSection *MOS = *I;
-
- // Convert the relocations to target-specific relocations, and fill in the
- // relocation offset for this section.
- CalculateRelocations(*MOS);
- MOS->reloff = MOS->nreloc ? currentAddr : 0;
- currentAddr += MOS->nreloc * 8;
-
- // write the finalized section command to the output buffer
- FHOut.outstring(MOS->sectname, 16);
- FHOut.outstring(MOS->segname, 16);
- FHOut.outaddr(MOS->addr);
- FHOut.outaddr(MOS->size());
- FHOut.outword(MOS->offset);
- FHOut.outword(MOS->align);
- FHOut.outword(MOS->reloff);
- FHOut.outword(MOS->nreloc);
- FHOut.outword(MOS->flags);
- FHOut.outword(MOS->reserved1);
- FHOut.outword(MOS->reserved2);
- if (is64Bit)
- FHOut.outword(MOS->reserved3);
- }
-
- // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands
- SymTab.symoff = currentAddr;
- SymTab.nsyms = SymbolTable.size();
- SymTab.stroff = SymTab.symoff + SymT.size();
- SymTab.strsize = StrT.size();
- FHOut.outword(SymTab.cmd);
- FHOut.outword(SymTab.cmdsize);
- FHOut.outword(SymTab.symoff);
- FHOut.outword(SymTab.nsyms);
- FHOut.outword(SymTab.stroff);
- FHOut.outword(SymTab.strsize);
-
- // FIXME: set DySymTab fields appropriately
- // We should probably just update these in BufferSymbolAndStringTable since
- // thats where we're partitioning up the different kinds of symbols.
- FHOut.outword(DySymTab.cmd);
- FHOut.outword(DySymTab.cmdsize);
- FHOut.outword(DySymTab.ilocalsym);
- FHOut.outword(DySymTab.nlocalsym);
- FHOut.outword(DySymTab.iextdefsym);
- FHOut.outword(DySymTab.nextdefsym);
- FHOut.outword(DySymTab.iundefsym);
- FHOut.outword(DySymTab.nundefsym);
- FHOut.outword(DySymTab.tocoff);
- FHOut.outword(DySymTab.ntoc);
- FHOut.outword(DySymTab.modtaboff);
- FHOut.outword(DySymTab.nmodtab);
- FHOut.outword(DySymTab.extrefsymoff);
- FHOut.outword(DySymTab.nextrefsyms);
- FHOut.outword(DySymTab.indirectsymoff);
- FHOut.outword(DySymTab.nindirectsyms);
- FHOut.outword(DySymTab.extreloff);
- FHOut.outword(DySymTab.nextrel);
- FHOut.outword(DySymTab.locreloff);
- FHOut.outword(DySymTab.nlocrel);
-
- O.write((char*)&FH[0], FH.size());
-}
-
-/// EmitSections - Now that we have constructed the file header and load
-/// commands, emit the data for each section to the file.
-void MachOWriter::EmitSections() {
- for (std::vector<MachOSection*>::iterator I = SectionList.begin(),
- E = SectionList.end(); I != E; ++I)
- // Emit the contents of each section
- if ((*I)->size())
- O.write((char*)&(*I)->getData()[0], (*I)->size());
-}
-
-/// EmitRelocations - emit relocation data from buffer.
-void MachOWriter::EmitRelocations() {
- for (std::vector<MachOSection*>::iterator I = SectionList.begin(),
- E = SectionList.end(); I != E; ++I)
- // Emit the relocation entry data for each section.
- if ((*I)->RelocBuffer.size())
- O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size());
-}
-
-/// BufferSymbolAndStringTable - Sort the symbols we encountered and assign them
-/// each a string table index so that they appear in the correct order in the
-/// output file.
-void MachOWriter::BufferSymbolAndStringTable() {
- // The order of the symbol table is:
- // 1. local symbols
- // 2. defined external symbols (sorted by name)
- // 3. undefined external symbols (sorted by name)
-
- // Before sorting the symbols, check the PendingGlobals for any undefined
- // globals that need to be put in the symbol table.
- for (std::vector<GlobalValue*>::iterator I = PendingGlobals.begin(),
- E = PendingGlobals.end(); I != E; ++I) {
- if (GVOffset[*I] == 0 && GVSection[*I] == 0) {
- MachOSym UndfSym(*I, Mang->getMangledName(*I), MachOSym::NO_SECT, MAI);
- SymbolTable.push_back(UndfSym);
- GVOffset[*I] = -1;
- }
- }
-
- // Sort the symbols by name, so that when we partition the symbols by scope
- // of definition, we won't have to sort by name within each partition.
- std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSym::SymCmp());
-
- // Parition the symbol table entries so that all local symbols come before
- // all symbols with external linkage. { 1 | 2 3 }
- std::partition(SymbolTable.begin(), SymbolTable.end(),
- MachOSym::PartitionByLocal);
-
- // Advance iterator to beginning of external symbols and partition so that
- // all external symbols defined in this module come before all external
- // symbols defined elsewhere. { 1 | 2 | 3 }
- for (std::vector<MachOSym>::iterator I = SymbolTable.begin(),
- E = SymbolTable.end(); I != E; ++I) {
- if (!MachOSym::PartitionByLocal(*I)) {
- std::partition(I, E, MachOSym::PartitionByDefined);
- break;
- }
- }
-
- // Calculate the starting index for each of the local, extern defined, and
- // undefined symbols, as well as the number of each to put in the LC_DYSYMTAB
- // load command.
- for (std::vector<MachOSym>::iterator I = SymbolTable.begin(),
- E = SymbolTable.end(); I != E; ++I) {
- if (MachOSym::PartitionByLocal(*I)) {
- ++DySymTab.nlocalsym;
- ++DySymTab.iextdefsym;
- ++DySymTab.iundefsym;
- } else if (MachOSym::PartitionByDefined(*I)) {
- ++DySymTab.nextdefsym;
- ++DySymTab.iundefsym;
- } else {
- ++DySymTab.nundefsym;
- }
- }
-
- // Write out a leading zero byte when emitting string table, for n_strx == 0
- // which means an empty string.
- OutputBuffer StrTOut(StrT, is64Bit, isLittleEndian);
- StrTOut.outbyte(0);
-
- // The order of the string table is:
- // 1. strings for external symbols
- // 2. strings for local symbols
- // Since this is the opposite order from the symbol table, which we have just
- // sorted, we can walk the symbol table backwards to output the string table.
- for (std::vector<MachOSym>::reverse_iterator I = SymbolTable.rbegin(),
- E = SymbolTable.rend(); I != E; ++I) {
- if (I->GVName == "") {
- I->n_strx = 0;
- } else {
- I->n_strx = StrT.size();
- StrTOut.outstring(I->GVName, I->GVName.length()+1);
- }
- }
-
- OutputBuffer SymTOut(SymT, is64Bit, isLittleEndian);
-
- unsigned index = 0;
- for (std::vector<MachOSym>::iterator I = SymbolTable.begin(),
- E = SymbolTable.end(); I != E; ++I, ++index) {
- // Add the section base address to the section offset in the n_value field
- // to calculate the full address.
- // FIXME: handle symbols where the n_value field is not the address
- GlobalValue *GV = const_cast<GlobalValue*>(I->GV);
- if (GV && GVSection[GV])
- I->n_value += GVSection[GV]->addr;
- if (GV && (GVOffset[GV] == -1))
- GVOffset[GV] = index;
-
- // Emit nlist to buffer
- SymTOut.outword(I->n_strx);
- SymTOut.outbyte(I->n_type);
- SymTOut.outbyte(I->n_sect);
- SymTOut.outhalf(I->n_desc);
- SymTOut.outaddr(I->n_value);
- }
-}
-
-/// CalculateRelocations - For each MachineRelocation in the current section,
-/// calculate the index of the section containing the object to be relocated,
-/// and the offset into that section. From this information, create the
-/// appropriate target-specific MachORelocation type and add buffer it to be
-/// written out after we are finished writing out sections.
-void MachOWriter::CalculateRelocations(MachOSection &MOS) {
- std::vector<MachineRelocation> Relocations = MOS.getRelocations();
- for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
- MachineRelocation &MR = Relocations[i];
- unsigned TargetSection = MR.getConstantVal();
- unsigned TargetAddr = 0;
- unsigned TargetIndex = 0;
-
- // This is a scattered relocation entry if it points to a global value with
- // a non-zero offset.
- bool Scattered = false;
- bool Extern = false;
-
- // Since we may not have seen the GlobalValue we were interested in yet at
- // the time we emitted the relocation for it, fix it up now so that it
- // points to the offset into the correct section.
- if (MR.isGlobalValue()) {
- GlobalValue *GV = MR.getGlobalValue();
- MachOSection *MOSPtr = GVSection[GV];
- intptr_t Offset = GVOffset[GV];
-
- // If we have never seen the global before, it must be to a symbol
- // defined in another module (N_UNDF).
- if (!MOSPtr) {
- // FIXME: need to append stub suffix
- Extern = true;
- TargetAddr = 0;
- TargetIndex = GVOffset[GV];
- } else {
- Scattered = TargetSection != 0;
- TargetSection = MOSPtr->Index;
- }
- MR.setResultPointer((void*)Offset);
- }
-
- // If the symbol is locally defined, pass in the address of the section and
- // the section index to the code which will generate the target relocation.
- if (!Extern) {
- MachOSection &To = *SectionList[TargetSection - 1];
- TargetAddr = To.addr;
- TargetIndex = To.Index;
- }
-
- OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian);
- OutputBuffer SecOut(MOS.getData(), is64Bit, isLittleEndian);
-
- MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex,
- RelocOut, SecOut, Scattered, Extern);
- }
-}
-
-// InitMem - Write the value of a Constant to the specified memory location,
-// converting it into bytes and relocations.
-void MachOWriter::InitMem(const Constant *C, uintptr_t Offset,
- const TargetData *TD, MachOSection* mos) {
- typedef std::pair<const Constant*, intptr_t> CPair;
- std::vector<CPair> WorkList;
- uint8_t *Addr = &mos->getData()[0];
-
- WorkList.push_back(CPair(C,(intptr_t)Addr + Offset));
-
- intptr_t ScatteredOffset = 0;
-
- while (!WorkList.empty()) {
- const Constant *PC = WorkList.back().first;
- intptr_t PA = WorkList.back().second;
- WorkList.pop_back();
-
- if (isa<UndefValue>(PC)) {
- continue;
- } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(PC)) {
- unsigned ElementSize =
- TD->getTypeAllocSize(CP->getType()->getElementType());
- for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
- WorkList.push_back(CPair(CP->getOperand(i), PA+i*ElementSize));
- } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(PC)) {
- //
- // FIXME: Handle ConstantExpression. See EE::getConstantValue()
- //
- switch (CE->getOpcode()) {
- case Instruction::GetElementPtr: {
- SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end());
- ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(),
- &Indices[0], Indices.size());
- WorkList.push_back(CPair(CE->getOperand(0), PA));
- break;
- }
- case Instruction::Add:
- default:
- dbgs() << "ConstantExpr not handled as global var init: " << *CE <<"\n";
- llvm_unreachable(0);
- }
- } else if (PC->getType()->isSingleValueType()) {
- unsigned char *ptr = (unsigned char *)PA;
- switch (PC->getType()->getTypeID()) {
- case Type::IntegerTyID: {
- unsigned NumBits = cast<IntegerType>(PC->getType())->getBitWidth();
- uint64_t val = cast<ConstantInt>(PC)->getZExtValue();
- if (NumBits <= 8)
- ptr[0] = val;
- else if (NumBits <= 16) {
- if (TD->isBigEndian())
- val = ByteSwap_16(val);
- ptr[0] = val;
- ptr[1] = val >> 8;
- } else if (NumBits <= 32) {
- if (TD->isBigEndian())
- val = ByteSwap_32(val);
- ptr[0] = val;
- ptr[1] = val >> 8;
- ptr[2] = val >> 16;
- ptr[3] = val >> 24;
- } else if (NumBits <= 64) {
- if (TD->isBigEndian())
- val = ByteSwap_64(val);
- ptr[0] = val;
- ptr[1] = val >> 8;
- ptr[2] = val >> 16;
- ptr[3] = val >> 24;
- ptr[4] = val >> 32;
- ptr[5] = val >> 40;
- ptr[6] = val >> 48;
- ptr[7] = val >> 56;
- } else {
- llvm_unreachable("Not implemented: bit widths > 64");
+bool MachOWriter::runOnMachineFunction(MachineFunction &MF) {
+ const Function *F = MF.getFunction();
+ TargetLoweringObjectFile &TLOF = TM.getTargetLowering()->getObjFileLowering();
+ const MCSection *S = TLOF.SectionForGlobal(F, Mang, TM);
+ OutStreamer.SwitchSection(S);
+
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ // Print a label for the basic block.
+ for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
+ II != IE; ++II) {
+ const MachineInstr *MI = II;
+ MCInst OutMI;
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ MCOperand MCOp;
+
+ switch (MO.getType()) {
+ default:
+ MI->dump();
+ llvm_unreachable("unknown operand type");
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit()) continue;
+ MCOp = MCOperand::CreateReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::CreateImm(MO.getImm());
+ break;
}
- break;
- }
- case Type::FloatTyID: {
- uint32_t val = cast<ConstantFP>(PC)->getValueAPF().bitcastToAPInt().
- getZExtValue();
- if (TD->isBigEndian())
- val = ByteSwap_32(val);
- ptr[0] = val;
- ptr[1] = val >> 8;
- ptr[2] = val >> 16;
- ptr[3] = val >> 24;
- break;
- }
- case Type::DoubleTyID: {
- uint64_t val = cast<ConstantFP>(PC)->getValueAPF().bitcastToAPInt().
- getZExtValue();
- if (TD->isBigEndian())
- val = ByteSwap_64(val);
- ptr[0] = val;
- ptr[1] = val >> 8;
- ptr[2] = val >> 16;
- ptr[3] = val >> 24;
- ptr[4] = val >> 32;
- ptr[5] = val >> 40;
- ptr[6] = val >> 48;
- ptr[7] = val >> 56;
- break;
- }
- case Type::PointerTyID:
- if (isa<ConstantPointerNull>(PC))
- memset(ptr, 0, TD->getPointerSize());
- else if (const GlobalValue* GV = dyn_cast<GlobalValue>(PC)) {
- // FIXME: what about function stubs?
- mos->addRelocation(MachineRelocation::getGV(PA-(intptr_t)Addr,
- MachineRelocation::VANILLA,
- const_cast<GlobalValue*>(GV),
- ScatteredOffset));
- ScatteredOffset = 0;
- } else
- llvm_unreachable("Unknown constant pointer type!");
- break;
- default:
- std::string msg;
- raw_string_ostream Msg(msg);
- Msg << "ERROR: Constant unimp for type: " << *PC->getType();
- llvm_report_error(Msg.str());
+ OutMI.addOperand(MCOp);
}
- } else if (isa<ConstantAggregateZero>(PC)) {
- memset((void*)PA, 0, (size_t)TD->getTypeAllocSize(PC->getType()));
- } else if (const ConstantArray *CPA = dyn_cast<ConstantArray>(PC)) {
- unsigned ElementSize =
- TD->getTypeAllocSize(CPA->getType()->getElementType());
- for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
- WorkList.push_back(CPair(CPA->getOperand(i), PA+i*ElementSize));
- } else if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(PC)) {
- const StructLayout *SL =
- TD->getStructLayout(cast<StructType>(CPS->getType()));
- for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i)
- WorkList.push_back(CPair(CPS->getOperand(i),
- PA+SL->getElementOffset(i)));
- } else {
- dbgs() << "Bad Type: " << *PC->getType() << "\n";
- llvm_unreachable("Unknown constant type to initialize memory with!");
+
+ OutStreamer.EmitInstruction(OutMI);
}
}
-}
-
-//===----------------------------------------------------------------------===//
-// MachOSym Implementation
-//===----------------------------------------------------------------------===//
-MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect,
- const MCAsmInfo *MAI) :
- GV(gv), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect),
- n_desc(0), n_value(0) {
-
- // FIXME: This is completely broken, it should use the mangler interface.
- switch (GV->getLinkage()) {
- default:
- llvm_unreachable("Unexpected linkage type!");
- break;
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::CommonLinkage:
- assert(!isa<Function>(gv) && "Unexpected linkage type for Function!");
- case GlobalValue::ExternalLinkage:
- GVName = MAI->getGlobalPrefix() + name;
- n_type |= GV->hasHiddenVisibility() ? N_PEXT : N_EXT;
- break;
- case GlobalValue::PrivateLinkage:
- GVName = MAI->getPrivateGlobalPrefix() + name;
- break;
- case GlobalValue::LinkerPrivateLinkage:
- GVName = MAI->getLinkerPrivateGlobalPrefix() + name;
- break;
- case GlobalValue::InternalLinkage:
- GVName = MAI->getGlobalPrefix() + name;
- break;
- }
+ return false;
}
-
-} // end namespace llvm
diff --git a/lib/CodeGen/MachOWriter.h b/lib/CodeGen/MachOWriter.h
index 9273f38..2e7e67d 100644
--- a/lib/CodeGen/MachOWriter.h
+++ b/lib/CodeGen/MachOWriter.h
@@ -15,191 +15,73 @@
#define MACHOWRITER_H
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include <vector>
-#include <map>
+#include "llvm/Target/TargetMachine.h"
namespace llvm {
- class Constant;
class GlobalVariable;
class Mangler;
- class MachineBasicBlock;
- class MachineRelocation;
- class MachOCodeEmitter;
- struct MachODySymTab;
- struct MachOHeader;
- struct MachOSection;
- struct MachOSym;
- class TargetData;
- class TargetMachine;
- class MCAsmInfo;
- class ObjectCodeEmitter;
- class OutputBuffer;
- class raw_ostream;
-
+ class MCCodeEmitter;
+ class MCContext;
+ class MCStreamer;
+
/// MachOWriter - This class implements the common target-independent code for
/// writing Mach-O files. Targets should derive a class from this to
/// parameterize the output format.
///
class MachOWriter : public MachineFunctionPass {
- friend class MachOCodeEmitter;
- public:
static char ID;
- ObjectCodeEmitter *getObjectCodeEmitter() {
- return reinterpret_cast<ObjectCodeEmitter*>(MachOCE);
- }
-
- MachOWriter(raw_ostream &O, TargetMachine &TM);
- virtual ~MachOWriter();
-
- virtual const char *getPassName() const {
- return "Mach-O Writer";
- }
-
protected:
/// Output stream to send the resultant object file to.
///
- raw_ostream &O;
+ formatted_raw_ostream &O;
/// Target machine description.
///
TargetMachine &TM;
- /// Mang - The object used to perform name mangling for this module.
+ /// Target Asm Printer information.
///
- Mangler *Mang;
-
- /// MachOCE - The MachineCodeEmitter object that we are exposing to emit
- /// machine code for functions to the .o file.
- MachOCodeEmitter *MachOCE;
-
- /// is64Bit/isLittleEndian - This information is inferred from the target
- /// machine directly, indicating what header values and flags to set.
- bool is64Bit, isLittleEndian;
-
- // Target Asm Info
const MCAsmInfo *MAI;
-
- /// Header - An instance of MachOHeader that we will update while we build
- /// the file, and then emit during finalization.
- MachOHeader Header;
-
+
+ /// MCCE - The MCCodeEmitter object that we are exposing to emit machine
+ /// code for functions to the .o file.
+ MCCodeEmitter *MCCE;
+
+ /// OutContext - This is the context for the output file that we are
+ /// streaming. This owns all of the global MC-related objects for the
+ /// generated translation unit.
+ MCContext &OutContext;
+
+ /// OutStreamer - This is the MCStreamer object for the file we are
+ /// generating. This contains the transient state for the current
+ /// translation unit that we are generating (such as the current section
+ /// etc).
+ MCStreamer &OutStreamer;
+
+ /// Name-mangler for global names.
+ ///
+ Mangler *Mang;
+
/// doInitialization - Emit the file header and all of the global variables
/// for the module to the Mach-O file.
bool doInitialization(Module &M);
- bool runOnMachineFunction(MachineFunction &MF);
-
/// doFinalization - Now that the module has been completely processed, emit
/// the Mach-O file to 'O'.
bool doFinalization(Module &M);
- private:
-
- /// SectionList - This is the list of sections that we have emitted to the
- /// file. Once the file has been completely built, the segment load command
- /// SectionCommands are constructed from this info.
- std::vector<MachOSection*> SectionList;
-
- /// SectionLookup - This is a mapping from section name to SectionList entry
- std::map<std::string, MachOSection*> SectionLookup;
-
- /// GVSection - This is a mapping from a GlobalValue to a MachOSection,
- /// to aid in emitting relocations.
- std::map<GlobalValue*, MachOSection*> GVSection;
-
- /// GVOffset - This is a mapping from a GlobalValue to an offset from the
- /// start of the section in which the GV resides, to aid in emitting
- /// relocations.
- std::map<GlobalValue*, intptr_t> GVOffset;
-
- /// getSection - Return the section with the specified name, creating a new
- /// section if one does not already exist.
- MachOSection *getSection(const std::string &seg, const std::string &sect,
- unsigned Flags = 0);
-
- /// getTextSection - Return text section with different flags for code/data
- MachOSection *getTextSection(bool isCode = true);
-
- MachOSection *getDataSection() {
- return getSection("__DATA", "__data");
+ bool runOnMachineFunction(MachineFunction &MF);
+
+ public:
+ explicit MachOWriter(formatted_raw_ostream &O, TargetMachine &TM,
+ const MCAsmInfo *T, MCCodeEmitter *MCE);
+
+ virtual ~MachOWriter();
+
+ virtual const char *getPassName() const {
+ return "Mach-O Writer";
}
-
- MachOSection *getBSSSection();
- MachOSection *getConstSection(Constant *C);
- MachOSection *getJumpTableSection();
-
- /// MachOSymTab - This struct contains information about the offsets and
- /// size of symbol table information.
- /// segment.
- struct MachOSymTab {
- uint32_t cmd; // LC_SYMTAB
- uint32_t cmdsize; // sizeof( MachOSymTab )
- uint32_t symoff; // symbol table offset
- uint32_t nsyms; // number of symbol table entries
- uint32_t stroff; // string table offset
- uint32_t strsize; // string table size in bytes
-
- // Constants for the cmd field
- // see <mach-o/loader.h>
- enum { LC_SYMTAB = 0x02 // link-edit stab symbol table info
- };
-
- MachOSymTab() : cmd(LC_SYMTAB), cmdsize(6 * sizeof(uint32_t)), symoff(0),
- nsyms(0), stroff(0), strsize(0) { }
- };
-
- /// SymTab - The "stab" style symbol table information
- MachOSymTab SymTab;
- /// DySymTab - symbol table info for the dynamic link editor
- MachODySymTab DySymTab;
-
- protected:
-
- /// SymbolTable - This is the list of symbols we have emitted to the file.
- /// This actually gets rearranged before emission to the file (to put the
- /// local symbols first in the list).
- std::vector<MachOSym> SymbolTable;
-
- /// SymT - A buffer to hold the symbol table before we write it out at the
- /// appropriate location in the file.
- std::vector<unsigned char> SymT;
-
- /// StrT - A buffer to hold the string table before we write it out at the
- /// appropriate location in the file.
- std::vector<unsigned char> StrT;
-
- /// PendingSyms - This is a list of externally defined symbols that we have
- /// been asked to emit, but have not seen a reference to. When a reference
- /// is seen, the symbol will move from this list to the SymbolTable.
- std::vector<GlobalValue*> PendingGlobals;
-
- /// DynamicSymbolTable - This is just a vector of indices into
- /// SymbolTable to aid in emitting the DYSYMTAB load command.
- std::vector<unsigned> DynamicSymbolTable;
-
- static void InitMem(const Constant *C, uintptr_t Offset,
- const TargetData *TD, MachOSection* mos);
-
- private:
- void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV);
- void EmitGlobal(GlobalVariable *GV);
- void EmitHeaderAndLoadCommands();
- void EmitSections();
- void EmitRelocations();
- void BufferSymbolAndStringTable();
- void CalculateRelocations(MachOSection &MOS);
-
- // GetJTRelocation - Get a relocation a new BB relocation based
- // on target information.
- MachineRelocation GetJTRelocation(unsigned Offset,
- MachineBasicBlock *MBB) const;
-
- /// GetTargetRelocation - Returns the number of relocations.
- unsigned GetTargetRelocation(MachineRelocation &MR, unsigned FromIdx,
- unsigned ToAddr, unsigned ToIndex,
- OutputBuffer &RelocOut, OutputBuffer &SecOut,
- bool Scattered, bool Extern);
};
}
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp
index e2ce642..9215bd5 100644
--- a/lib/CodeGen/MachineBasicBlock.cpp
+++ b/lib/CodeGen/MachineBasicBlock.cpp
@@ -378,7 +378,7 @@ bool MachineBasicBlock::canFallThrough() {
MachineBasicBlock *TBB = 0, *FBB = 0;
SmallVector<MachineOperand, 4> Cond;
const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo();
- if (TII->AnalyzeBranch(*this, TBB, FBB, Cond, true)) {
+ if (TII->AnalyzeBranch(*this, TBB, FBB, Cond)) {
// If we couldn't analyze the branch, examine the last instruction.
// If the block doesn't end in a known control barrier, assume fallthrough
// is possible. The isPredicable check is needed because this code can be
@@ -524,7 +524,26 @@ bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA,
return MadeChange;
}
+/// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping
+/// any DEBUG_VALUE instructions. Return UnknownLoc if there is none.
+DebugLoc
+MachineBasicBlock::findDebugLoc(MachineBasicBlock::iterator &MBBI) {
+ DebugLoc DL;
+ MachineBasicBlock::iterator E = end();
+ if (MBBI != E) {
+ // Skip debug declarations, we don't want a DebugLoc from them.
+ MachineBasicBlock::iterator MBBI2 = MBBI;
+ while (MBBI2 != E &&
+ MBBI2->getOpcode()==TargetInstrInfo::DEBUG_VALUE)
+ MBBI2++;
+ if (MBBI2 != E)
+ DL = MBBI2->getDebugLoc();
+ }
+ return DL;
+}
+
void llvm::WriteAsOperand(raw_ostream &OS, const MachineBasicBlock *MBB,
bool t) {
OS << "BB#" << MBB->getNumber();
}
+
diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index ae9451c..1e3e314 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -26,6 +26,7 @@
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
@@ -426,12 +427,12 @@ unsigned MachineFunction::addLiveIn(unsigned PReg,
return VReg;
}
-/// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object.
-DebugLocTuple MachineFunction::getDebugLocTuple(DebugLoc DL) const {
+/// getDILocation - Get the DILocation for a given DebugLoc object.
+DILocation MachineFunction::getDILocation(DebugLoc DL) const {
unsigned Idx = DL.getIndex();
assert(Idx < DebugLocInfo.DebugLocations.size() &&
"Invalid index into debug locations!");
- return DebugLocInfo.DebugLocations[Idx];
+ return DILocation(DebugLocInfo.DebugLocations[Idx]);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index cf3e3e1..ef2fcee 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -1162,6 +1162,13 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
if (FirstOp) FirstOp = false; else OS << ",";
OS << " ";
+ if (i < getDesc().NumOperands) {
+ const TargetOperandInfo &TOI = getDesc().OpInfo[i];
+ if (TOI.isPredicate())
+ OS << "pred:";
+ if (TOI.isOptionalDef())
+ OS << "opt:";
+ }
MO.print(OS, TM);
}
@@ -1189,17 +1196,17 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
// TODO: print InlinedAtLoc information
- DebugLocTuple DLT = MF->getDebugLocTuple(debugLoc);
- DIScope Scope(DLT.Scope);
+ DILocation DLT = MF->getDILocation(debugLoc);
+ DIScope Scope = DLT.getScope();
OS << " dbg:";
// Omit the directory, since it's usually long and uninteresting.
if (!Scope.isNull())
OS << Scope.getFilename();
else
OS << "<unknown>";
- OS << ':' << DLT.Line;
- if (DLT.Col != 0)
- OS << ':' << DLT.Col;
+ OS << ':' << DLT.getLineNumber();
+ if (DLT.getColumnNumber() != 0)
+ OS << ':' << DLT.getColumnNumber();
}
OS << "\n";
diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile
index 4ab3e3c..8c0204c 100644
--- a/lib/CodeGen/Makefile
+++ b/lib/CodeGen/Makefile
@@ -11,6 +11,7 @@ LEVEL = ../..
LIBRARYNAME = LLVMCodeGen
PARALLEL_DIRS = SelectionDAG AsmPrinter
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/CodeGen/MaxStackAlignment.cpp b/lib/CodeGen/MaxStackAlignment.cpp
deleted file mode 100644
index d327cfa..0000000
--- a/lib/CodeGen/MaxStackAlignment.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//===-- MaxStackAlignment.cpp - Compute the required stack alignment -- ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass looks for vector register usage and aligned local objects to
-// calculate the maximum required alignment for a function. This is used by
-// targets which support it to determine if dynamic stack realignment is
-// necessary.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/Passes.h"
-
-using namespace llvm;
-
-namespace {
- struct MaximalStackAlignmentCalculator : public MachineFunctionPass {
- static char ID;
- MaximalStackAlignmentCalculator() : MachineFunctionPass(&ID) {}
-
- virtual bool runOnMachineFunction(MachineFunction &MF) {
- MachineFrameInfo *FFI = MF.getFrameInfo();
- MachineRegisterInfo &RI = MF.getRegInfo();
-
- // Calculate max stack alignment of all already allocated stack objects.
- FFI->calculateMaxStackAlignment();
- unsigned MaxAlign = FFI->getMaxAlignment();
-
- // Be over-conservative: scan over all vreg defs and find whether vector
- // registers are used. If yes, there is probability that vector registers
- // will be spilled and thus the stack needs to be aligned properly.
- // FIXME: It would be better to only do this if a spill actually
- // happens rather than conseratively aligning the stack regardless.
- for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister;
- RegNum < RI.getLastVirtReg(); ++RegNum)
- MaxAlign = std::max(MaxAlign, RI.getRegClass(RegNum)->getAlignment());
-
- if (FFI->getMaxAlignment() == MaxAlign)
- return false;
-
- FFI->setMaxAlignment(MaxAlign);
- return true;
- }
-
- virtual const char *getPassName() const {
- return "Stack Alignment Requirements Auto-Detector";
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
- };
-
- char MaximalStackAlignmentCalculator::ID = 0;
-}
-
-FunctionPass*
-llvm::createMaxStackAlignmentCalculatorPass() {
- return new MaximalStackAlignmentCalculator();
-}
-
diff --git a/lib/CodeGen/OptimizeExts.cpp b/lib/CodeGen/OptimizeExts.cpp
index 625ff89..096f9d4 100644
--- a/lib/CodeGen/OptimizeExts.cpp
+++ b/lib/CodeGen/OptimizeExts.cpp
@@ -143,11 +143,23 @@ bool OptimizeExts::OptimizeInstr(MachineInstr *MI, MachineBasicBlock *MBB,
// Now replace all uses.
if (!Uses.empty()) {
+ SmallPtrSet<MachineBasicBlock*, 4> PHIBBs;
+ // Look for PHI uses of the extended result, we don't want to extend the
+ // liveness of a PHI input. It breaks all kinds of assumptions down
+ // stream. A PHI use is expected to be the kill of its source values.
+ UI = MRI->use_begin(DstReg);
+ for (MachineRegisterInfo::use_iterator UE = MRI->use_end(); UI != UE;
+ ++UI)
+ if (UI->getOpcode() == TargetInstrInfo::PHI)
+ PHIBBs.insert(UI->getParent());
+
const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);
for (unsigned i = 0, e = Uses.size(); i != e; ++i) {
MachineOperand *UseMO = Uses[i];
MachineInstr *UseMI = UseMO->getParent();
MachineBasicBlock *UseMBB = UseMI->getParent();
+ if (PHIBBs.count(UseMBB))
+ continue;
unsigned NewVR = MRI->createVirtualRegister(RC);
BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),
TII->get(TargetInstrInfo::EXTRACT_SUBREG), NewVR)
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 549527c..8883064 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1088,6 +1088,26 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
if (Result.getNode()) return Result;
}
+ // fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n))
+ if (N1.getOpcode() == ISD::SHL &&
+ N1.getOperand(0).getOpcode() == ISD::SUB)
+ if (ConstantSDNode *C =
+ dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(0)))
+ if (C->getAPIntValue() == 0)
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0,
+ DAG.getNode(ISD::SHL, N->getDebugLoc(), VT,
+ N1.getOperand(0).getOperand(1),
+ N1.getOperand(1)));
+ if (N0.getOpcode() == ISD::SHL &&
+ N0.getOperand(0).getOpcode() == ISD::SUB)
+ if (ConstantSDNode *C =
+ dyn_cast<ConstantSDNode>(N0.getOperand(0).getOperand(0)))
+ if (C->getAPIntValue() == 0)
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1,
+ DAG.getNode(ISD::SHL, N->getDebugLoc(), VT,
+ N0.getOperand(0).getOperand(1),
+ N0.getOperand(1)));
+
return SDValue();
}
@@ -1176,6 +1196,9 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
if (N1C)
return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0,
DAG.getConstant(-N1C->getAPIntValue(), VT));
+ // Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1)
+ if (N0C && N0C->isAllOnesValue())
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0);
// fold (A+B)-A -> B
if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1)
return N0.getOperand(1);
diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 4868c9e..dc7d82d 100644
--- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -35,7 +35,6 @@
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 669d414..9c50936 100644
--- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -24,7 +24,6 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
diff --git a/lib/CodeGen/SelectionDAG/Makefile b/lib/CodeGen/SelectionDAG/Makefile
index 73f0b5d..4706e68 100644
--- a/lib/CodeGen/SelectionDAG/Makefile
+++ b/lib/CodeGen/SelectionDAG/Makefile
@@ -6,8 +6,9 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMSelectionDAG
-PARALLEL_DIRS =
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
index 0c3c974c..ad8630a 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
@@ -22,7 +22,6 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 1ad7919..dea5993 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -46,6 +46,11 @@ static RegisterScheduler
tdrListrDAGScheduler("list-tdrr",
"Top-down register reduction list scheduling",
createTDRRListDAGScheduler);
+static RegisterScheduler
+ sourceListDAGScheduler("source",
+ "Similar to list-burr but schedules in source "
+ "order when possible",
+ createSourceListDAGScheduler);
namespace {
//===----------------------------------------------------------------------===//
@@ -931,6 +936,16 @@ namespace {
bool operator()(const SUnit* left, const SUnit* right) const;
};
+
+ struct src_ls_rr_sort : public std::binary_function<SUnit*, SUnit*, bool> {
+ RegReductionPriorityQueue<src_ls_rr_sort> *SPQ;
+ src_ls_rr_sort(RegReductionPriorityQueue<src_ls_rr_sort> *spq)
+ : SPQ(spq) {}
+ src_ls_rr_sort(const src_ls_rr_sort &RHS)
+ : SPQ(RHS.SPQ) {}
+
+ bool operator()(const SUnit* left, const SUnit* right) const;
+ };
} // end anonymous namespace
/// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
@@ -981,9 +996,9 @@ namespace {
public:
RegReductionPriorityQueue(const TargetInstrInfo *tii,
- const TargetRegisterInfo *tri) :
- Queue(SF(this)), currentQueueId(0),
- TII(tii), TRI(tri), scheduleDAG(NULL) {}
+ const TargetRegisterInfo *tri)
+ : Queue(SF(this)), currentQueueId(0),
+ TII(tii), TRI(tri), scheduleDAG(NULL) {}
void initNodes(std::vector<SUnit> &sunits) {
SUnits = &sunits;
@@ -1089,6 +1104,9 @@ namespace {
typedef RegReductionPriorityQueue<td_ls_rr_sort>
TDRegReductionPriorityQueue;
+
+ typedef RegReductionPriorityQueue<src_ls_rr_sort>
+ SrcRegReductionPriorityQueue;
}
/// closestSucc - Returns the scheduled cycle of the successor which is
@@ -1122,16 +1140,9 @@ static unsigned calcMaxScratches(const SUnit *SU) {
return Scratches;
}
-// Bottom up
-bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
- unsigned LOrder = SPQ->getNodeOrdering(left);
- unsigned ROrder = SPQ->getNodeOrdering(right);
-
- // Prefer an ordering where the lower the non-zero order number, the higher
- // the preference.
- if ((LOrder || ROrder) && LOrder != ROrder)
- return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
-
+template <typename RRSort>
+static bool BURRSort(const SUnit *left, const SUnit *right,
+ const RegReductionPriorityQueue<RRSort> *SPQ) {
unsigned LPriority = SPQ->getNodePriority(left);
unsigned RPriority = SPQ->getNodePriority(right);
if (LPriority != RPriority)
@@ -1176,6 +1187,24 @@ bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
return (left->NodeQueueId > right->NodeQueueId);
}
+// Bottom up
+bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
+ return BURRSort(left, right, SPQ);
+}
+
+// Source order, otherwise bottom up.
+bool src_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const{
+ unsigned LOrder = SPQ->getNodeOrdering(left);
+ unsigned ROrder = SPQ->getNodeOrdering(right);
+
+ // Prefer an ordering where the lower the non-zero order number, the higher
+ // the preference.
+ if ((LOrder || ROrder) && LOrder != ROrder)
+ return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
+
+ return BURRSort(left, right, SPQ);
+}
+
template<class SF>
bool
RegReductionPriorityQueue<SF>::canClobber(const SUnit *SU, const SUnit *Op) {
@@ -1196,7 +1225,6 @@ RegReductionPriorityQueue<SF>::canClobber(const SUnit *SU, const SUnit *Op) {
return false;
}
-
/// hasCopyToRegUse - Return true if SU has a value successor that is a
/// CopyToReg node.
static bool hasCopyToRegUse(const SUnit *SU) {
@@ -1544,3 +1572,17 @@ llvm::createTDRRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
PQ->setScheduleDAG(SD);
return SD;
}
+
+llvm::ScheduleDAGSDNodes *
+llvm::createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
+ const TargetMachine &TM = IS->TM;
+ const TargetInstrInfo *TII = TM.getInstrInfo();
+ const TargetRegisterInfo *TRI = TM.getRegisterInfo();
+
+ SrcRegReductionPriorityQueue *PQ = new SrcRegReductionPriorityQueue(TII, TRI);
+
+ ScheduleDAGRRList *SD =
+ new ScheduleDAGRRList(*IS->MF, true, PQ);
+ PQ->setScheduleDAG(SD);
+ return SD;
+}
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index aaaa2b3..b51c61b 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -20,10 +20,16 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtarget.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+STATISTIC(LoadsClustered, "Number of loads clustered together");
+
ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf)
: ScheduleDAG(mf) {
}
@@ -75,6 +81,122 @@ static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op,
}
}
+static void AddFlags(SDNode *N, SDValue Flag, bool AddFlag,
+ SelectionDAG *DAG) {
+ SmallVector<EVT, 4> VTs;
+ for (unsigned i = 0, e = N->getNumValues(); i != e; ++i)
+ VTs.push_back(N->getValueType(i));
+ if (AddFlag)
+ VTs.push_back(MVT::Flag);
+ SmallVector<SDValue, 4> Ops;
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+ Ops.push_back(N->getOperand(i));
+ if (Flag.getNode())
+ Ops.push_back(Flag);
+ SDVTList VTList = DAG->getVTList(&VTs[0], VTs.size());
+ DAG->MorphNodeTo(N, N->getOpcode(), VTList, &Ops[0], Ops.size());
+}
+
+/// ClusterNeighboringLoads - Force nearby loads together by "flagging" them.
+/// This function finds loads of the same base and different offsets. If the
+/// offsets are not far apart (target specific), it add MVT::Flag inputs and
+/// outputs to ensure they are scheduled together and in order. This
+/// optimization may benefit some targets by improving cache locality.
+void ScheduleDAGSDNodes::ClusterNeighboringLoads() {
+ SmallPtrSet<SDNode*, 16> Visited;
+ SmallVector<int64_t, 4> Offsets;
+ DenseMap<long long, SDNode*> O2SMap; // Map from offset to SDNode.
+ for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
+ E = DAG->allnodes_end(); NI != E; ++NI) {
+ SDNode *Node = &*NI;
+ if (!Node || !Node->isMachineOpcode())
+ continue;
+
+ unsigned Opc = Node->getMachineOpcode();
+ const TargetInstrDesc &TID = TII->get(Opc);
+ if (!TID.mayLoad())
+ continue;
+
+ SDNode *Chain = 0;
+ unsigned NumOps = Node->getNumOperands();
+ if (Node->getOperand(NumOps-1).getValueType() == MVT::Other)
+ Chain = Node->getOperand(NumOps-1).getNode();
+ if (!Chain)
+ continue;
+
+ // Look for other loads of the same chain. Find loads that are loading from
+ // the same base pointer and different offsets.
+ Visited.clear();
+ Offsets.clear();
+ O2SMap.clear();
+ bool Cluster = false;
+ SDNode *Base = Node;
+ int64_t BaseOffset;
+ for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
+ I != E; ++I) {
+ SDNode *User = *I;
+ if (User == Node || !Visited.insert(User))
+ continue;
+ int64_t Offset1, Offset2;
+ if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) ||
+ Offset1 == Offset2)
+ // FIXME: Should be ok if they addresses are identical. But earlier
+ // optimizations really should have eliminated one of the loads.
+ continue;
+ if (O2SMap.insert(std::make_pair(Offset1, Base)).second)
+ Offsets.push_back(Offset1);
+ O2SMap.insert(std::make_pair(Offset2, User));
+ Offsets.push_back(Offset2);
+ if (Offset2 < Offset1) {
+ Base = User;
+ BaseOffset = Offset2;
+ } else {
+ BaseOffset = Offset1;
+ }
+ Cluster = true;
+ }
+
+ if (!Cluster)
+ continue;
+
+ // Sort them in increasing order.
+ std::sort(Offsets.begin(), Offsets.end());
+
+ // Check if the loads are close enough.
+ SmallVector<SDNode*, 4> Loads;
+ unsigned NumLoads = 0;
+ int64_t BaseOff = Offsets[0];
+ SDNode *BaseLoad = O2SMap[BaseOff];
+ Loads.push_back(BaseLoad);
+ for (unsigned i = 1, e = Offsets.size(); i != e; ++i) {
+ int64_t Offset = Offsets[i];
+ SDNode *Load = O2SMap[Offset];
+ if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset,
+ NumLoads))
+ break; // Stop right here. Ignore loads that are further away.
+ Loads.push_back(Load);
+ ++NumLoads;
+ }
+
+ if (NumLoads == 0)
+ continue;
+
+ // Cluster loads by adding MVT::Flag outputs and inputs. This also
+ // ensure they are scheduled in order of increasing addresses.
+ SDNode *Lead = Loads[0];
+ AddFlags(Lead, SDValue(0,0), true, DAG);
+ SDValue InFlag = SDValue(Lead, Lead->getNumValues()-1);
+ for (unsigned i = 1, e = Loads.size(); i != e; ++i) {
+ bool OutFlag = i < e-1;
+ SDNode *Load = Loads[i];
+ AddFlags(Load, InFlag, OutFlag, DAG);
+ if (OutFlag)
+ InFlag = SDValue(Load, Load->getNumValues()-1);
+ ++LoadsClustered;
+ }
+ }
+}
+
void ScheduleDAGSDNodes::BuildSchedUnits() {
// During scheduling, the NodeId field of SDNode is used to map SDNodes
// to their associated SUnits by holding SUnits table indices. A value
@@ -232,6 +354,8 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
/// excludes nodes that aren't interesting to scheduling, and represents
/// flagged together nodes with a single SUnit.
void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) {
+ // Cluster loads from "near" addresses into combined SUnits.
+ ClusterNeighboringLoads();
// Populate the SUnits array.
BuildSchedUnits();
// Compute all the scheduling dependencies between nodes.
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
index ebb31ac..6b829b6 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
@@ -108,6 +108,10 @@ namespace llvm {
virtual void getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const;
private:
+ /// ClusterNeighboringLoads - Cluster loads from "near" addresses into
+ /// combined SUnits.
+ void ClusterNeighboringLoads();
+
/// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph.
void BuildSchedUnits();
void AddSchedEdges();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index cb1a0d6..f1b6f1e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -593,7 +593,7 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
NodeAllocator.Deallocate(AllNodes.remove(N));
// Remove the ordering of this node.
- if (Ordering) Ordering->remove(N);
+ Ordering->remove(N);
}
/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that
@@ -790,8 +790,7 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli)
getVTList(MVT::Other)),
Root(getEntryNode()), Ordering(0) {
AllNodes.push_back(&EntryNode);
- if (DisableScheduling)
- Ordering = new SDNodeOrdering();
+ Ordering = new SDNodeOrdering();
}
void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi,
@@ -830,8 +829,7 @@ void SelectionDAG::clear() {
EntryNode.UseList = 0;
AllNodes.push_back(&EntryNode);
Root = getEntryNode();
- if (DisableScheduling)
- Ordering = new SDNodeOrdering();
+ Ordering = new SDNodeOrdering();
}
SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) {
@@ -5172,6 +5170,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
// count of outstanding operands.
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
SDNode *N = I++;
+ checkForCycles(N);
unsigned Degree = N->getNumOperands();
if (Degree == 0) {
// A node with no uses, add it to the result array immediately.
@@ -5179,6 +5178,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
allnodes_iterator Q = N;
if (Q != SortedPos)
SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q));
+ assert(SortedPos != AllNodes.end() && "Overran node list");
++SortedPos;
} else {
// Temporarily use the Node Id as scratch space for the degree count.
@@ -5190,22 +5190,34 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
// such that by the time the end is reached all nodes will be sorted.
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) {
SDNode *N = I;
+ checkForCycles(N);
+ // N is in sorted position, so all its uses have one less operand
+ // that needs to be sorted.
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI) {
SDNode *P = *UI;
unsigned Degree = P->getNodeId();
+ assert(Degree != 0 && "Invalid node degree");
--Degree;
if (Degree == 0) {
// All of P's operands are sorted, so P may sorted now.
P->setNodeId(DAGSize++);
if (P != SortedPos)
SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P));
+ assert(SortedPos != AllNodes.end() && "Overran node list");
++SortedPos;
} else {
// Update P's outstanding operand count.
P->setNodeId(Degree);
}
}
+ if (I == SortedPos) {
+ allnodes_iterator J = I;
+ SDNode *S = ++J;
+ dbgs() << "Offending node:\n";
+ S->dumprFull();
+ assert(0 && "Overran sorted position");
+ }
}
assert(SortedPos == AllNodes.end() &&
@@ -5227,14 +5239,13 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
/// AssignOrdering - Assign an order to the SDNode.
void SelectionDAG::AssignOrdering(SDNode *SD, unsigned Order) {
assert(SD && "Trying to assign an order to a null node!");
- if (Ordering)
- Ordering->add(SD, Order);
+ Ordering->add(SD, Order);
}
/// GetOrdering - Get the order for the SDNode.
unsigned SelectionDAG::GetOrdering(const SDNode *SD) const {
assert(SD && "Trying to get the order of a null node!");
- return Ordering ? Ordering->getOrder(SD) : 0;
+ return Ordering->getOrder(SD);
}
@@ -5893,6 +5904,45 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
print_details(OS, G);
}
+static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N,
+ const SelectionDAG *G, unsigned depth,
+ unsigned indent)
+{
+ if (depth == 0)
+ return;
+
+ OS.indent(indent);
+
+ N->print(OS, G);
+
+ if (depth < 1)
+ return;
+
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
+ OS << '\n';
+ printrWithDepthHelper(OS, N->getOperand(i).getNode(), G, depth-1, indent+2);
+ }
+}
+
+void SDNode::printrWithDepth(raw_ostream &OS, const SelectionDAG *G,
+ unsigned depth) const {
+ printrWithDepthHelper(OS, this, G, depth, 0);
+}
+
+void SDNode::printrFull(raw_ostream &OS, const SelectionDAG *G) const {
+ // Don't print impossibly deep things.
+ printrWithDepth(OS, G, 100);
+}
+
+void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const {
+ printrWithDepth(dbgs(), G, depth);
+}
+
+void SDNode::dumprFull(const SelectionDAG *G) const {
+ // Don't print impossibly deep things.
+ dumprWithDepth(G, 100);
+}
+
static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) {
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
if (N->getOperand(i).getNode()->hasOneUse())
@@ -6228,3 +6278,35 @@ bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) {
return false;
return true;
}
+
+static void checkForCyclesHelper(const SDNode *N,
+ std::set<const SDNode *> &visited) {
+ if (visited.find(N) != visited.end()) {
+ dbgs() << "Offending node:\n";
+ N->dumprFull();
+ assert(0 && "Detected cycle in SelectionDAG");
+ }
+
+ std::set<const SDNode*>::iterator i;
+ bool inserted;
+
+ tie(i, inserted) = visited.insert(N);
+ assert(inserted && "Missed cycle");
+
+ for(unsigned i = 0; i < N->getNumOperands(); ++i) {
+ checkForCyclesHelper(N->getOperand(i).getNode(), visited);
+ }
+ visited.erase(i);
+}
+
+void llvm::checkForCycles(const llvm::SDNode *N) {
+#ifdef XDEBUG
+ assert(N && "Checking nonexistant SDNode");
+ std::set<const SDNode *> visited;
+ checkForCyclesHelper(N, visited);
+#endif
+}
+
+void llvm::checkForCycles(const llvm::SelectionDAG *DAG) {
+ checkForCycles(DAG->getRoot().getNode());
+}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 5e3a3b5..23c7059 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -176,7 +176,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
assert(NumParts > 0 && "No parts to assemble!");
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDValue Val = Parts[0];
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
if (NumParts > 1) {
// Assemble the value from multiple parts.
@@ -209,11 +209,9 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
Val = DAG.getNode(ISD::BUILD_PAIR, dl, RoundVT, Lo, Hi);
- if (DisableScheduling) {
- DAG.AssignOrdering(Lo.getNode(), Order);
- DAG.AssignOrdering(Hi.getNode(), Order);
- DAG.AssignOrdering(Val.getNode(), Order);
- }
+ DAG.AssignOrdering(Lo.getNode(), Order);
+ DAG.AssignOrdering(Hi.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
if (RoundParts < NumParts) {
// Assemble the trailing non-power-of-2 part.
@@ -228,15 +226,15 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
std::swap(Lo, Hi);
EVT TotalVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits);
Hi = DAG.getNode(ISD::ANY_EXTEND, dl, TotalVT, Hi);
- if (DisableScheduling) DAG.AssignOrdering(Hi.getNode(), Order);
+ DAG.AssignOrdering(Hi.getNode(), Order);
Hi = DAG.getNode(ISD::SHL, dl, TotalVT, Hi,
DAG.getConstant(Lo.getValueType().getSizeInBits(),
TLI.getPointerTy()));
- if (DisableScheduling) DAG.AssignOrdering(Hi.getNode(), Order);
+ DAG.AssignOrdering(Hi.getNode(), Order);
Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, TotalVT, Lo);
- if (DisableScheduling) DAG.AssignOrdering(Lo.getNode(), Order);
+ DAG.AssignOrdering(Lo.getNode(), Order);
Val = DAG.getNode(ISD::OR, dl, TotalVT, Lo, Hi);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
}
} else if (ValueVT.isVector()) {
// Handle a multi-element vector.
@@ -277,7 +275,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
Val = DAG.getNode(IntermediateVT.isVector() ?
ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR, dl,
ValueVT, &Ops[0], NumIntermediates);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
} else if (PartVT.isFloatingPoint()) {
// FP split into multiple FP parts (for ppcf128)
assert(ValueVT == EVT(MVT::ppcf128) && PartVT == EVT(MVT::f64) &&
@@ -289,11 +287,9 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
std::swap(Lo, Hi);
Val = DAG.getNode(ISD::BUILD_PAIR, dl, ValueVT, Lo, Hi);
- if (DisableScheduling) {
- DAG.AssignOrdering(Hi.getNode(), Order);
- DAG.AssignOrdering(Lo.getNode(), Order);
- DAG.AssignOrdering(Val.getNode(), Order);
- }
+ DAG.AssignOrdering(Hi.getNode(), Order);
+ DAG.AssignOrdering(Lo.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
} else {
// FP split into integer parts (soft fp)
assert(ValueVT.isFloatingPoint() && PartVT.isInteger() &&
@@ -312,8 +308,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
if (PartVT.isVector()) {
assert(ValueVT.isVector() && "Unknown vector conversion!");
SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return Res;
}
@@ -322,8 +317,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
ValueVT.getVectorNumElements() == 1 &&
"Only trivial scalar-to-vector conversions should get here!");
SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, ValueVT, Val);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return Res;
}
@@ -336,13 +330,13 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
if (AssertOp != ISD::DELETED_NODE)
Val = DAG.getNode(AssertOp, dl, PartVT, Val,
DAG.getValueType(ValueVT));
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
return Val;
} else {
Val = DAG.getNode(ISD::ANY_EXTEND, dl, ValueVT, Val);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
return Val;
}
}
@@ -352,18 +346,18 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
// FP_ROUND's are always exact here.
Val = DAG.getNode(ISD::FP_ROUND, dl, ValueVT, Val,
DAG.getIntPtrConstant(1));
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
return Val;
}
Val = DAG.getNode(ISD::FP_EXTEND, dl, ValueVT, Val);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
return Val;
}
if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) {
Val = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val);
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
return Val;
}
@@ -420,7 +414,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
}
}
- if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
// The value may have changed - recompute ValueVT.
ValueVT = Val.getValueType();
@@ -455,10 +449,8 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits);
Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val);
- if (DisableScheduling) {
- DAG.AssignOrdering(OddVal.getNode(), Order);
- DAG.AssignOrdering(Val.getNode(), Order);
- }
+ DAG.AssignOrdering(OddVal.getNode(), Order);
+ DAG.AssignOrdering(Val.getNode(), Order);
}
// The number of parts is a power of 2. Repeatedly bisect the value using
@@ -468,8 +460,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
ValueVT.getSizeInBits()),
Val);
- if (DisableScheduling)
- DAG.AssignOrdering(Parts[0].getNode(), Order);
+ DAG.AssignOrdering(Parts[0].getNode(), Order);
for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) {
for (unsigned i = 0; i < NumParts; i += StepSize) {
@@ -485,20 +476,16 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
ThisVT, Part0,
DAG.getConstant(0, PtrVT));
- if (DisableScheduling) {
- DAG.AssignOrdering(Part0.getNode(), Order);
- DAG.AssignOrdering(Part1.getNode(), Order);
- }
+ DAG.AssignOrdering(Part0.getNode(), Order);
+ DAG.AssignOrdering(Part1.getNode(), Order);
if (ThisBits == PartBits && ThisVT != PartVT) {
Part0 = DAG.getNode(ISD::BIT_CONVERT, dl,
PartVT, Part0);
Part1 = DAG.getNode(ISD::BIT_CONVERT, dl,
PartVT, Part1);
- if (DisableScheduling) {
- DAG.AssignOrdering(Part0.getNode(), Order);
- DAG.AssignOrdering(Part1.getNode(), Order);
- }
+ DAG.AssignOrdering(Part0.getNode(), Order);
+ DAG.AssignOrdering(Part1.getNode(), Order);
}
}
}
@@ -524,9 +511,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
}
}
- if (DisableScheduling)
- DAG.AssignOrdering(Val.getNode(), Order);
-
+ DAG.AssignOrdering(Val.getNode(), Order);
Parts[0] = Val;
return;
}
@@ -555,8 +540,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order,
IntermediateVT, Val,
DAG.getConstant(i, PtrVT));
- if (DisableScheduling)
- DAG.AssignOrdering(Ops[i].getNode(), Order);
+ DAG.AssignOrdering(Ops[i].getNode(), Order);
}
// Split the intermediate operands into legal parts.
@@ -717,8 +701,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
SDValue Res = DAG.getMergeValues(&Constants[0], Constants.size(),
getCurDebugLoc());
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return Res;
}
@@ -744,8 +727,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
SDValue Res = DAG.getMergeValues(&Constants[0], NumElts,
getCurDebugLoc());
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return Res;
}
@@ -776,9 +758,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
// Create a BUILD_VECTOR node.
SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(),
VT, &Ops[0], Ops.size());
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return NodeMap[V] = Res;
}
@@ -800,18 +780,19 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
SDNodeOrder, Chain, NULL);
}
-/// Get the EVTs and ArgFlags collections that represent the return type
-/// of the given function. This does not require a DAG or a return value, and
-/// is suitable for use before any DAGs for the function are constructed.
+/// Get the EVTs and ArgFlags collections that represent the legalized return
+/// type of the given function. This does not require a DAG or a return value,
+/// and is suitable for use before any DAGs for the function are constructed.
static void getReturnInfo(const Type* ReturnType,
Attributes attr, SmallVectorImpl<EVT> &OutVTs,
SmallVectorImpl<ISD::ArgFlagsTy> &OutFlags,
TargetLowering &TLI,
SmallVectorImpl<uint64_t> *Offsets = 0) {
SmallVector<EVT, 4> ValueVTs;
- ComputeValueVTs(TLI, ReturnType, ValueVTs, Offsets);
+ ComputeValueVTs(TLI, ReturnType, ValueVTs);
unsigned NumValues = ValueVTs.size();
- if ( NumValues == 0 ) return;
+ if (NumValues == 0) return;
+ unsigned Offset = 0;
for (unsigned j = 0, f = NumValues; j != f; ++j) {
EVT VT = ValueVTs[j];
@@ -834,6 +815,9 @@ static void getReturnInfo(const Type* ReturnType,
unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT);
EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT);
+ unsigned PartSize = TLI.getTargetData()->getTypeAllocSize(
+ PartVT.getTypeForEVT(ReturnType->getContext()));
+
// 'inreg' on function refers to return value
ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
if (attr & Attribute::InReg)
@@ -848,6 +832,11 @@ static void getReturnInfo(const Type* ReturnType,
for (unsigned i = 0; i < NumParts; ++i) {
OutVTs.push_back(PartVT);
OutFlags.push_back(Flags);
+ if (Offsets)
+ {
+ Offsets->push_back(Offset);
+ Offset += PartSize;
+ }
}
}
}
@@ -886,17 +875,14 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) {
SDValue(RetOp.getNode(), RetOp.getResNo() + i),
Add, NULL, Offsets[i], false, 0);
- if (DisableScheduling) {
- DAG.AssignOrdering(Add.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Add.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder);
}
Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(),
MVT::Other, &Chains[0], NumValues);
- if (DisableScheduling)
- DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
} else {
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
SmallVector<EVT, 4> ValueVTs;
@@ -962,9 +948,7 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) {
// Update the DAG with the new chain value resulting from return lowering.
DAG.setRoot(Chain);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
}
/// CopyToExportRegsIfNeeded - If the given value has virtual registers
@@ -1230,9 +1214,7 @@ void SelectionDAGBuilder::visitBr(BranchInst &I) {
MVT::Other, getControlRoot(),
DAG.getBasicBlock(Succ0MBB));
DAG.setRoot(V);
-
- if (DisableScheduling)
- DAG.AssignOrdering(V.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(V.getNode(), SDNodeOrder);
}
return;
@@ -1339,8 +1321,7 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) {
}
}
- if (DisableScheduling)
- DAG.AssignOrdering(Cond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Cond.getNode(), SDNodeOrder);
// Update successor info
CurMBB->addSuccessor(CB.TrueBB);
@@ -1359,17 +1340,13 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) {
std::swap(CB.TrueBB, CB.FalseBB);
SDValue True = DAG.getConstant(1, Cond.getValueType());
Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Cond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Cond.getNode(), SDNodeOrder);
}
SDValue BrCond = DAG.getNode(ISD::BRCOND, dl,
MVT::Other, getControlRoot(), Cond,
DAG.getBasicBlock(CB.TrueBB));
-
- if (DisableScheduling)
- DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
// If the branch was constant folded, fix up the CFG.
if (BrCond.getOpcode() == ISD::BR) {
@@ -1383,8 +1360,7 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) {
BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond,
DAG.getBasicBlock(CB.FalseBB));
- if (DisableScheduling)
- DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
}
}
@@ -1404,11 +1380,9 @@ void SelectionDAGBuilder::visitJumpTable(JumpTable &JT) {
Table, Index);
DAG.setRoot(BrJumpTable);
- if (DisableScheduling) {
- DAG.AssignOrdering(Index.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Table.getNode(), SDNodeOrder);
- DAG.AssignOrdering(BrJumpTable.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Index.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Table.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrJumpTable.getNode(), SDNodeOrder);
}
/// visitJumpTableHeader - This function emits necessary code to produce index
@@ -1443,12 +1417,10 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT,
DAG.getConstant(JTH.Last-JTH.First,VT),
ISD::SETUGT);
- if (DisableScheduling) {
- DAG.AssignOrdering(Sub.getNode(), SDNodeOrder);
- DAG.AssignOrdering(SwitchOp.getNode(), SDNodeOrder);
- DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder);
- DAG.AssignOrdering(CMP.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Sub.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(SwitchOp.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(CMP.getNode(), SDNodeOrder);
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
@@ -1462,15 +1434,12 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT,
MVT::Other, CopyTo, CMP,
DAG.getBasicBlock(JT.Default));
- if (DisableScheduling)
- DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
if (JT.MBB != NextBlock) {
BrCond = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrCond,
DAG.getBasicBlock(JT.MBB));
-
- if (DisableScheduling)
- DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder);
}
DAG.setRoot(BrCond);
@@ -1498,12 +1467,10 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) {
SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(),
B.Reg, ShiftOp);
- if (DisableScheduling) {
- DAG.AssignOrdering(Sub.getNode(), SDNodeOrder);
- DAG.AssignOrdering(RangeCmp.getNode(), SDNodeOrder);
- DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder);
- DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Sub.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(RangeCmp.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder);
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
@@ -1521,15 +1488,12 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) {
MVT::Other, CopyTo, RangeCmp,
DAG.getBasicBlock(B.Default));
- if (DisableScheduling)
- DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder);
if (MBB != NextBlock) {
BrRange = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, CopyTo,
DAG.getBasicBlock(MBB));
-
- if (DisableScheduling)
- DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder);
}
DAG.setRoot(BrRange);
@@ -1556,12 +1520,10 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB,
AndOp, DAG.getConstant(0, TLI.getPointerTy()),
ISD::SETNE);
- if (DisableScheduling) {
- DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder);
- DAG.AssignOrdering(SwitchVal.getNode(), SDNodeOrder);
- DAG.AssignOrdering(AndOp.getNode(), SDNodeOrder);
- DAG.AssignOrdering(AndCmp.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(SwitchVal.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AndOp.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AndCmp.getNode(), SDNodeOrder);
CurMBB->addSuccessor(B.TargetBB);
CurMBB->addSuccessor(NextMBB);
@@ -1570,8 +1532,7 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB,
MVT::Other, getControlRoot(),
AndCmp, DAG.getBasicBlock(B.TargetBB));
- if (DisableScheduling)
- DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder);
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
@@ -1583,9 +1544,7 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB,
if (NextMBB != NextBlock) {
BrAnd = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrAnd,
DAG.getBasicBlock(NextMBB));
-
- if (DisableScheduling)
- DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder);
}
DAG.setRoot(BrAnd);
@@ -1615,9 +1574,7 @@ void SelectionDAGBuilder::visitInvoke(InvokeInst &I) {
MVT::Other, getControlRoot(),
DAG.getBasicBlock(Return));
DAG.setRoot(Branch);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Branch.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Branch.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitUnwind(UnwindInst &I) {
@@ -2134,9 +2091,7 @@ void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) {
MVT::Other, getControlRoot(),
DAG.getBasicBlock(Default));
DAG.setRoot(Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
return;
@@ -2194,9 +2149,7 @@ void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) {
MVT::Other, getControlRoot(),
getValue(I.getAddress()));
DAG.setRoot(Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFSub(User &I) {
@@ -2214,10 +2167,7 @@ void SelectionDAGBuilder::visitFSub(User &I) {
SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(),
Op2.getValueType(), Op2);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
}
@@ -2229,10 +2179,7 @@ void SelectionDAGBuilder::visitFSub(User &I) {
SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(),
Op2.getValueType(), Op2);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
@@ -2245,9 +2192,7 @@ void SelectionDAGBuilder::visitBinary(User &I, unsigned OpCode) {
SDValue Res = DAG.getNode(OpCode, getCurDebugLoc(),
Op1.getValueType(), Op1, Op2);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) {
@@ -2283,12 +2228,9 @@ void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) {
SDValue Res = DAG.getNode(Opcode, getCurDebugLoc(),
Op1.getValueType(), Op1, Op2);
setValue(&I, Res);
-
- if (DisableScheduling) {
- DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Op2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Op2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitICmp(User &I) {
@@ -2304,9 +2246,7 @@ void SelectionDAGBuilder::visitICmp(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFCmp(User &I) {
@@ -2321,9 +2261,7 @@ void SelectionDAGBuilder::visitFCmp(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitSelect(User &I) {
@@ -2345,17 +2283,14 @@ void SelectionDAGBuilder::visitSelect(User &I) {
SDValue(FalseVal.getNode(),
FalseVal.getResNo() + i));
- if (DisableScheduling)
- DAG.AssignOrdering(Values[i].getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Values[i].getNode(), SDNodeOrder);
}
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(),
DAG.getVTList(&ValueVTs[0], NumValues),
&Values[0], NumValues);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitTrunc(User &I) {
@@ -2364,9 +2299,7 @@ void SelectionDAGBuilder::visitTrunc(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitZExt(User &I) {
@@ -2376,9 +2309,7 @@ void SelectionDAGBuilder::visitZExt(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitSExt(User &I) {
@@ -2388,9 +2319,7 @@ void SelectionDAGBuilder::visitSExt(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFPTrunc(User &I) {
@@ -2400,9 +2329,7 @@ void SelectionDAGBuilder::visitFPTrunc(User &I) {
SDValue Res = DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(),
DestVT, N, DAG.getIntPtrConstant(0));
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFPExt(User &I){
@@ -2411,9 +2338,7 @@ void SelectionDAGBuilder::visitFPExt(User &I){
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFPToUI(User &I) {
@@ -2422,9 +2347,7 @@ void SelectionDAGBuilder::visitFPToUI(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitFPToSI(User &I) {
@@ -2433,9 +2356,7 @@ void SelectionDAGBuilder::visitFPToSI(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitUIToFP(User &I) {
@@ -2444,9 +2365,7 @@ void SelectionDAGBuilder::visitUIToFP(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitSIToFP(User &I){
@@ -2455,9 +2374,7 @@ void SelectionDAGBuilder::visitSIToFP(User &I){
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitPtrToInt(User &I) {
@@ -2468,9 +2385,7 @@ void SelectionDAGBuilder::visitPtrToInt(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitIntToPtr(User &I) {
@@ -2481,9 +2396,7 @@ void SelectionDAGBuilder::visitIntToPtr(User &I) {
EVT DestVT = TLI.getValueType(I.getType());
SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitBitCast(User &I) {
@@ -2496,9 +2409,7 @@ void SelectionDAGBuilder::visitBitCast(User &I) {
SDValue Res = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(),
DestVT, N); // convert types.
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
} else {
setValue(&I, N); // noop cast.
}
@@ -2515,10 +2426,8 @@ void SelectionDAGBuilder::visitInsertElement(User &I) {
InVec, InVal, InIdx);
setValue(&I, Res);
- if (DisableScheduling) {
- DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitExtractElement(User &I) {
@@ -2530,10 +2439,8 @@ void SelectionDAGBuilder::visitExtractElement(User &I) {
TLI.getValueType(I.getType()), InVec, InIdx);
setValue(&I, Res);
- if (DisableScheduling) {
- DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
@@ -2573,10 +2480,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2,
&Mask[0]);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
@@ -2590,10 +2494,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(),
VT, Src1, Src2);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
@@ -2628,13 +2529,9 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2,
&MappedOps[0]);
setValue(&I, Res);
-
- if (DisableScheduling) {
- DAG.AssignOrdering(Src1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Src2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
-
+ DAG.AssignOrdering(Src1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Src2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
@@ -2688,10 +2585,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
if (RangeUse[0] == 0 && RangeUse[1] == 0) {
SDValue Res = DAG.getUNDEF(VT);
setValue(&I, Res); // Vectors are not used.
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
else if (RangeUse[0] < 2 && RangeUse[1] < 2) {
@@ -2704,8 +2598,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, getCurDebugLoc(), VT,
Src, DAG.getIntPtrConstant(StartIdx[Input]));
- if (DisableScheduling)
- DAG.AssignOrdering(Src.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Src.getNode(), SDNodeOrder);
}
// Calculate new mask.
@@ -2723,10 +2616,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2,
&MappedOps[0]);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return;
}
}
@@ -2753,18 +2643,14 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) {
DAG.getConstant(Idx - SrcNumElts, PtrVT));
Ops.push_back(Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
}
SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(),
VT, &Ops[0], Ops.size());
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) {
@@ -2807,9 +2693,7 @@ void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) {
DAG.getVTList(&AggValueVTs[0], NumAggValues),
&Values[0], NumAggValues);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) {
@@ -2839,9 +2723,7 @@ void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) {
DAG.getVTList(&ValValueVTs[0], NumValValues),
&Values[0], NumValValues);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitGetElementPtr(User &I) {
@@ -2858,9 +2740,7 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) {
uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field);
N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N,
DAG.getIntPtrConstant(Offset));
-
- if (DisableScheduling)
- DAG.AssignOrdering(N.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(N.getNode(), SDNodeOrder);
}
Ty = StTy->getElementType(Field);
@@ -2885,11 +2765,8 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) {
N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N,
OffsVal);
- if (DisableScheduling) {
- DAG.AssignOrdering(OffsVal.getNode(), SDNodeOrder);
- DAG.AssignOrdering(N.getNode(), SDNodeOrder);
- }
-
+ DAG.AssignOrdering(OffsVal.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(N.getNode(), SDNodeOrder);
continue;
}
@@ -2916,15 +2793,12 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) {
N.getValueType(), IdxN, Scale);
}
- if (DisableScheduling)
- DAG.AssignOrdering(IdxN.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IdxN.getNode(), SDNodeOrder);
}
N = DAG.getNode(ISD::ADD, getCurDebugLoc(),
N.getValueType(), N, IdxN);
-
- if (DisableScheduling)
- DAG.AssignOrdering(N.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(N.getNode(), SDNodeOrder);
}
}
@@ -2949,14 +2823,11 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) {
AllocSize,
DAG.getConstant(TySize, AllocSize.getValueType()));
- if (DisableScheduling)
- DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
EVT IntPtr = TLI.getPointerTy();
AllocSize = DAG.getZExtOrTrunc(AllocSize, getCurDebugLoc(), IntPtr);
-
- if (DisableScheduling)
- DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
// Handle alignment. If the requested alignment is less than or equal to
// the stack alignment, ignore it. If the size is greater than or equal to
@@ -2971,15 +2842,13 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) {
AllocSize = DAG.getNode(ISD::ADD, getCurDebugLoc(),
AllocSize.getValueType(), AllocSize,
DAG.getIntPtrConstant(StackAlign-1));
- if (DisableScheduling)
- DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
// Mask out the low bits for alignment purposes.
AllocSize = DAG.getNode(ISD::AND, getCurDebugLoc(),
AllocSize.getValueType(), AllocSize,
DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1)));
- if (DisableScheduling)
- DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder);
SDValue Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) };
SDVTList VTs = DAG.getVTList(AllocSize.getValueType(), MVT::Other);
@@ -2987,9 +2856,7 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) {
VTs, Ops, 3);
setValue(&I, DSA);
DAG.setRoot(DSA.getValue(1));
-
- if (DisableScheduling)
- DAG.AssignOrdering(DSA.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(DSA.getNode(), SDNodeOrder);
// Inform the Frame Information that we have just allocated a variable-sized
// object.
@@ -3038,10 +2905,8 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) {
Values[i] = L;
Chains[i] = L.getValue(1);
- if (DisableScheduling) {
- DAG.AssignOrdering(A.getNode(), SDNodeOrder);
- DAG.AssignOrdering(L.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(A.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(L.getNode(), SDNodeOrder);
}
if (!ConstantMemory) {
@@ -3052,17 +2917,14 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) {
else
PendingLoads.push_back(Chain);
- if (DisableScheduling)
- DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
}
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(),
DAG.getVTList(&ValueVTs[0], NumValues),
&Values[0], NumValues);
setValue(&I, Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
void SelectionDAGBuilder::visitStore(StoreInst &I) {
@@ -3095,18 +2957,14 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) {
SDValue(Src.getNode(), Src.getResNo() + i),
Add, PtrV, Offsets[i], isVolatile, Alignment);
- if (DisableScheduling) {
- DAG.AssignOrdering(Add.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Add.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder);
}
SDValue Res = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(),
MVT::Other, &Chains[0], NumValues);
DAG.setRoot(Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
@@ -3177,8 +3035,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I,
VTs, &Ops[0], Ops.size());
}
- if (DisableScheduling)
- DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
if (HasChain) {
SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1);
@@ -3192,9 +3049,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I,
if (const VectorType *PTy = dyn_cast<VectorType>(I.getType())) {
EVT VT = TLI.getValueType(PTy);
Result = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), VT, Result);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
}
setValue(&I, Result);
@@ -3215,12 +3070,9 @@ GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl, unsigned Order) {
DAG.getConstant(0x3f800000, MVT::i32));
SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t2);
- if (DisableScheduling) {
- DAG.AssignOrdering(t1.getNode(), Order);
- DAG.AssignOrdering(t2.getNode(), Order);
- DAG.AssignOrdering(Res.getNode(), Order);
- }
-
+ DAG.AssignOrdering(t1.getNode(), Order);
+ DAG.AssignOrdering(t2.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return Res;
}
@@ -3240,13 +3092,10 @@ GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI,
DAG.getConstant(127, MVT::i32));
SDValue Res = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), Order);
- DAG.AssignOrdering(t1.getNode(), Order);
- DAG.AssignOrdering(t2.getNode(), Order);
- DAG.AssignOrdering(Res.getNode(), Order);
- }
-
+ DAG.AssignOrdering(t0.getNode(), Order);
+ DAG.AssignOrdering(t1.getNode(), Order);
+ DAG.AssignOrdering(t2.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return Res;
}
@@ -3271,10 +3120,7 @@ SelectionDAGBuilder::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) {
I.getOperand(1));
setValue(&I, L);
DAG.setRoot(L.getValue(1));
-
- if (DisableScheduling)
- DAG.AssignOrdering(L.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(L.getNode(), SDNodeOrder);
return 0;
}
@@ -3288,10 +3134,7 @@ SelectionDAGBuilder::implVisitAluOverflow(CallInst &I, ISD::NodeType Op) {
SDValue Result = DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2);
setValue(&I, Result);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
-
+ DAG.AssignOrdering(Result.getNode(), SDNodeOrder);
return 0;
}
@@ -3319,19 +3162,15 @@ SelectionDAGBuilder::visitExp(CallInst &I) {
SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX);
SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(X.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(X.getNode(), SDNodeOrder);
// IntegerPartOfX <<= 23;
IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX,
DAG.getConstant(23, TLI.getPointerTy()));
-
- if (DisableScheduling)
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
if (LimitFloatPrecision <= 6) {
// For floating-point precision of 6:
@@ -3356,15 +3195,13 @@ SelectionDAGBuilder::visitExp(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t6);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -3392,17 +3229,15 @@ SelectionDAGBuilder::visitExp(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t8);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -3443,31 +3278,28 @@ SelectionDAGBuilder::visitExp(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t14);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
result = DAG.getNode(ISD::FEXP, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -3485,16 +3317,14 @@ SelectionDAGBuilder::visitLog(CallInst &I) {
SDValue Op = getValue(I.getOperand(1));
SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op);
- if (DisableScheduling)
- DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
// Scale the exponent by log(2) [0.69314718f].
SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder);
SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp,
getF32Constant(DAG, 0x3f317218));
- if (DisableScheduling)
- DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
// Get the significand and build it into a floating-point number with
// exponent of 1.
@@ -3519,13 +3349,11 @@ SelectionDAGBuilder::visitLog(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, LogOfMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -3553,17 +3381,15 @@ SelectionDAGBuilder::visitLog(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, LogOfMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -3599,30 +3425,26 @@ SelectionDAGBuilder::visitLog(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, LogOfMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
- DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
result = DAG.getNode(ISD::FLOG, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
-
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -3640,14 +3462,12 @@ SelectionDAGBuilder::visitLog2(CallInst &I) {
SDValue Op = getValue(I.getOperand(1));
SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op);
- if (DisableScheduling)
- DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
// Get the exponent.
SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder);
- if (DisableScheduling)
- DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
// Get the significand and build it into a floating-point number with
// exponent of 1.
@@ -3672,13 +3492,11 @@ SelectionDAGBuilder::visitLog2(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log2ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -3706,17 +3524,15 @@ SelectionDAGBuilder::visitLog2(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log2ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -3753,30 +3569,26 @@ SelectionDAGBuilder::visitLog2(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log2ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
result = DAG.getNode(ISD::FLOG2, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
-
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -3794,16 +3606,14 @@ SelectionDAGBuilder::visitLog10(CallInst &I) {
SDValue Op = getValue(I.getOperand(1));
SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op);
- if (DisableScheduling)
- DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Op1.getNode(), SDNodeOrder);
// Scale the exponent by log10(2) [0.30102999f].
SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder);
SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp,
getF32Constant(DAG, 0x3e9a209a));
- if (DisableScheduling)
- DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder);
// Get the significand and build it into a floating-point number with
// exponent of 1.
@@ -3828,13 +3638,11 @@ SelectionDAGBuilder::visitLog10(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log10ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -3858,15 +3666,13 @@ SelectionDAGBuilder::visitLog10(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log10ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -3898,28 +3704,24 @@ SelectionDAGBuilder::visitLog10(CallInst &I) {
result = DAG.getNode(ISD::FADD, dl,
MVT::f32, LogOfExponent, Log10ofMantissa);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
result = DAG.getNode(ISD::FLOG10, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
-
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -3938,8 +3740,7 @@ SelectionDAGBuilder::visitExp2(CallInst &I) {
SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Op);
- if (DisableScheduling)
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
// FractionalPartOfX = x - (float)IntegerPartOfX;
SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX);
@@ -3949,11 +3750,9 @@ SelectionDAGBuilder::visitExp2(CallInst &I) {
IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX,
DAG.getConstant(23, TLI.getPointerTy()));
- if (DisableScheduling) {
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(X.getNode(), SDNodeOrder);
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(X.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
if (LimitFloatPrecision <= 6) {
// For floating-point precision of 6:
@@ -3977,15 +3776,13 @@ SelectionDAGBuilder::visitExp2(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -4012,17 +3809,15 @@ SelectionDAGBuilder::visitExp2(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -4060,32 +3855,28 @@ SelectionDAGBuilder::visitExp2(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
result = DAG.getNode(ISD::FEXP2, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
-
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -4127,19 +3918,16 @@ SelectionDAGBuilder::visitPow(CallInst &I) {
SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX);
SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1);
- if (DisableScheduling) {
- DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(X.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t0.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t1.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(X.getNode(), SDNodeOrder);
// IntegerPartOfX <<= 23;
IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX,
DAG.getConstant(23, TLI.getPointerTy()));
- if (DisableScheduling)
- DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder);
if (LimitFloatPrecision <= 6) {
// For floating-point precision of 6:
@@ -4163,15 +3951,13 @@ SelectionDAGBuilder::visitPow(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) {
// For floating-point precision of 12:
//
@@ -4198,17 +3984,15 @@ SelectionDAGBuilder::visitPow(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
} else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18
// For floating-point precision of 18:
//
@@ -4246,23 +4030,21 @@ SelectionDAGBuilder::visitPow(CallInst &I) {
result = DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::f32, TwoToFractionalPartOfX);
- if (DisableScheduling) {
- DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
- DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
- DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(t2.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t3.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t4.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t5.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t6.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t7.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t8.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t9.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t10.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t11.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t12.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t13.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(t14.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
} else {
// No special expansion.
@@ -4270,9 +4052,7 @@ SelectionDAGBuilder::visitPow(CallInst &I) {
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)),
getValue(I.getOperand(2)));
-
- if (DisableScheduling)
- DAG.AssignOrdering(result.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(result.getNode(), SDNodeOrder);
}
setValue(&I, result);
@@ -4352,15 +4132,13 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::frameaddress:
Res = DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::setjmp:
return "_setjmp"+!TLI.usesUnderscoreSetJmp();
@@ -4374,8 +4152,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false,
I.getOperand(1), 0, I.getOperand(2), 0);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::memset: {
@@ -4386,8 +4163,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align,
I.getOperand(1), 0);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::memmove: {
@@ -4406,16 +4182,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false,
I.getOperand(1), 0, I.getOperand(2), 0);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
Res = DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align,
I.getOperand(1), 0, I.getOperand(2), 0);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::dbg_declare: {
@@ -4457,8 +4231,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
SDValue Op = DAG.getNode(ISD::EXCEPTIONADDR, dl, VTs, Ops, 1);
setValue(&I, Op);
DAG.setRoot(Op.getValue(1));
- if (DisableScheduling)
- DAG.AssignOrdering(Op.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Op.getNode(), SDNodeOrder);
return 0;
}
@@ -4487,10 +4260,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getSExtOrTrunc(Op, dl, MVT::i32);
setValue(&I, Res);
- if (DisableScheduling) {
- DAG.AssignOrdering(Op.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Op.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
@@ -4508,8 +4279,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
}
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
@@ -4523,8 +4293,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
getValue(I.getOperand(1)),
getValue(I.getOperand(2)));
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
} else {
setValue(&I, DAG.getConstant(0, TLI.getPointerTy()));
}
@@ -4550,12 +4319,10 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(),
FA, Offset);
setValue(&I, Res);
- if (DisableScheduling) {
- DAG.AssignOrdering(CfaArg.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Offset.getNode(), SDNodeOrder);
- DAG.AssignOrdering(FA.getNode(), SDNodeOrder);
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(CfaArg.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Offset.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(FA.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::convertff:
@@ -4588,8 +4355,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
getValue(I.getOperand(3)),
Code);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::sqrt:
@@ -4597,31 +4363,27 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::powi:
Res = ExpandPowI(dl, getValue(I.getOperand(1)), getValue(I.getOperand(2)),
DAG);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::sin:
Res = DAG.getNode(ISD::FSIN, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::cos:
Res = DAG.getNode(ISD::FCOS, dl,
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::log:
visitLog(I);
@@ -4645,8 +4407,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
SDValue Tmp = getValue(I.getOperand(1));
Res = DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::readcyclecounter: {
@@ -4656,8 +4417,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
&Op, 1);
setValue(&I, Res);
DAG.setRoot(Res.getValue(1));
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::bswap:
@@ -4665,16 +4425,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
getValue(I.getOperand(1)).getValueType(),
getValue(I.getOperand(1)));
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::cttz: {
SDValue Arg = getValue(I.getOperand(1));
EVT Ty = Arg.getValueType();
Res = DAG.getNode(ISD::CTTZ, dl, Ty, Arg);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::ctlz: {
@@ -4682,8 +4440,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
EVT Ty = Arg.getValueType();
Res = DAG.getNode(ISD::CTLZ, dl, Ty, Arg);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::ctpop: {
@@ -4691,8 +4448,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
EVT Ty = Arg.getValueType();
Res = DAG.getNode(ISD::CTPOP, dl, Ty, Arg);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::stacksave: {
@@ -4701,16 +4457,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
DAG.getVTList(TLI.getPointerTy(), MVT::Other), &Op, 1);
setValue(&I, Res);
DAG.setRoot(Res.getValue(1));
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::stackrestore: {
Res = getValue(I.getOperand(1));
Res = DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Res);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::stackprotector: {
@@ -4733,8 +4487,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
0, true);
setValue(&I, Res);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::objectsize: {
@@ -4752,8 +4505,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getConstant(0, Ty);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::var_annotation:
@@ -4777,8 +4529,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
setValue(&I, Res);
DAG.setRoot(Res.getValue(1));
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::gcroot:
@@ -4797,14 +4548,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
case Intrinsic::flt_rounds:
Res = DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32);
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::trap:
Res = DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot());
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::uadd_with_overflow:
return implVisitAluOverflow(I, ISD::UADDO);
@@ -4827,8 +4576,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Ops[3] = getValue(I.getOperand(3));
Res = DAG.getNode(ISD::PREFETCH, dl, MVT::Other, &Ops[0], 4);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
@@ -4840,8 +4588,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Res = DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6);
DAG.setRoot(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::atomic_cmp_swap: {
@@ -4856,8 +4603,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
I.getOperand(1));
setValue(&I, L);
DAG.setRoot(L.getValue(1));
- if (DisableScheduling)
- DAG.AssignOrdering(L.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(L.getNode(), SDNodeOrder);
return 0;
}
case Intrinsic::atomic_load_add:
@@ -4888,8 +4634,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
// Discard region information.
Res = DAG.getUNDEF(TLI.getPointerTy());
setValue(&I, Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
case Intrinsic::invariant_end:
case Intrinsic::lifetime_end:
@@ -5070,8 +4815,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee,
"Null value expected with tail call!");
if (Result.first.getNode()) {
setValue(CS.getInstruction(), Result.first);
- if (DisableScheduling)
- DAG.AssignOrdering(Result.first.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Result.first.getNode(), SDNodeOrder);
} else if (!CanLowerReturn && Result.second.getNode()) {
// The instruction result is the result of loading from the
// hidden sret parameter.
@@ -5098,25 +4842,42 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee,
SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(),
MVT::Other, &Chains[0], NumValues);
PendingLoads.push_back(Chain);
+
+ // Collect the legal value parts into potentially illegal values
+ // that correspond to the original function's return values.
+ SmallVector<EVT, 4> RetTys;
+ RetTy = FTy->getReturnType();
+ ComputeValueVTs(TLI, RetTy, RetTys);
+ ISD::NodeType AssertOp = ISD::DELETED_NODE;
+ SmallVector<SDValue, 4> ReturnValues;
+ unsigned CurReg = 0;
+ for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+ EVT VT = RetTys[I];
+ EVT RegisterVT = TLI.getRegisterType(RetTy->getContext(), VT);
+ unsigned NumRegs = TLI.getNumRegisters(RetTy->getContext(), VT);
+
+ SDValue ReturnValue =
+ getCopyFromParts(DAG, getCurDebugLoc(), SDNodeOrder, &Values[CurReg], NumRegs,
+ RegisterVT, VT, AssertOp);
+ ReturnValues.push_back(ReturnValue);
+ DAG.AssignOrdering(ReturnValue.getNode(), SDNodeOrder);
+ CurReg += NumRegs;
+ }
+ SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(),
+ DAG.getVTList(&RetTys[0], RetTys.size()),
+ &ReturnValues[0], ReturnValues.size());
- SDValue MV = DAG.getNode(ISD::MERGE_VALUES,
- getCurDebugLoc(),
- DAG.getVTList(&OutVTs[0], NumValues),
- &Values[0], NumValues);
- setValue(CS.getInstruction(), MV);
+ setValue(CS.getInstruction(), Res);
- if (DisableScheduling) {
- DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
- DAG.AssignOrdering(MV.getNode(), SDNodeOrder);
- }
+ DAG.AssignOrdering(Chain.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
}
// As a special case, a null chain means that a tail call has been emitted and
// the DAG root is already updated.
if (Result.second.getNode()) {
DAG.setRoot(Result.second);
- if (DisableScheduling)
- DAG.AssignOrdering(Result.second.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(Result.second.getNode(), SDNodeOrder);
} else {
HasTailCall = true;
}
@@ -5391,9 +5152,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl,
}
Chain = P.getValue(1);
-
- if (DisableScheduling)
- DAG.AssignOrdering(P.getNode(), Order);
+ DAG.AssignOrdering(P.getNode(), Order);
// If the source register was virtual and if we know something about it,
// add an assert node.
@@ -5432,9 +5191,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl,
if (FromVT != MVT::Other) {
P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, dl,
RegisterVT, P, DAG.getValueType(FromVT));
-
- if (DisableScheduling)
- DAG.AssignOrdering(P.getNode(), Order);
+ DAG.AssignOrdering(P.getNode(), Order);
}
}
}
@@ -5444,8 +5201,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl,
Values[Value] = getCopyFromParts(DAG, dl, Order, Parts.begin(),
NumRegs, RegisterVT, ValueVT);
- if (DisableScheduling)
- DAG.AssignOrdering(Values[Value].getNode(), Order);
+ DAG.AssignOrdering(Values[Value].getNode(), Order);
Part += NumRegs;
Parts.clear();
}
@@ -5453,8 +5209,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl,
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
&Values[0], ValueVTs.size());
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return Res;
}
@@ -5491,9 +5246,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl,
}
Chains[i] = Part.getValue(0);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Part.getNode(), Order);
+ DAG.AssignOrdering(Part.getNode(), Order);
}
if (NumRegs == 1 || Flag)
@@ -5511,8 +5264,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl,
else
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], NumRegs);
- if (DisableScheduling)
- DAG.AssignOrdering(Chain.getNode(), Order);
+ DAG.AssignOrdering(Chain.getNode(), Order);
}
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
@@ -5529,8 +5281,7 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code,
SDValue Res = DAG.getTargetConstant(Flag, MVT::i32);
Ops.push_back(Res);
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) {
unsigned NumRegs = TLI->getNumRegisters(*DAG.getContext(), ValueVTs[Value]);
@@ -5539,9 +5290,7 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code,
assert(Reg < Regs.size() && "Mismatch in # registers expected");
SDValue Res = DAG.getRegister(Regs[Reg++], RegisterVT);
Ops.push_back(Res);
-
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
}
}
}
@@ -5761,8 +5510,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo,
OpInfo.ConstraintVT = RegVT;
}
- if (DisableScheduling)
- DAG.AssignOrdering(OpInfo.CallOperand.getNode(), SDNodeOrder);
+ DAG.AssignOrdering(OpInfo.CallOperand.getNode(), SDNodeOrder);
}
NumRegs = TLI.getNumRegisters(Context, OpInfo.ConstraintVT);
@@ -6483,8 +6231,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
"LowerCall emitted a value with the wrong type!");
});
- if (DisableScheduling)
- DAG.AssignOrdering(Chain.getNode(), Order);
+ DAG.AssignOrdering(Chain.getNode(), Order);
// For a tail call, the return value is merely live-out and there aren't
// any nodes in the DAG representing it. Return a special value to
@@ -6513,8 +6260,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
getCopyFromParts(DAG, dl, Order, &InVals[CurReg], NumRegs,
RegisterVT, VT, AssertOp);
ReturnValues.push_back(ReturnValue);
- if (DisableScheduling)
- DAG.AssignOrdering(ReturnValue.getNode(), Order);
+ DAG.AssignOrdering(ReturnValue.getNode(), Order);
CurReg += NumRegs;
}
@@ -6527,8 +6273,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&RetTys[0], RetTys.size()),
&ReturnValues[0], ReturnValues.size());
- if (DisableScheduling)
- DAG.AssignOrdering(Res.getNode(), Order);
+ DAG.AssignOrdering(Res.getNode(), Order);
return std::make_pair(Res, Chain);
}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9ac8f83..2bec964 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -144,7 +144,7 @@ namespace llvm {
if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency)
return createTDListDAGScheduler(IS, OptLevel);
assert(TLI.getSchedulingPreference() ==
- TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
+ TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
return createBURRListDAGScheduler(IS, OptLevel);
}
}
@@ -1426,7 +1426,7 @@ void SelectionDAGISel::CannotYetSelect(SDNode *N) {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Cannot yet select: ";
- N->print(Msg, CurDAG);
+ N->printrFull(Msg, CurDAG);
llvm_report_error(Msg.str());
}
diff --git a/lib/CodeGen/SlotIndexes.cpp b/lib/CodeGen/SlotIndexes.cpp
index b8f529b..a23efb2 100644
--- a/lib/CodeGen/SlotIndexes.cpp
+++ b/lib/CodeGen/SlotIndexes.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;
@@ -107,6 +108,8 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end();
miItr != miEnd; ++miItr) {
MachineInstr *mi = &*miItr;
+ if (mi->getOpcode()==TargetInstrInfo::DEBUG_VALUE)
+ continue;
if (miItr == mbb->getFirstTerminator()) {
push_back(createEntry(0, index));
diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp
index f51f74d..d6860bc 100644
--- a/lib/CodeGen/TailDuplication.cpp
+++ b/lib/CodeGen/TailDuplication.cpp
@@ -108,12 +108,8 @@ bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) {
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
bool MadeChange = false;
- bool MadeChangeThisIteration = true;
- while (MadeChangeThisIteration) {
- MadeChangeThisIteration = false;
- MadeChangeThisIteration |= TailDuplicateBlocks(MF);
- MadeChange |= MadeChangeThisIteration;
- }
+ while (TailDuplicateBlocks(MF))
+ MadeChange = true;
return MadeChange;
}
@@ -437,28 +433,28 @@ bool
TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF,
SmallVector<MachineBasicBlock*, 8> &TDBBs,
SmallVector<MachineInstr*, 16> &Copies) {
- // Pre-regalloc tail duplication hurts compile time and doesn't help
- // much except for indirect branches.
- bool hasIndirectBranch = (!TailBB->empty() &&
- TailBB->back().getDesc().isIndirectBranch());
- if (PreRegAlloc && !hasIndirectBranch)
- return false;
-
// Set the limit on the number of instructions to duplicate, with a default
// of one less than the tail-merge threshold. When optimizing for size,
// duplicate only one, because one branch instruction can be eliminated to
// compensate for the duplication.
unsigned MaxDuplicateCount;
- if (hasIndirectBranch)
+ if (MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
+ MaxDuplicateCount = 1;
+ else
+ MaxDuplicateCount = TailDuplicateSize;
+
+ if (PreRegAlloc) {
+ // Pre-regalloc tail duplication hurts compile time and doesn't help
+ // much except for indirect branches.
+ if (TailBB->empty() || !TailBB->back().getDesc().isIndirectBranch())
+ return false;
// If the target has hardware branch prediction that can handle indirect
// branches, duplicating them can often make them predictable when there
// are common paths through the code. The limit needs to be high enough
- // to allow undoing the effects of tail merging.
+ // to allow undoing the effects of tail merging and other optimizations
+ // that rearrange the predecessors of the indirect branch.
MaxDuplicateCount = 20;
- else if (MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
- MaxDuplicateCount = 1;
- else
- MaxDuplicateCount = TailDuplicateSize;
+ }
// Don't try to tail-duplicate single-block loops.
if (TailBB->isSuccessor(TailBB))
diff --git a/lib/ExecutionEngine/Interpreter/Makefile b/lib/ExecutionEngine/Interpreter/Makefile
index 5f937c3..4df38ea 100644
--- a/lib/ExecutionEngine/Interpreter/Makefile
+++ b/lib/ExecutionEngine/Interpreter/Makefile
@@ -6,7 +6,9 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMInterpreter
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 0f604ac..4dc119d 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -20,6 +20,7 @@
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -368,12 +369,12 @@ namespace {
// the stub is unused.
DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs;
- DebugLocTuple PrevDLT;
+ DILocation PrevDLT;
public:
JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM)
: SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0),
- EmittedFunctions(this) {
+ EmittedFunctions(this), PrevDLT(NULL) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
if (jit.getJITInfo().needsGOT()) {
MemMgr->AllocateGOT();
@@ -806,10 +807,11 @@ void JITEmitter::AddStubToCurrentFunction(void *StubAddr) {
void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) {
if (!DL.isUnknown()) {
- DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL);
+ DILocation CurDLT = EmissionDetails.MF->getDILocation(DL);
if (BeforePrintingInsn) {
- if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
+ if (CurDLT.getScope().getNode() != 0
+ && PrevDLT.getNode() != CurDLT.getNode()) {
JITEvent_EmittedFunctionDetails::LineStart NextLine;
NextLine.Address = getCurrentPCValue();
NextLine.Loc = DL;
diff --git a/lib/ExecutionEngine/JIT/Makefile b/lib/ExecutionEngine/JIT/Makefile
index e2c9c61..1c93c06 100644
--- a/lib/ExecutionEngine/JIT/Makefile
+++ b/lib/ExecutionEngine/JIT/Makefile
@@ -6,8 +6,10 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMJIT
+CXXFLAGS = -fno-rtti
# Get the $(ARCH) setting
include $(LEVEL)/Makefile.config
diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
index d01c4b2..2baf979 100644
--- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
+++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
@@ -18,10 +18,12 @@
#define DEBUG_TYPE "oprofile-jit-event-listener"
#include "llvm/Function.h"
+#include "llvm/Metadata.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Errno.h"
#include "llvm/Config/config.h"
@@ -70,15 +72,15 @@ OProfileJITEventListener::~OProfileJITEventListener() {
class FilenameCache {
// Holds the filename of each Scope, so that we can pass a null-terminated
- // string into oprofile.
- DenseMap<MDNode*, std::string> Filenames;
+ // string into oprofile. Use an AssertingVH rather than a ValueMap because we
+ // shouldn't be modifying any MDNodes while this map is alive.
+ DenseMap<AssertingVH<MDNode>, std::string> Filenames;
public:
- const char *getFilename(MDNode *Scope) {
- std::string &Filename = Filenames[Scope];
+ const char *getFilename(DIScope Scope) {
+ std::string &Filename = Filenames[Scope.getNode()];
if (Filename.empty()) {
- DIScope S(Scope);
- Filename = S.getFilename();
+ Filename = Scope.getFilename();
}
return Filename.c_str();
}
@@ -89,9 +91,9 @@ static debug_line_info LineStartToOProfileFormat(
uintptr_t Address, DebugLoc Loc) {
debug_line_info Result;
Result.vma = Address;
- const DebugLocTuple &tuple = MF.getDebugLocTuple(Loc);
- Result.lineno = tuple.Line;
- Result.filename = Filenames.getFilename(tuple.Scope);
+ DILocation DILoc = MF.getDILocation(Loc);
+ Result.lineno = DILoc.getLineNumber();
+ Result.filename = Filenames.getFilename(DILoc.getScope());
DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
<< Result.filename << ":" << Result.lineno << "\n");
return Result;
diff --git a/lib/ExecutionEngine/Makefile b/lib/ExecutionEngine/Makefile
index e0e050e..2387b0e 100644
--- a/lib/ExecutionEngine/Makefile
+++ b/lib/ExecutionEngine/Makefile
@@ -9,5 +9,6 @@
LEVEL = ../..
LIBRARYNAME = LLVMExecutionEngine
PARALLEL_DIRS = Interpreter JIT
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index dcd696c..e2cd47a 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -392,7 +392,7 @@ static Value *RemapOperand(const Value *In,
assert(!isa<GlobalValue>(CPV) && "Unmapped global?");
llvm_unreachable("Unknown type of derived type constant value!");
}
- } else if (isa<MetadataBase>(In)) {
+ } else if (isa<MDNode>(In) || isa<MDString>(In)) {
Result = const_cast<Value*>(In);
} else if (isa<InlineAsm>(In)) {
Result = const_cast<Value*>(In);
diff --git a/lib/Linker/Makefile b/lib/Linker/Makefile
index 19e646b..2179fd2 100644
--- a/lib/Linker/Makefile
+++ b/lib/Linker/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../..
LIBRARYNAME = LLVMLinker
BUILD_ARCHIVE := 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 8a1a058..9ead33b 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -2,8 +2,6 @@ add_llvm_library(LLVMMC
MCAsmInfo.cpp
MCAsmInfoCOFF.cpp
MCAsmInfoDarwin.cpp
- MCAsmLexer.cpp
- MCAsmParser.cpp
MCAsmStreamer.cpp
MCAssembler.cpp
MCCodeEmitter.cpp
@@ -20,5 +18,4 @@ add_llvm_library(LLVMMC
MCStreamer.cpp
MCSymbol.cpp
MCValue.cpp
- TargetAsmParser.cpp
)
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 3e5c97d..547f904 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -19,8 +19,9 @@
using namespace llvm;
MCAsmInfo::MCAsmInfo() {
- ZeroFillDirective = 0;
- NonexecutableStackDirective = 0;
+ HasSubsectionsViaSymbols = false;
+ HasMachoZeroFillDirective = false;
+ HasStaticCtorDtorReferenceInStaticMode = false;
NeedsSet = false;
MaxInstLength = 4;
PCSymbol = "$";
@@ -36,7 +37,6 @@ MCAsmInfo::MCAsmInfo() {
AllowQuotesInName = false;
AllowNameToStartWithDigit = false;
ZeroDirective = "\t.zero\t";
- ZeroDirectiveSuffix = 0;
AsciiDirective = "\t.ascii\t";
AscizDirective = "\t.asciz\t";
Data8bitsDirective = "\t.byte\t";
@@ -52,17 +52,16 @@ MCAsmInfo::MCAsmInfo() {
PICJumpTableDirective = 0;
GlobalDirective = "\t.globl\t";
SetDirective = 0;
- LCOMMDirective = 0;
- COMMDirective = "\t.comm\t";
+ HasLCOMMDirective = false;
COMMDirectiveTakesAlignment = true;
HasDotTypeDotSizeDirective = true;
HasSingleParameterDotFile = true;
- UsedDirective = 0;
+ HasNoDeadStrip = false;
WeakRefDirective = 0;
WeakDefDirective = 0;
- // FIXME: These are ELFish - move to ELFMAI.
- HiddenDirective = "\t.hidden\t";
- ProtectedDirective = "\t.protected\t";
+ LinkOnceDirective = 0;
+ HiddenVisibilityAttr = MCSA_Hidden;
+ ProtectedVisibilityAttr = MCSA_Protected;
AbsoluteDebugSectionOffsets = false;
AbsoluteEHSectionOffsets = false;
HasLEB128 = false;
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index 23b0dd7..e395acd 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -18,14 +18,17 @@ using namespace llvm;
MCAsmInfoCOFF::MCAsmInfoCOFF() {
GlobalPrefix = "_";
- LCOMMDirective = "\t.lcomm\t";
+ HasLCOMMDirective = true;
COMMDirectiveTakesAlignment = false;
HasDotTypeDotSizeDirective = false;
HasSingleParameterDotFile = false;
- HiddenDirective = NULL;
PrivateGlobalPrefix = "L"; // Prefix for private global symbols
WeakRefDirective = "\t.weak\t";
+ LinkOnceDirective = "\t.linkonce same_size\n";
SetDirective = "\t.set\t";
+
+ // Doesn't support visibility:
+ HiddenVisibilityAttr = ProtectedVisibilityAttr = MCSA_Invalid;
// Set up DWARF directives
HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index d99120d..9902f50 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -24,6 +24,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
NeedsSet = true;
AllowQuotesInName = true;
HasSingleParameterDotFile = false;
+ HasSubsectionsViaSymbols = true;
AlignmentIsInBytes = false;
InlineAsmStart = " InlineAsm Start";
@@ -32,14 +33,20 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
// Directives:
WeakDefDirective = "\t.weak_definition ";
WeakRefDirective = "\t.weak_reference ";
- HiddenDirective = "\t.private_extern ";
- LCOMMDirective = "\t.lcomm\t";
ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
- ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
+ HasMachoZeroFillDirective = true; // Uses .zerofill
+ HasStaticCtorDtorReferenceInStaticMode = true;
SetDirective = "\t.set";
- ProtectedDirective = "\t.globl\t";
+
+ HiddenVisibilityAttr = MCSA_PrivateExtern;
+ // Doesn't support protected visibility.
+ ProtectedVisibilityAttr = MCSA_Global;
+
+
HasDotTypeDotSizeDirective = false;
- UsedDirective = "\t.no_dead_strip\t";
+ 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
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index b6ebb1a..bf39239 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
@@ -17,26 +16,68 @@
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormattedStream.h"
using namespace llvm;
namespace {
class MCAsmStreamer : public MCStreamer {
- raw_ostream &OS;
+ formatted_raw_ostream &OS;
const MCAsmInfo &MAI;
+ bool IsLittleEndian, IsVerboseAsm;
MCInstPrinter *InstPrinter;
MCCodeEmitter *Emitter;
+
+ SmallString<128> CommentToEmit;
+ raw_svector_ostream CommentStream;
public:
- MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai,
- MCInstPrinter *_Printer, MCCodeEmitter *_Emitter)
- : MCStreamer(Context), OS(_OS), MAI(tai), InstPrinter(_Printer),
- Emitter(_Emitter) {}
+ MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
+ const MCAsmInfo &mai,
+ bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer,
+ MCCodeEmitter *emitter)
+ : MCStreamer(Context), OS(os), MAI(mai), IsLittleEndian(isLittleEndian),
+ IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter),
+ CommentStream(CommentToEmit) {}
~MCAsmStreamer() {}
+ bool isLittleEndian() const { return IsLittleEndian; }
+
+
+ inline void EmitEOL() {
+ // If we don't have any comments, just emit a \n.
+ if (!IsVerboseAsm) {
+ OS << '\n';
+ return;
+ }
+ EmitCommentsAndEOL();
+ }
+ void EmitCommentsAndEOL();
+
+ /// AddComment - Add a comment that can be emitted to the generated .s
+ /// file if applicable as a QoI issue to make the output of the compiler
+ /// more readable. This only affects the MCAsmStreamer, and only when
+ /// verbose assembly output is enabled.
+ virtual void AddComment(const Twine &T);
+
+ /// GetCommentOS - Return a raw_ostream that comments can be written to.
+ /// Unlike AddComment, you are required to terminate comments with \n if you
+ /// use this method.
+ virtual raw_ostream &GetCommentOS() {
+ if (!IsVerboseAsm)
+ return nulls(); // Discard comments unless in verbose asm mode.
+ return CommentStream;
+ }
+
+ /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
+ virtual void AddBlankLine() {
+ EmitEOL();
+ }
+
/// @name MCStreamer Interface
/// @{
@@ -44,23 +85,33 @@ public:
virtual void EmitLabel(MCSymbol *Symbol);
- virtual void EmitAssemblerFlag(AssemblerFlag Flag);
+ virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
- virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
+ /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
+ ///
+ /// @param Symbol - The common symbol to emit.
+ /// @param Size - The size of the common symbol.
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0);
- virtual void EmitBytes(StringRef Data);
+ virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
- virtual void EmitValue(const MCExpr *Value, unsigned Size);
+ virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
+ virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace);
+
+ virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue,
+ unsigned AddrSpace);
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
@@ -78,6 +129,50 @@ public:
} // end anonymous namespace.
+/// AddComment - Add a comment that can be emitted to the generated .s
+/// file if applicable as a QoI issue to make the output of the compiler
+/// more readable. This only affects the MCAsmStreamer, and only when
+/// verbose assembly output is enabled.
+void MCAsmStreamer::AddComment(const Twine &T) {
+ if (!IsVerboseAsm) return;
+
+ // Make sure that CommentStream is flushed.
+ CommentStream.flush();
+
+ T.toVector(CommentToEmit);
+ // Each comment goes on its own line.
+ CommentToEmit.push_back('\n');
+
+ // Tell the comment stream that the vector changed underneath it.
+ CommentStream.resync();
+}
+
+void MCAsmStreamer::EmitCommentsAndEOL() {
+ if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
+ OS << '\n';
+ return;
+ }
+
+ CommentStream.flush();
+ StringRef Comments = CommentToEmit.str();
+
+ assert(Comments.back() == '\n' &&
+ "Comment array not newline terminated");
+ do {
+ // Emit a line of comments.
+ OS.PadToColumn(MAI.getCommentColumn());
+ size_t Position = Comments.find('\n');
+ OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n';
+
+ Comments = Comments.substr(Position+1);
+ } while (!Comments.empty());
+
+ CommentToEmit.clear();
+ // Tell the comment stream that the vector changed underneath it.
+ CommentStream.resync();
+}
+
+
static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
assert(Bytes && "Invalid size!");
return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
@@ -101,17 +196,17 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
assert(CurSection && "Cannot emit before setting section!");
- Symbol->print(OS, &MAI);
- OS << ":\n";
+ OS << *Symbol << ":";
+ EmitEOL();
Symbol->setSection(*CurSection);
}
-void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
+void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
default: assert(0 && "Invalid flag!");
- case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
+ case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
}
- OS << '\n';
+ EmitEOL();
}
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
@@ -119,10 +214,8 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
"Cannot define a symbol twice!");
- Symbol->print(OS, &MAI);
- OS << " = ";
- Value->print(OS, &MAI);
- OS << '\n';
+ OS << *Symbol << " = " << *Value;
+ EmitEOL();
// FIXME: Lift context changes into super class.
// FIXME: Set associated section.
@@ -130,41 +223,54 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
}
void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
- SymbolAttr Attribute) {
+ MCSymbolAttr Attribute) {
switch (Attribute) {
- case Global: OS << ".globl"; break;
- case Hidden: OS << ".hidden"; break;
- case IndirectSymbol: OS << ".indirect_symbol"; break;
- case Internal: OS << ".internal"; break;
- case LazyReference: OS << ".lazy_reference"; break;
- case NoDeadStrip: OS << ".no_dead_strip"; break;
- case PrivateExtern: OS << ".private_extern"; break;
- case Protected: OS << ".protected"; break;
- case Reference: OS << ".reference"; break;
- case Weak: OS << ".weak"; break;
- case WeakDefinition: OS << ".weak_definition"; break;
- case WeakReference: OS << ".weak_reference"; break;
+ case MCSA_Invalid: assert(0 && "Invalid symbol attribute");
+ case MCSA_Global: OS << MAI.getGlobalDirective(); break; // .globl
+ case MCSA_Hidden: OS << ".hidden "; break;
+ case MCSA_IndirectSymbol: OS << ".indirect_symbol "; break;
+ case MCSA_Internal: OS << ".internal "; break;
+ case MCSA_LazyReference: OS << ".lazy_reference "; break;
+ case MCSA_Local: OS << ".local "; break;
+ case MCSA_NoDeadStrip: OS << ".no_dead_strip "; break;
+ case MCSA_PrivateExtern: OS << ".private_extern "; break;
+ case MCSA_Protected: OS << ".protected "; break;
+ case MCSA_Reference: OS << ".reference "; break;
+ case MCSA_Weak: OS << ".weak "; break;
+ case MCSA_WeakDefinition: OS << ".weak_definition "; break;
+ // .weak_reference
+ case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break;
}
- OS << ' ';
- Symbol->print(OS, &MAI);
- OS << '\n';
+ OS << *Symbol;
+ EmitEOL();
}
void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- OS << ".desc" << ' ';
- Symbol->print(OS, &MAI);
- OS << ',' << DescValue << '\n';
+ OS << ".desc" << ' ' << *Symbol << ',' << DescValue;
+ EmitEOL();
}
-void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
- OS << ".comm ";
- Symbol->print(OS, &MAI);
- OS << ',' << Size;
- if (ByteAlignment != 0)
- OS << ',' << Log2_32(ByteAlignment);
- OS << '\n';
+ OS << "\t.comm\t" << *Symbol << ',' << Size;
+ if (ByteAlignment != 0 && MAI.getCOMMDirectiveTakesAlignment()) {
+ if (MAI.getAlignmentIsInBytes())
+ OS << ',' << ByteAlignment;
+ else
+ OS << ',' << Log2_32(ByteAlignment);
+ }
+ EmitEOL();
+}
+
+/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
+///
+/// @param Symbol - The common symbol to emit.
+/// @param Size - The size of the common symbol.
+void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!");
+ OS << "\t.lcomm\t" << *Symbol << ',' << Size;
+ EmitEOL();
}
void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
@@ -177,36 +283,130 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
if (Symbol != NULL) {
- OS << ',';
- Symbol->print(OS, &MAI);
- OS << ',' << Size;
+ OS << ',' << *Symbol << ',' << Size;
if (ByteAlignment != 0)
OS << ',' << Log2_32(ByteAlignment);
}
- OS << '\n';
+ EmitEOL();
+}
+
+static inline char toOctal(int X) { return (X&7)+'0'; }
+
+void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
+ assert(CurSection && "Cannot emit contents before setting section!");
+ if (Data.empty()) return;
+
+ if (Data.size() == 1) {
+ OS << MAI.getData8bitsDirective(AddrSpace);
+ OS << (unsigned)(unsigned char)Data[0];
+ EmitEOL();
+ return;
+ }
+
+ // If the data ends with 0 and the target supports .asciz, use it, otherwise
+ // use .ascii
+ if (MAI.getAscizDirective() && Data.back() == 0) {
+ OS << MAI.getAscizDirective();
+ Data = Data.substr(0, Data.size()-1);
+ } else {
+ OS << MAI.getAsciiDirective();
+ }
+
+ OS << " \"";
+ for (unsigned i = 0, e = Data.size(); i != e; ++i) {
+ unsigned char C = Data[i];
+ if (C == '"' || C == '\\') {
+ OS << '\\' << (char)C;
+ continue;
+ }
+
+ if (isprint((unsigned char)C)) {
+ OS << (char)C;
+ continue;
+ }
+
+ switch (C) {
+ case '\b': OS << "\\b"; break;
+ case '\f': OS << "\\f"; break;
+ case '\n': OS << "\\n"; break;
+ case '\r': OS << "\\r"; break;
+ case '\t': OS << "\\t"; break;
+ default:
+ OS << '\\';
+ OS << toOctal(C >> 6);
+ OS << toOctal(C >> 3);
+ OS << toOctal(C >> 0);
+ break;
+ }
+ }
+ OS << '"';
+ EmitEOL();
}
-void MCAsmStreamer::EmitBytes(StringRef Data) {
+/// EmitIntValue - Special case of EmitValue that avoids the client having
+/// to pass in a MCExpr for constant integers.
+void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
+ unsigned AddrSpace) {
assert(CurSection && "Cannot emit contents before setting section!");
- for (unsigned i = 0, e = Data.size(); i != e; ++i)
- OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n';
+ const char *Directive = 0;
+ switch (Size) {
+ default: break;
+ case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break;
+ case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break;
+ case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
+ case 8:
+ Directive = MAI.getData64bitsDirective(AddrSpace);
+ // If the target doesn't support 64-bit data, emit as two 32-bit halves.
+ if (Directive) break;
+ if (isLittleEndian()) {
+ EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace);
+ EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace);
+ } else {
+ EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace);
+ EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace);
+ }
+ return;
+ }
+
+ assert(Directive && "Invalid size for machine code value!");
+ OS << Directive << truncateToSize(Value, Size);
+ EmitEOL();
}
-void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size) {
+void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
+ unsigned AddrSpace) {
assert(CurSection && "Cannot emit contents before setting section!");
- // Need target hooks to know how to print this.
+ const char *Directive = 0;
switch (Size) {
- default:
- llvm_unreachable("Invalid size for machine code value!");
- case 1: OS << ".byte"; break;
- case 2: OS << ".short"; break;
- case 4: OS << ".long"; break;
- case 8: OS << ".quad"; break;
+ default: break;
+ case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break;
+ case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break;
+ case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
+ case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break;
}
+
+ assert(Directive && "Invalid size for machine code value!");
+ OS << Directive << *truncateToSize(Value, Size);
+ EmitEOL();
+}
+
+/// EmitFill - Emit NumBytes bytes worth of the value specified by
+/// FillValue. This implements directives such as '.space'.
+void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
+ unsigned AddrSpace) {
+ if (NumBytes == 0) return;
+
+ if (AddrSpace == 0)
+ if (const char *ZeroDirective = MAI.getZeroDirective()) {
+ OS << ZeroDirective << NumBytes;
+ if (FillValue != 0)
+ OS << ',' << (int)FillValue;
+ EmitEOL();
+ return;
+ }
- OS << ' ';
- truncateToSize(Value, Size)->print(OS, &MAI);
- OS << '\n';
+ // Emit a byte at a time.
+ MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace);
}
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
@@ -236,7 +436,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
}
- OS << '\n';
+ EmitEOL();
return;
}
@@ -254,15 +454,14 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
OS << ", " << truncateToSize(Value, ValueSize);
if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
- OS << '\n';
+ EmitEOL();
}
void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
unsigned char Value) {
// FIXME: Verify that Offset is associated with the current section.
- OS << ".org ";
- Offset->print(OS, &MAI);
- OS << ", " << (unsigned) Value << '\n';
+ OS << ".org " << *Offset << ", " << (unsigned) Value;
+ EmitEOL();
}
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
@@ -271,7 +470,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
// If we have an AsmPrinter, use that to print.
if (InstPrinter) {
InstPrinter->printInst(&Inst);
- OS << '\n';
+ EmitEOL();
// Show the encoding if we have a code emitter.
if (Emitter) {
@@ -296,15 +495,18 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
// Otherwise fall back to a structural printing for now. Eventually we should
// always have access to the target specific printer.
Inst.print(OS, &MAI);
- OS << '\n';
+ EmitEOL();
}
void MCAsmStreamer::Finish() {
OS.flush();
}
-MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS,
- const MCAsmInfo &MAI, MCInstPrinter *IP,
+MCStreamer *llvm::createAsmStreamer(MCContext &Context,
+ formatted_raw_ostream &OS,
+ const MCAsmInfo &MAI, bool isLittleEndian,
+ bool isVerboseAsm, MCInstPrinter *IP,
MCCodeEmitter *CE) {
- return new MCAsmStreamer(Context, OS, MAI, IP, CE);
+ return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm,
+ IP, CE);
}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 1f5b6f1..f0f5a47 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -679,8 +679,6 @@ public:
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
// The string table is padded to a multiple of 4.
- //
- // FIXME: Check to see if this varies per arch.
while (StringTable.size() % 4)
StringTable += '\x00';
}
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index a19ec19..1ee1b1b 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -15,7 +15,7 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+void MCExpr::print(raw_ostream &OS) const {
switch (getKind()) {
case MCExpr::Constant:
OS << cast<MCConstantExpr>(*this).getValue();
@@ -26,13 +26,10 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
// Parenthesize names that start with $ so that they don't look like
// absolute names.
- if (Sym.getName()[0] == '$') {
- OS << '(';
- Sym.print(OS, MAI);
- OS << ')';
- } else {
- Sym.print(OS, MAI);
- }
+ if (Sym.getName()[0] == '$')
+ OS << '(' << Sym << ')';
+ else
+ OS << Sym;
return;
}
@@ -45,7 +42,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
case MCUnaryExpr::Not: OS << '~'; break;
case MCUnaryExpr::Plus: OS << '+'; break;
}
- UE.getSubExpr()->print(OS, MAI);
+ OS << *UE.getSubExpr();
return;
}
@@ -54,11 +51,9 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
// Only print parens around the LHS if it is non-trivial.
if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
- BE.getLHS()->print(OS, MAI);
+ OS << *BE.getLHS();
} else {
- OS << '(';
- BE.getLHS()->print(OS, MAI);
- OS << ')';
+ OS << '(' << *BE.getLHS() << ')';
}
switch (BE.getOpcode()) {
@@ -95,11 +90,9 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
// Only print parens around the LHS if it is non-trivial.
if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
- BE.getRHS()->print(OS, MAI);
+ OS << *BE.getRHS();
} else {
- OS << '(';
- BE.getRHS()->print(OS, MAI);
- OS << ')';
+ OS << '(' << *BE.getRHS() << ')';
}
return;
}
@@ -109,7 +102,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
}
void MCExpr::dump() const {
- print(dbgs(), 0);
+ print(dbgs());
dbgs() << '\n';
}
diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp
index 7c7a644..0634c9f 100644
--- a/lib/MC/MCInst.cpp
+++ b/lib/MC/MCInst.cpp
@@ -23,9 +23,7 @@ void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
else if (isImm())
OS << "Imm:" << getImm();
else if (isExpr()) {
- OS << "Expr:(";
- getExpr()->print(OS, MAI);
- OS << ")";
+ OS << "Expr:(" << *getExpr() << ")";
} else
OS << "UNDEFINED";
OS << ">";
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 828b92a..e559c65 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -117,36 +117,26 @@ public:
/// @{
virtual void SwitchSection(const MCSection *Section);
-
virtual void EmitLabel(MCSymbol *Symbol);
-
- virtual void EmitAssemblerFlag(AssemblerFlag Flag);
-
+ virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
-
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
-
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
-
- virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
-
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ assert(0 && "macho doesn't support this directive");
+ }
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0);
-
- virtual void EmitBytes(StringRef Data);
-
- virtual void EmitValue(const MCExpr *Value, unsigned Size);
-
+ virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
+ virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
-
virtual void EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
-
virtual void EmitInstruction(const MCInst &Inst);
-
virtual void Finish();
/// @}
@@ -183,9 +173,9 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
Symbol->setSection(*CurSection);
}
-void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
+void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
- case SubsectionsViaSymbols:
+ case MCAF_SubsectionsViaSymbols:
Assembler.setSubsectionsViaSymbols(true);
return;
}
@@ -204,10 +194,10 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
}
void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
- SymbolAttr Attribute) {
+ MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
// them. This makes writing matching .o files easier.
- if (Attribute == MCStreamer::IndirectSymbol) {
+ if (Attribute == MCSA_IndirectSymbol) {
// Note that we intentionally cannot use the symbol data here; this is
// important for matching the string table that 'as' generates.
IndirectSymbolData ISD;
@@ -229,19 +219,21 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
// In the future it might be worth trying to make these operations more well
// defined.
switch (Attribute) {
- case MCStreamer::IndirectSymbol:
- case MCStreamer::Hidden:
- case MCStreamer::Internal:
- case MCStreamer::Protected:
- case MCStreamer::Weak:
+ case MCSA_Invalid:
+ case MCSA_IndirectSymbol:
+ case MCSA_Hidden:
+ case MCSA_Internal:
+ case MCSA_Protected:
+ case MCSA_Weak:
+ case MCSA_Local:
assert(0 && "Invalid symbol attribute for Mach-O!");
break;
- case MCStreamer::Global:
+ case MCSA_Global:
SD.setExternal(true);
break;
- case MCStreamer::LazyReference:
+ case MCSA_LazyReference:
// FIXME: This requires -dynamic.
SD.setFlags(SD.getFlags() | SF_NoDeadStrip);
if (Symbol->isUndefined())
@@ -250,23 +242,23 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
// Since .reference sets the no dead strip bit, it is equivalent to
// .no_dead_strip in practice.
- case MCStreamer::Reference:
- case MCStreamer::NoDeadStrip:
+ case MCSA_Reference:
+ case MCSA_NoDeadStrip:
SD.setFlags(SD.getFlags() | SF_NoDeadStrip);
break;
- case MCStreamer::PrivateExtern:
+ case MCSA_PrivateExtern:
SD.setExternal(true);
SD.setPrivateExtern(true);
break;
- case MCStreamer::WeakReference:
+ case MCSA_WeakReference:
// FIXME: This requires -dynamic.
if (Symbol->isUndefined())
SD.setFlags(SD.getFlags() | SF_WeakReference);
break;
- case MCStreamer::WeakDefinition:
+ case MCSA_WeakDefinition:
// FIXME: 'as' enforces that this is defined and global. The manual claims
// it has to be in a coalesced section, but this isn't enforced.
SD.setFlags(SD.getFlags() | SF_WeakDefinition);
@@ -281,7 +273,7 @@ void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask);
}
-void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
@@ -315,14 +307,15 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
SectData.setAlignment(ByteAlignment);
}
-void MCMachOStreamer::EmitBytes(StringRef Data) {
+void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
if (!DF)
DF = new MCDataFragment(CurSectionData);
DF->getContents().append(Data.begin(), Data.end());
}
-void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size) {
+void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size,
+ unsigned AddrSpace) {
new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData);
}
@@ -353,11 +346,13 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
if (!Emitter)
llvm_unreachable("no code emitter available!");
+ // FIXME: Emitting an instruction should cause S_ATTR_SOME_INSTRUCTIONS to
+ // be set for the current section.
// FIXME: Relocations!
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
Emitter->EncodeInstruction(Inst, VecOS);
- EmitBytes(VecOS.str());
+ EmitBytes(VecOS.str(), 0);
}
void MCMachOStreamer::Finish() {
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index ddc4e69..7c219b3 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -31,23 +31,25 @@ namespace {
virtual void EmitLabel(MCSymbol *Symbol) {}
- virtual void EmitAssemblerFlag(AssemblerFlag Flag) {}
+ virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute) {}
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){}
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
- virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0) {}
- virtual void EmitBytes(StringRef Data) {}
+ virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {}
- virtual void EmitValue(const MCExpr *Value, unsigned Size) {}
+ virtual void EmitValue(const MCExpr *Value, unsigned Size,
+ unsigned AddrSpace) {}
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
new file mode 100644
index 0000000..482eefd
--- /dev/null
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -0,0 +1,320 @@
+//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the lexer for assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+using namespace llvm;
+
+AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) {
+ CurBuf = NULL;
+ CurPtr = NULL;
+ TokStart = 0;
+}
+
+AsmLexer::~AsmLexer() {
+}
+
+void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) {
+ CurBuf = buf;
+
+ if (ptr)
+ CurPtr = ptr;
+ else
+ CurPtr = CurBuf->getBufferStart();
+
+ TokStart = 0;
+}
+
+SMLoc AsmLexer::getLoc() const {
+ return SMLoc::getFromPointer(TokStart);
+}
+
+/// ReturnError - Set the error to the specified string at the specified
+/// location. This is defined to always return AsmToken::Error.
+AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
+ SetError(SMLoc::getFromPointer(Loc), Msg);
+
+ return AsmToken(AsmToken::Error, StringRef(Loc, 0));
+}
+
+int AsmLexer::getNextChar() {
+ char CurChar = *CurPtr++;
+ switch (CurChar) {
+ default:
+ return (unsigned char)CurChar;
+ case 0:
+ // A nul character in the stream is either the end of the current buffer or
+ // a random nul in the file. Disambiguate that here.
+ if (CurPtr-1 != CurBuf->getBufferEnd())
+ return 0; // Just whitespace.
+
+ // Otherwise, return end of file.
+ --CurPtr; // Another call to lex will return EOF again.
+ return EOF;
+ }
+}
+
+/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+AsmToken AsmLexer::LexIdentifier() {
+ while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
+ *CurPtr == '.' || *CurPtr == '@')
+ ++CurPtr;
+ return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
+}
+
+/// LexSlash: Slash: /
+/// C-Style Comment: /* ... */
+AsmToken AsmLexer::LexSlash() {
+ switch (*CurPtr) {
+ case '*': break; // C style comment.
+ case '/': return ++CurPtr, LexLineComment();
+ default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1));
+ }
+
+ // C Style comment.
+ ++CurPtr; // skip the star.
+ while (1) {
+ int CurChar = getNextChar();
+ switch (CurChar) {
+ case EOF:
+ return ReturnError(TokStart, "unterminated comment");
+ case '*':
+ // End of the comment?
+ if (CurPtr[0] != '/') break;
+
+ ++CurPtr; // End the */.
+ return LexToken();
+ }
+ }
+}
+
+/// LexLineComment: Comment: #[^\n]*
+/// : //[^\n]*
+AsmToken AsmLexer::LexLineComment() {
+ // FIXME: This is broken if we happen to a comment at the end of a file, which
+ // was .included, and which doesn't end with a newline.
+ int CurChar = getNextChar();
+ while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF)
+ CurChar = getNextChar();
+
+ if (CurChar == EOF)
+ return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0));
+ return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0));
+}
+
+
+/// LexDigit: First character is [0-9].
+/// Local Label: [0-9][:]
+/// Forward/Backward Label: [0-9][fb]
+/// Binary integer: 0b[01]+
+/// Octal integer: 0[0-7]+
+/// Hex integer: 0x[0-9a-fA-F]+
+/// Decimal integer: [1-9][0-9]*
+/// TODO: FP literal.
+AsmToken AsmLexer::LexDigit() {
+ if (*CurPtr == ':')
+ return ReturnError(TokStart, "FIXME: local label not implemented");
+ if (*CurPtr == 'f' || *CurPtr == 'b')
+ return ReturnError(TokStart, "FIXME: directional label not implemented");
+
+ // Decimal integer: [1-9][0-9]*
+ if (CurPtr[-1] != '0') {
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+
+ StringRef Result(TokStart, CurPtr - TokStart);
+
+ long long Value;
+ if (Result.getAsInteger(10, Value))
+ return ReturnError(TokStart, "Invalid decimal number");
+ return AsmToken(AsmToken::Integer, Result, Value);
+ }
+
+ if (*CurPtr == 'b') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (CurPtr[0] == '0' || CurPtr[0] == '1')
+ ++CurPtr;
+
+ // Requires at least one binary digit.
+ if (CurPtr == NumStart)
+ return ReturnError(TokStart, "Invalid binary number");
+
+ StringRef Result(TokStart, CurPtr - TokStart);
+
+ long long Value;
+ if (Result.getAsInteger(2, Value))
+ return ReturnError(TokStart, "Invalid binary number");
+
+ return AsmToken(AsmToken::Integer, Result, Value);
+ }
+
+ if (*CurPtr == 'x') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (isxdigit(CurPtr[0]))
+ ++CurPtr;
+
+ // Requires at least one hex digit.
+ if (CurPtr == NumStart)
+ return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+
+ unsigned long long Result;
+ if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+
+ return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
+ (int64_t)Result);
+ }
+
+ // Must be an octal number, it starts with 0.
+ while (*CurPtr >= '0' && *CurPtr <= '7')
+ ++CurPtr;
+
+ StringRef Result(TokStart, CurPtr - TokStart);
+ long long Value;
+ if (Result.getAsInteger(8, Value))
+ return ReturnError(TokStart, "Invalid octal number");
+
+ return AsmToken(AsmToken::Integer, Result, Value);
+}
+
+/// LexQuote: String: "..."
+AsmToken AsmLexer::LexQuote() {
+ int CurChar = getNextChar();
+ // TODO: does gas allow multiline string constants?
+ while (CurChar != '"') {
+ if (CurChar == '\\') {
+ // Allow \", etc.
+ CurChar = getNextChar();
+ }
+
+ if (CurChar == EOF)
+ return ReturnError(TokStart, "unterminated string constant");
+
+ CurChar = getNextChar();
+ }
+
+ return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
+}
+
+StringRef AsmLexer::LexUntilEndOfStatement() {
+ TokStart = CurPtr;
+
+ while (!isAtStartOfComment(*CurPtr) && // Start of line comment.
+ *CurPtr != ';' && // End of statement marker.
+ *CurPtr != '\n' &&
+ *CurPtr != '\r' &&
+ (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) {
+ ++CurPtr;
+ }
+ return StringRef(TokStart, CurPtr-TokStart);
+}
+
+bool AsmLexer::isAtStartOfComment(char Char) {
+ // FIXME: This won't work for multi-character comment indicators like "//".
+ return Char == *MAI.getCommentString();
+}
+
+AsmToken AsmLexer::LexToken() {
+ TokStart = CurPtr;
+ // This always consumes at least one character.
+ int CurChar = getNextChar();
+
+ if (isAtStartOfComment(CurChar))
+ return LexLineComment();
+
+ switch (CurChar) {
+ default:
+ // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
+ return LexIdentifier();
+
+ // Unknown character, emit an error.
+ return ReturnError(TokStart, "invalid character in input");
+ case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
+ case 0:
+ case ' ':
+ case '\t':
+ // Ignore whitespace.
+ return LexToken();
+ case '\n': // FALL THROUGH.
+ case '\r': // FALL THROUGH.
+ case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
+ case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
+ case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
+ case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
+ case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
+ case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
+ case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
+ case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
+ case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
+ case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
+ case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
+ case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
+ case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
+ case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
+ case '=':
+ if (*CurPtr == '=')
+ return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
+ case '|':
+ if (*CurPtr == '|')
+ return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
+ case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
+ case '&':
+ if (*CurPtr == '&')
+ return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
+ case '!':
+ if (*CurPtr == '=')
+ return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
+ case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
+ case '/': return LexSlash();
+ case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
+ case '"': return LexQuote();
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return LexDigit();
+ case '<':
+ switch (*CurPtr) {
+ case '<': return ++CurPtr, AsmToken(AsmToken::LessLess,
+ StringRef(TokStart, 2));
+ case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual,
+ StringRef(TokStart, 2));
+ case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater,
+ StringRef(TokStart, 2));
+ default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
+ }
+ case '>':
+ switch (*CurPtr) {
+ case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater,
+ StringRef(TokStart, 2));
+ case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual,
+ StringRef(TokStart, 2));
+ default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
+ }
+
+ // TODO: Quoted identifiers (objc methods etc)
+ // local labels: [0-9][:]
+ // Forward/backward labels: [0-9][fb]
+ // Integers, fp constants, character constants.
+ }
+}
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
new file mode 100644
index 0000000..dd438b7
--- /dev/null
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -0,0 +1,1781 @@
+//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the parser for assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/AsmParser.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.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"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetAsmParser.h"
+using namespace llvm;
+
+
+enum { DEFAULT_ADDRSPACE = 0 };
+
+// Mach-O section uniquing.
+//
+// FIXME: Figure out where this should live, it should be shared by
+// TargetLoweringObjectFile.
+typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
+
+AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
+ const MCAsmInfo &_MAI)
+ : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0),
+ CurBuffer(0), SectionUniquingMap(0) {
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+
+ // Debugging directives.
+ AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile);
+ AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine);
+ AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc);
+}
+
+
+
+AsmParser::~AsmParser() {
+ // If we have the MachO uniquing map, free it.
+ delete (MachOUniqueMapTy*)SectionUniquingMap;
+}
+
+const MCSection *AsmParser::getMachOSection(const StringRef &Segment,
+ const StringRef &Section,
+ unsigned TypeAndAttributes,
+ unsigned Reserved2,
+ SectionKind Kind) const {
+ // We unique sections by their segment/section pair. The returned section
+ // may not have the same flags as the requested section, if so this should be
+ // diagnosed by the client as an error.
+
+ // Create the map if it doesn't already exist.
+ if (SectionUniquingMap == 0)
+ SectionUniquingMap = new MachOUniqueMapTy();
+ MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap;
+
+ // Form the name to look up.
+ SmallString<64> Name;
+ Name += Segment;
+ Name.push_back(',');
+ Name += Section;
+
+ // Do the lookup, if we have a hit, return it.
+ const MCSectionMachO *&Entry = Map[Name.str()];
+
+ // FIXME: This should validate the type and attributes.
+ if (Entry) return Entry;
+
+ // Otherwise, return a new section.
+ return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes,
+ Reserved2, Kind, Ctx);
+}
+
+void AsmParser::Warning(SMLoc L, const Twine &Msg) {
+ PrintMessage(L, Msg.str(), "warning");
+}
+
+bool AsmParser::Error(SMLoc L, const Twine &Msg) {
+ PrintMessage(L, Msg.str(), "error");
+ return true;
+}
+
+bool AsmParser::TokError(const char *Msg) {
+ PrintMessage(Lexer.getLoc(), Msg, "error");
+ return true;
+}
+
+void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
+ const char *Type) const {
+ SrcMgr.PrintMessage(Loc, Msg, Type);
+}
+
+bool AsmParser::EnterIncludeFile(const std::string &Filename) {
+ int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
+ if (NewBuf == -1)
+ return true;
+
+ CurBuffer = NewBuf;
+
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+
+ return false;
+}
+
+const AsmToken &AsmParser::Lex() {
+ const AsmToken *tok = &Lexer.Lex();
+
+ if (tok->is(AsmToken::Eof)) {
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer),
+ ParentIncludeLoc.getPointer());
+ tok = &Lexer.Lex();
+ }
+ }
+
+ if (tok->is(AsmToken::Error))
+ PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error");
+
+ return *tok;
+}
+
+bool AsmParser::Run() {
+ // Create the initial section.
+ //
+ // FIXME: Support -n.
+ // FIXME: Target hook & command line option for initial section.
+ Out.SwitchSection(getMachOSection("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, SectionKind()));
+
+
+ // Prime the lexer.
+ Lex();
+
+ bool HadError = false;
+
+ AsmCond StartingCondState = TheCondState;
+
+ // While we have input, parse each statement.
+ while (Lexer.isNot(AsmToken::Eof)) {
+ // Handle conditional assembly here before calling ParseStatement()
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ // If we have an identifier, handle it as the key symbol.
+ AsmToken ID = getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal = ID.getString();
+
+ if (IDVal == ".if" ||
+ IDVal == ".elseif" ||
+ IDVal == ".else" ||
+ IDVal == ".endif") {
+ if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc))
+ continue;
+ HadError = true;
+ EatToEndOfStatement();
+ continue;
+ }
+ }
+ if (TheCondState.Ignore) {
+ EatToEndOfStatement();
+ continue;
+ }
+
+ if (!ParseStatement()) continue;
+
+ // We had an error, remember it and recover by skipping to the next line.
+ HadError = true;
+ EatToEndOfStatement();
+ }
+
+ if (TheCondState.TheCond != StartingCondState.TheCond ||
+ TheCondState.Ignore != StartingCondState.Ignore)
+ return TokError("unmatched .ifs or .elses");
+
+ if (!HadError)
+ Out.Finish();
+
+ return HadError;
+}
+
+/// ParseConditionalAssemblyDirectives - parse the conditional assembly
+/// directives
+bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive,
+ SMLoc DirectiveLoc) {
+ if (Directive == ".if")
+ return ParseDirectiveIf(DirectiveLoc);
+ if (Directive == ".elseif")
+ return ParseDirectiveElseIf(DirectiveLoc);
+ if (Directive == ".else")
+ return ParseDirectiveElse(DirectiveLoc);
+ if (Directive == ".endif")
+ return ParseDirectiveEndIf(DirectiveLoc);
+ return true;
+}
+
+/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
+void AsmParser::EatToEndOfStatement() {
+ while (Lexer.isNot(AsmToken::EndOfStatement) &&
+ Lexer.isNot(AsmToken::Eof))
+ Lex();
+
+ // Eat EOL.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lex();
+}
+
+
+/// ParseParenExpr - Parse a paren expression and return it.
+/// NOTE: This assumes the leading '(' has already been consumed.
+///
+/// parenexpr ::= expr)
+///
+bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (ParseExpression(Res)) return true;
+ if (Lexer.isNot(AsmToken::RParen))
+ return TokError("expected ')' in parentheses expression");
+ EndLoc = Lexer.getLoc();
+ Lex();
+ return false;
+}
+
+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);
+}
+
+/// ParsePrimaryExpr - Parse a primary expression and return it.
+/// primaryexpr ::= (parenexpr
+/// primaryexpr ::= symbol
+/// primaryexpr ::= number
+/// primaryexpr ::= ~,+,- primaryexpr
+bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ switch (Lexer.getKind()) {
+ default:
+ return TokError("unknown token in expression");
+ case AsmToken::Exclaim:
+ Lex(); // Eat the operator.
+ if (ParsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::CreateLNot(Res, getContext());
+ return false;
+ case AsmToken::String:
+ case AsmToken::Identifier: {
+ // This is a symbol reference.
+ MCSymbol *Sym = CreateSymbol(getTok().getIdentifier());
+ EndLoc = Lexer.getLoc();
+ Lex(); // Eat identifier.
+
+ // If this is an absolute variable reference, substitute it now to preserve
+ // semantics in the face of reassignment.
+ if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) {
+ Res = Sym->getValue();
+ return false;
+ }
+
+ // Otherwise create a symbol ref.
+ Res = MCSymbolRefExpr::Create(Sym, getContext());
+ return false;
+ }
+ case AsmToken::Integer:
+ Res = MCConstantExpr::Create(getTok().getIntVal(), getContext());
+ EndLoc = Lexer.getLoc();
+ Lex(); // Eat token.
+ return false;
+ case AsmToken::LParen:
+ Lex(); // Eat the '('.
+ return ParseParenExpr(Res, EndLoc);
+ case AsmToken::Minus:
+ Lex(); // Eat the operator.
+ if (ParsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::CreateMinus(Res, getContext());
+ return false;
+ case AsmToken::Plus:
+ Lex(); // Eat the operator.
+ if (ParsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::CreatePlus(Res, getContext());
+ return false;
+ case AsmToken::Tilde:
+ Lex(); // Eat the operator.
+ if (ParsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::CreateNot(Res, getContext());
+ return false;
+ }
+}
+
+bool AsmParser::ParseExpression(const MCExpr *&Res) {
+ SMLoc EndLoc;
+ return ParseExpression(Res, EndLoc);
+}
+
+/// ParseExpression - Parse an expression and return it.
+///
+/// expr ::= expr +,- expr -> lowest.
+/// expr ::= expr |,^,&,! expr -> middle.
+/// expr ::= expr *,/,%,<<,>> expr -> highest.
+/// expr ::= primaryexpr
+///
+bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ Res = 0;
+ return ParsePrimaryExpr(Res, EndLoc) ||
+ ParseBinOpRHS(1, Res, EndLoc);
+}
+
+bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (ParseParenExpr(Res, EndLoc))
+ return true;
+
+ return false;
+}
+
+bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
+ const MCExpr *Expr;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Expr))
+ return true;
+
+ if (!Expr->EvaluateAsAbsolute(Res))
+ return Error(StartLoc, "expected absolute expression");
+
+ return false;
+}
+
+static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
+ switch (K) {
+ default:
+ return 0; // not a binop.
+
+ // Lowest Precedence: &&, ||
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
+ return 1;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
+ return 1;
+
+ // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 2;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 2;
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
+ return 2;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
+ return 2;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
+ return 2;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
+ return 2;
+ case AsmToken::Greater:
+ Kind = MCBinaryExpr::GT;
+ return 2;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
+ return 2;
+
+ // Intermediate Precedence: |, &, ^
+ //
+ // FIXME: gas seems to support '!' as an infix operator?
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
+ return 3;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 3;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
+ return 3;
+
+ // Highest Precedence: *, /, %, <<, >>
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
+ return 4;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
+ return 4;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
+ return 4;
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
+ return 4;
+ case AsmToken::GreaterGreater:
+ Kind = MCBinaryExpr::Shr;
+ return 4;
+ }
+}
+
+
+/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
+/// Res contains the LHS of the expression on input.
+bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ while (1) {
+ MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
+ unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
+
+ // If the next token is lower precedence than we are allowed to eat, return
+ // successfully with what we ate already.
+ if (TokPrec < Precedence)
+ return false;
+
+ Lex();
+
+ // Eat the next primary expression.
+ const MCExpr *RHS;
+ if (ParsePrimaryExpr(RHS, EndLoc)) return true;
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ MCBinaryExpr::Opcode Dummy;
+ unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
+ if (TokPrec < NextTokPrec) {
+ if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
+ }
+
+ // Merge LHS and RHS according to operator.
+ Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
+ }
+}
+
+
+
+
+/// ParseStatement:
+/// ::= EndOfStatement
+/// ::= Label* Directive ...Operands... EndOfStatement
+/// ::= Label* Identifier OperandList* EndOfStatement
+bool AsmParser::ParseStatement() {
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ Lex();
+ return false;
+ }
+
+ // Statements always start with an identifier.
+ AsmToken ID = getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal;
+ if (ParseIdentifier(IDVal))
+ return TokError("unexpected token at start of statement");
+
+ // FIXME: Recurse on local labels?
+
+ // See what kind of statement we have.
+ switch (Lexer.getKind()) {
+ case AsmToken::Colon: {
+ // identifier ':' -> Label.
+ Lex();
+
+ // Diagnose attempt to use a variable as a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: This doesn't diagnose assignment to a symbol which has been
+ // implicitly marked as external.
+ MCSymbol *Sym = CreateSymbol(IDVal);
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Emit the label.
+ Out.EmitLabel(Sym);
+
+ return ParseStatement();
+ }
+
+ case AsmToken::Equal:
+ // identifier '=' ... -> assignment statement
+ Lex();
+
+ return ParseAssignment(IDVal);
+
+ default: // Normal instruction or directive.
+ break;
+ }
+
+ // Otherwise, we have a normal instruction or directive.
+ if (IDVal[0] == '.') {
+ // FIXME: This should be driven based on a hash lookup and callback.
+ if (IDVal == ".section")
+ return ParseDirectiveDarwinSection();
+ if (IDVal == ".text")
+ // FIXME: This changes behavior based on the -static flag to the
+ // assembler.
+ return ParseDirectiveSectionSwitch("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
+ if (IDVal == ".const")
+ return ParseDirectiveSectionSwitch("__TEXT", "__const");
+ if (IDVal == ".static_const")
+ return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
+ if (IDVal == ".cstring")
+ return ParseDirectiveSectionSwitch("__TEXT","__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".literal4")
+ return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
+ MCSectionMachO::S_4BYTE_LITERALS,
+ 4);
+ if (IDVal == ".literal8")
+ return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
+ MCSectionMachO::S_8BYTE_LITERALS,
+ 8);
+ if (IDVal == ".literal16")
+ return ParseDirectiveSectionSwitch("__TEXT","__literal16",
+ MCSectionMachO::S_16BYTE_LITERALS,
+ 16);
+ if (IDVal == ".constructor")
+ return ParseDirectiveSectionSwitch("__TEXT","__constructor");
+ if (IDVal == ".destructor")
+ return ParseDirectiveSectionSwitch("__TEXT","__destructor");
+ if (IDVal == ".fvmlib_init0")
+ return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
+ if (IDVal == ".fvmlib_init1")
+ return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
+
+ // FIXME: The assembler manual claims that this has the self modify code
+ // flag, at least on x86-32, but that does not appear to be correct.
+ if (IDVal == ".symbol_stub")
+ return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ // FIXME: Different on PPC and ARM.
+ 0, 16);
+ // FIXME: PowerPC only?
+ if (IDVal == ".picsymbol_stub")
+ return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, 26);
+ if (IDVal == ".data")
+ return ParseDirectiveSectionSwitch("__DATA", "__data");
+ if (IDVal == ".static_data")
+ return ParseDirectiveSectionSwitch("__DATA", "__static_data");
+
+ // FIXME: The section names of these two are misspelled in the assembler
+ // manual.
+ if (IDVal == ".non_lazy_symbol_pointer")
+ return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
+ MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
+ 4);
+ if (IDVal == ".lazy_symbol_pointer")
+ return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
+ MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
+ 4);
+
+ if (IDVal == ".dyld")
+ return ParseDirectiveSectionSwitch("__DATA", "__dyld");
+ if (IDVal == ".mod_init_func")
+ return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
+ MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
+ 4);
+ if (IDVal == ".mod_term_func")
+ return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
+ MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
+ 4);
+ if (IDVal == ".const_data")
+ return ParseDirectiveSectionSwitch("__DATA", "__const");
+
+
+ if (IDVal == ".objc_class")
+ return ParseDirectiveSectionSwitch("__OBJC", "__class",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_meta_class")
+ return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cat_cls_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cat_inst_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_protocol")
+ return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_string_object")
+ return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cls_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_inst_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cls_refs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
+ MCSectionMachO::S_LITERAL_POINTERS,
+ 4);
+ if (IDVal == ".objc_message_refs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
+ MCSectionMachO::S_LITERAL_POINTERS,
+ 4);
+ if (IDVal == ".objc_symbols")
+ return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_category")
+ return ParseDirectiveSectionSwitch("__OBJC", "__category",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_class_vars")
+ return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_instance_vars")
+ return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_module_info")
+ return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_class_names")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_meth_var_types")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_meth_var_names")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_selector_strs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
+ MCSectionMachO::S_CSTRING_LITERALS);
+
+ // Assembler features
+ if (IDVal == ".set")
+ return ParseDirectiveSet();
+
+ // Data directives
+
+ if (IDVal == ".ascii")
+ return ParseDirectiveAscii(false);
+ if (IDVal == ".asciz")
+ return ParseDirectiveAscii(true);
+
+ if (IDVal == ".byte")
+ return ParseDirectiveValue(1);
+ if (IDVal == ".short")
+ return ParseDirectiveValue(2);
+ if (IDVal == ".long")
+ return ParseDirectiveValue(4);
+ if (IDVal == ".quad")
+ return ParseDirectiveValue(8);
+
+ // FIXME: Target hooks for IsPow2.
+ if (IDVal == ".align")
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ if (IDVal == ".align32")
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+ if (IDVal == ".balign")
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
+ if (IDVal == ".balignw")
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
+ if (IDVal == ".balignl")
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
+ if (IDVal == ".p2align")
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ if (IDVal == ".p2alignw")
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
+ if (IDVal == ".p2alignl")
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+
+ if (IDVal == ".org")
+ return ParseDirectiveOrg();
+
+ if (IDVal == ".fill")
+ return ParseDirectiveFill();
+ if (IDVal == ".space")
+ return ParseDirectiveSpace();
+
+ // Symbol attribute directives
+
+ if (IDVal == ".globl" || IDVal == ".global")
+ return ParseDirectiveSymbolAttribute(MCSA_Global);
+ if (IDVal == ".hidden")
+ return ParseDirectiveSymbolAttribute(MCSA_Hidden);
+ if (IDVal == ".indirect_symbol")
+ return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
+ if (IDVal == ".internal")
+ return ParseDirectiveSymbolAttribute(MCSA_Internal);
+ if (IDVal == ".lazy_reference")
+ return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
+ if (IDVal == ".no_dead_strip")
+ return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
+ if (IDVal == ".private_extern")
+ return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
+ if (IDVal == ".protected")
+ return ParseDirectiveSymbolAttribute(MCSA_Protected);
+ if (IDVal == ".reference")
+ return ParseDirectiveSymbolAttribute(MCSA_Reference);
+ if (IDVal == ".weak")
+ return ParseDirectiveSymbolAttribute(MCSA_Weak);
+ if (IDVal == ".weak_definition")
+ return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
+ if (IDVal == ".weak_reference")
+ return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
+
+ if (IDVal == ".comm")
+ return ParseDirectiveComm(/*IsLocal=*/false);
+ if (IDVal == ".lcomm")
+ return ParseDirectiveComm(/*IsLocal=*/true);
+ if (IDVal == ".zerofill")
+ return ParseDirectiveDarwinZerofill();
+ if (IDVal == ".desc")
+ return ParseDirectiveDarwinSymbolDesc();
+ if (IDVal == ".lsym")
+ return ParseDirectiveDarwinLsym();
+
+ if (IDVal == ".subsections_via_symbols")
+ return ParseDirectiveDarwinSubsectionsViaSymbols();
+ if (IDVal == ".abort")
+ return ParseDirectiveAbort();
+ if (IDVal == ".include")
+ return ParseDirectiveInclude();
+ if (IDVal == ".dump")
+ return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsDump=*/true);
+ if (IDVal == ".load")
+ return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsLoad=*/false);
+
+ // Look up the handler in the handler table,
+ bool(AsmParser::*Handler)(StringRef, SMLoc) = DirectiveMap[IDVal];
+ if (Handler)
+ return (this->*Handler)(IDVal, IDLoc);
+
+ // Target hook for parsing target specific directives.
+ if (!getTargetParser().ParseDirective(ID))
+ return false;
+
+ Warning(IDLoc, "ignoring directive for now");
+ EatToEndOfStatement();
+ return false;
+ }
+
+
+ SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
+ if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands))
+ // FIXME: Leaking ParsedOperands on failure.
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ // FIXME: Leaking ParsedOperands on failure.
+ return TokError("unexpected token in argument list");
+
+ // Eat the end of statement marker.
+ Lex();
+
+
+ MCInst Inst;
+
+ bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst);
+
+ // Free any parsed operands.
+ for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
+ delete ParsedOperands[i];
+
+ if (MatchFail) {
+ // FIXME: We should give nicer diagnostics about the exact failure.
+ Error(IDLoc, "unrecognized instruction");
+ return true;
+ }
+
+ // Instruction is good, process it.
+ Out.EmitInstruction(Inst);
+
+ // Skip to end of line for now.
+ return false;
+}
+
+bool AsmParser::ParseAssignment(const StringRef &Name) {
+ // FIXME: Use better location, we should use proper tokens.
+ SMLoc EqualLoc = Lexer.getLoc();
+
+ const MCExpr *Value;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in assignment");
+
+ // Eat the end of statement marker.
+ Lex();
+
+ // Validate that the LHS is allowed to be a variable (either it has not been
+ // used as a symbol, or it is an absolute symbol).
+ MCSymbol *Sym = getContext().LookupSymbol(Name);
+ if (Sym) {
+ // Diagnose assignment to a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: Diagnose assignment to protected identifier (e.g., register name).
+ if (!Sym->isUndefined() && !Sym->isAbsolute())
+ return Error(EqualLoc, "redefinition of '" + Name + "'");
+ else if (!Sym->isVariable())
+ return Error(EqualLoc, "invalid assignment to '" + Name + "'");
+ else if (!isa<MCConstantExpr>(Sym->getValue()))
+ return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
+ Name + "'");
+ } else
+ Sym = CreateSymbol(Name);
+
+ // FIXME: Handle '.'.
+
+ // Do the assignment.
+ Out.EmitAssignment(Sym, Value);
+
+ return false;
+}
+
+/// ParseIdentifier:
+/// ::= identifier
+/// ::= string
+bool AsmParser::ParseIdentifier(StringRef &Res) {
+ if (Lexer.isNot(AsmToken::Identifier) &&
+ Lexer.isNot(AsmToken::String))
+ return true;
+
+ Res = getTok().getIdentifier();
+
+ Lex(); // Consume the identifier token.
+
+ return false;
+}
+
+/// ParseDirectiveSet:
+/// ::= .set identifier ',' expression
+bool AsmParser::ParseDirectiveSet() {
+ StringRef Name;
+
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier after '.set' directive");
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.set'");
+ Lex();
+
+ return ParseAssignment(Name);
+}
+
+/// ParseDirectiveSection:
+/// ::= .section identifier (',' identifier)*
+/// FIXME: This should actually parse out the segment, section, attributes and
+/// sizeof_stub fields.
+bool AsmParser::ParseDirectiveDarwinSection() {
+ SMLoc Loc = Lexer.getLoc();
+
+ StringRef SectionName;
+ if (ParseIdentifier(SectionName))
+ return Error(Loc, "expected identifier after '.section' directive");
+
+ // Verify there is a following comma.
+ if (!Lexer.is(AsmToken::Comma))
+ return TokError("unexpected token in '.section' directive");
+
+ std::string SectionSpec = SectionName;
+ SectionSpec += ",";
+
+ // Add all the tokens until the end of the line, ParseSectionSpecifier will
+ // handle this.
+ StringRef EOL = Lexer.LexUntilEndOfStatement();
+ SectionSpec.append(EOL.begin(), EOL.end());
+
+ Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.section' directive");
+ Lex();
+
+
+ StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ std::string ErrorStr =
+ MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
+ TAA, StubSize);
+
+ if (!ErrorStr.empty())
+ return Error(Loc, ErrorStr.c_str());
+
+ // FIXME: Arch specific.
+ Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
+ SectionKind()));
+ return false;
+}
+
+/// ParseDirectiveSectionSwitch -
+bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
+ const char *Section,
+ unsigned TAA, unsigned Align,
+ unsigned StubSize) {
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ // FIXME: Arch specific.
+ Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
+ SectionKind()));
+
+ // Set the implicit alignment, if any.
+ //
+ // FIXME: This isn't really what 'as' does; I think it just uses the implicit
+ // alignment on the section (e.g., if one manually inserts bytes into the
+ // section, then just issueing the section switch directive will not realign
+ // the section. However, this is arguably more reasonable behavior, and there
+ // is no good reason for someone to intentionally emit incorrectly sized
+ // values into the implicitly aligned sections.
+ if (Align)
+ Out.EmitValueToAlignment(Align, 0, 1, 0);
+
+ return false;
+}
+
+bool AsmParser::ParseEscapedString(std::string &Data) {
+ assert(Lexer.is(AsmToken::String) && "Unexpected current token!");
+
+ Data = "";
+ StringRef Str = getTok().getStringContents();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] != '\\') {
+ Data += Str[i];
+ continue;
+ }
+
+ // Recognize escaped characters. Note that this escape semantics currently
+ // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
+ ++i;
+ if (i == e)
+ return TokError("unexpected backslash at end of string");
+
+ // Recognize octal sequences.
+ if ((unsigned) (Str[i] - '0') <= 7) {
+ // Consume up to three octal characters.
+ unsigned Value = Str[i] - '0';
+
+ if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+
+ if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+ }
+ }
+
+ if (Value > 255)
+ return TokError("invalid octal escape sequence (out of range)");
+
+ Data += (unsigned char) Value;
+ continue;
+ }
+
+ // Otherwise recognize individual escapes.
+ switch (Str[i]) {
+ default:
+ // Just reject invalid escape sequences for now.
+ return TokError("invalid escape sequence (unrecognized character)");
+
+ case 'b': Data += '\b'; break;
+ case 'f': Data += '\f'; break;
+ case 'n': Data += '\n'; break;
+ case 'r': Data += '\r'; break;
+ case 't': Data += '\t'; break;
+ case '"': Data += '"'; break;
+ case '\\': Data += '\\'; break;
+ }
+ }
+
+ return false;
+}
+
+/// ParseDirectiveAscii:
+/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
+bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.ascii' or '.asciz' directive");
+
+ std::string Data;
+ if (ParseEscapedString(Data))
+ return true;
+
+ Out.EmitBytes(Data, DEFAULT_ADDRSPACE);
+ if (ZeroTerminated)
+ Out.EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
+
+ Lex();
+
+ if (Lexer.is(AsmToken::EndOfStatement))
+ break;
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.ascii' or '.asciz' directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+/// ParseDirectiveValue
+/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
+bool AsmParser::ParseDirectiveValue(unsigned Size) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ const MCExpr *Value;
+ SMLoc ATTRIBUTE_UNUSED StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
+ return true;
+
+ Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE);
+
+ if (Lexer.is(AsmToken::EndOfStatement))
+ break;
+
+ // FIXME: Improve diagnostic.
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+/// ParseDirectiveSpace
+/// ::= .space expression [ , expression ]
+bool AsmParser::ParseDirectiveSpace() {
+ int64_t NumBytes;
+ if (ParseAbsoluteExpression(NumBytes))
+ return true;
+
+ int64_t FillExpr = 0;
+ bool HasFillExpr = false;
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.space' directive");
+ Lex();
+
+ if (ParseAbsoluteExpression(FillExpr))
+ return true;
+
+ HasFillExpr = true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.space' directive");
+ }
+
+ Lex();
+
+ if (NumBytes <= 0)
+ return TokError("invalid number of bytes in '.space' directive");
+
+ // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
+ Out.EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
+
+ return false;
+}
+
+/// ParseDirectiveFill
+/// ::= .fill expression , expression , expression
+bool AsmParser::ParseDirectiveFill() {
+ int64_t NumValues;
+ if (ParseAbsoluteExpression(NumValues))
+ return true;
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.fill' directive");
+ Lex();
+
+ int64_t FillSize;
+ if (ParseAbsoluteExpression(FillSize))
+ return true;
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.fill' directive");
+ Lex();
+
+ int64_t FillExpr;
+ if (ParseAbsoluteExpression(FillExpr))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.fill' directive");
+
+ Lex();
+
+ if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
+ return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
+
+ for (uint64_t i = 0, e = NumValues; i != e; ++i)
+ Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize,
+ DEFAULT_ADDRSPACE);
+
+ return false;
+}
+
+/// ParseDirectiveOrg
+/// ::= .org expression [ , expression ]
+bool AsmParser::ParseDirectiveOrg() {
+ const MCExpr *Offset;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Offset))
+ return true;
+
+ // Parse optional fill expression.
+ int64_t FillExpr = 0;
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.org' directive");
+ Lex();
+
+ if (ParseAbsoluteExpression(FillExpr))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.org' directive");
+ }
+
+ Lex();
+
+ // FIXME: Only limited forms of relocatable expressions are accepted here, it
+ // has to be relative to the current section.
+ Out.EmitValueToOffset(Offset, FillExpr);
+
+ return false;
+}
+
+/// ParseDirectiveAlign
+/// ::= {.align, ...} expression [ , expression [ , expression ]]
+bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+ SMLoc AlignmentLoc = Lexer.getLoc();
+ int64_t Alignment;
+ if (ParseAbsoluteExpression(Alignment))
+ return true;
+
+ SMLoc MaxBytesLoc;
+ bool HasFillExpr = false;
+ int64_t FillExpr = 0;
+ int64_t MaxBytesToFill = 0;
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ // The fill expression can be omitted while specifying a maximum number of
+ // alignment bytes, e.g:
+ // .align 3,,4
+ if (Lexer.isNot(AsmToken::Comma)) {
+ HasFillExpr = true;
+ if (ParseAbsoluteExpression(FillExpr))
+ return true;
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ MaxBytesLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(MaxBytesToFill))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ }
+ }
+
+ Lex();
+
+ if (!HasFillExpr) {
+ // FIXME: Sometimes fill with nop.
+ FillExpr = 0;
+ }
+
+ // Compute alignment in bytes.
+ if (IsPow2) {
+ // FIXME: Diagnose overflow.
+ if (Alignment >= 32) {
+ Error(AlignmentLoc, "invalid alignment value");
+ Alignment = 31;
+ }
+
+ Alignment = 1ULL << Alignment;
+ }
+
+ // Diagnose non-sensical max bytes to align.
+ if (MaxBytesLoc.isValid()) {
+ if (MaxBytesToFill < 1) {
+ Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
+ "many bytes, ignoring maximum bytes expression");
+ MaxBytesToFill = 0;
+ }
+
+ if (MaxBytesToFill >= Alignment) {
+ Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
+ "has no effect");
+ MaxBytesToFill = 0;
+ }
+ }
+
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
+ Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
+
+ return false;
+}
+
+/// ParseDirectiveSymbolAttribute
+/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
+bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ StringRef Name;
+
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ Out.EmitSymbolAttribute(Sym, Attr);
+
+ if (Lexer.is(AsmToken::EndOfStatement))
+ break;
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+/// ParseDirectiveDarwinSymbolDesc
+/// ::= .desc identifier , expression
+bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.desc' directive");
+ Lex();
+
+ SMLoc DescLoc = Lexer.getLoc();
+ int64_t DescValue;
+ if (ParseAbsoluteExpression(DescValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.desc' directive");
+
+ Lex();
+
+ // Set the n_desc field of this Symbol to this DescValue
+ Out.EmitSymbolDesc(Sym, DescValue);
+
+ return false;
+}
+
+/// ParseDirectiveComm
+/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool AsmParser::ParseDirectiveComm(bool IsLocal) {
+ SMLoc IDLoc = Lexer.getLoc();
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (Lexer.is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Pow2Alignment))
+ return true;
+
+ // If this target takes alignments in bytes (not log) validate and convert.
+ if (Lexer.getMAI().getAlignmentIsInBytes()) {
+ if (!isPowerOf2_64(Pow2Alignment))
+ return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
+ Pow2Alignment = Log2_64(Pow2Alignment);
+ }
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.comm' or '.lcomm' directive");
+
+ Lex();
+
+ // NOTE: a size of zero for a .comm should create a undefined symbol
+ // but a size of .lcomm creates a bss symbol of size zero.
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
+ "be less than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assember
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
+ "alignment, can't be less than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // '.lcomm' is equivalent to '.zerofill'.
+ // Create the Symbol as a common or local common with Size and Pow2Alignment
+ if (IsLocal) {
+ Out.EmitZerofill(getMachOSection("__DATA", "__bss",
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()),
+ Sym, Size, 1 << Pow2Alignment);
+ return false;
+ }
+
+ Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+}
+
+/// ParseDirectiveDarwinZerofill
+/// ::= .zerofill segname , sectname [, identifier , size_expression [
+/// , align_expression ]]
+bool AsmParser::ParseDirectiveDarwinZerofill() {
+ // FIXME: Handle quoted names here.
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected segment name after '.zerofill' directive");
+ StringRef Segment = getTok().getString();
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected section name after comma in '.zerofill' "
+ "directive");
+ StringRef Section = getTok().getString();
+ Lex();
+
+ // If this is the end of the line all that was wanted was to create the
+ // the section but with no symbol.
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ // Create the zerofill section but no symbol
+ Out.EmitZerofill(getMachOSection(Segment, Section,
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()));
+ return false;
+ }
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+
+ // handle the identifier as the key symbol.
+ SMLoc IDLoc = Lexer.getLoc();
+ MCSymbol *Sym = CreateSymbol(getTok().getString());
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (Lexer.is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.zerofill' directive");
+
+ Lex();
+
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
+ "than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assember
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
+ "can't be less than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the zerofill Symbol with Size and Pow2Alignment
+ //
+ // FIXME: Arch specific.
+ Out.EmitZerofill(getMachOSection(Segment, Section,
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()),
+ Sym, Size, 1 << Pow2Alignment);
+
+ return false;
+}
+
+/// ParseDirectiveDarwinSubsectionsViaSymbols
+/// ::= .subsections_via_symbols
+bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() {
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.subsections_via_symbols' directive");
+
+ Lex();
+
+ Out.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
+
+ return false;
+}
+
+/// ParseDirectiveAbort
+/// ::= .abort [ "abort_string" ]
+bool AsmParser::ParseDirectiveAbort() {
+ // FIXME: Use loc from directive.
+ SMLoc Loc = Lexer.getLoc();
+
+ StringRef Str = "";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.abort' directive");
+
+ Str = getTok().getString();
+
+ Lex();
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.abort' directive");
+
+ Lex();
+
+ // FIXME: Handle here.
+ if (Str.empty())
+ Error(Loc, ".abort detected. Assembly stopping.");
+ else
+ Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
+
+ return false;
+}
+
+/// ParseDirectiveLsym
+/// ::= .lsym identifier , expression
+bool AsmParser::ParseDirectiveDarwinLsym() {
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.lsym' directive");
+ Lex();
+
+ const MCExpr *Value;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.lsym' directive");
+
+ Lex();
+
+ // We don't currently support this directive.
+ //
+ // FIXME: Diagnostic location!
+ (void) Sym;
+ return TokError("directive '.lsym' is unsupported");
+}
+
+/// ParseDirectiveInclude
+/// ::= .include "filename"
+bool AsmParser::ParseDirectiveInclude() {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.include' directive");
+
+ std::string Filename = getTok().getString();
+ SMLoc IncludeLoc = Lexer.getLoc();
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.include' directive");
+
+ // Strip the quotes.
+ Filename = Filename.substr(1, Filename.size()-2);
+
+ // Attempt to switch the lexer to the included file before consuming the end
+ // of statement to avoid losing it when we switch.
+ if (EnterIncludeFile(Filename)) {
+ PrintMessage(IncludeLoc,
+ "Could not find include file '" + Filename + "'",
+ "error");
+ return true;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveDarwinDumpOrLoad
+/// ::= ( .dump | .load ) "filename"
+bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.dump' or '.load' directive");
+
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.dump' or '.load' directive");
+
+ Lex();
+
+ // FIXME: If/when .dump and .load are implemented they will be done in the
+ // the assembly parser and not have any need for an MCStreamer API.
+ if (IsDump)
+ Warning(IDLoc, "ignoring directive .dump for now");
+ else
+ Warning(IDLoc, "ignoring directive .load for now");
+
+ return false;
+}
+
+/// ParseDirectiveIf
+/// ::= .if expression
+bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .if directive
+ Lex();
+
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if(TheCondState.Ignore) {
+ EatToEndOfStatement();
+ }
+ else {
+ int64_t ExprValue;
+ if (ParseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.if' directive");
+
+ Lex();
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveElseIf
+/// ::= .elseif expression
+bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
+ " an .elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ // Consume the identifier that was the .elseif directive
+ Lex();
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ EatToEndOfStatement();
+ }
+ else {
+ int64_t ExprValue;
+ if (ParseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.elseif' directive");
+
+ Lex();
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveElse
+/// ::= .else
+bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .else directive
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.else' directive");
+
+ Lex();
+
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
+ ".elseif");
+ TheCondState.TheCond = AsmCond::ElseCond;
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet)
+ TheCondState.Ignore = true;
+ else
+ TheCondState.Ignore = false;
+
+ return false;
+}
+
+/// ParseDirectiveEndIf
+/// ::= .endif
+bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .endif directive
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.endif' directive");
+
+ Lex();
+
+ if ((TheCondState.TheCond == AsmCond::NoCond) ||
+ TheCondStack.empty())
+ Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
+ ".else");
+ if (!TheCondStack.empty()) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ return false;
+}
+
+/// ParseDirectiveFile
+/// ::= .file [number] string
+bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ if (Lexer.is(AsmToken::Integer)) {
+ FileNumber = getTok().getIntVal();
+ Lex();
+
+ if (FileNumber < 1)
+ return TokError("file number less than one");
+ }
+
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("unexpected token in '.file' directive");
+
+ StringRef ATTRIBUTE_UNUSED FileName = getTok().getString();
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ // FIXME: Do something with the .file.
+
+ return false;
+}
+
+/// ParseDirectiveLine
+/// ::= .line [number]
+bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.line' directive");
+
+ int64_t LineNumber = getTok().getIntVal();
+ (void) LineNumber;
+ Lex();
+
+ // FIXME: Do something with the .line.
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ return false;
+}
+
+
+/// ParseDirectiveLoc
+/// ::= .loc number [number [number]]
+bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ // FIXME: What are these fields?
+ int64_t FileNumber = getTok().getIntVal();
+ (void) FileNumber;
+ // FIXME: Validate file.
+
+ Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ int64_t Param2 = getTok().getIntVal();
+ (void) Param2;
+ Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ int64_t Param3 = getTok().getIntVal();
+ (void) Param3;
+ Lex();
+
+ // FIXME: Do something with the .loc.
+ }
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ return false;
+}
+
diff --git a/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt
new file mode 100644
index 0000000..a5c0818
--- /dev/null
+++ b/lib/MC/MCParser/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_llvm_library(LLVMMCParser
+ AsmLexer.cpp
+ AsmParser.cpp
+ MCAsmLexer.cpp
+ MCAsmParser.cpp
+ TargetAsmParser.cpp
+ )
diff --git a/lib/MC/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp
index 1e34ed6..e5b2955 100644
--- a/lib/MC/MCAsmLexer.cpp
+++ b/lib/MC/MCParser/MCAsmLexer.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;
diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp
new file mode 100644
index 0000000..b8c2054
--- /dev/null
+++ b/lib/MC/MCParser/MCAsmParser.cpp
@@ -0,0 +1,35 @@
+//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/Support/SourceMgr.h"
+using namespace llvm;
+
+MCAsmParser::MCAsmParser() {
+}
+
+MCAsmParser::~MCAsmParser() {
+}
+
+const AsmToken &MCAsmParser::getTok() {
+ return getLexer().getTok();
+}
+
+bool MCAsmParser::ParseExpression(const MCExpr *&Res) {
+ SMLoc L;
+ return ParseExpression(Res, L);
+}
+
+/// getStartLoc - Get the location of the first token of this operand.
+SMLoc MCParsedAsmOperand::getStartLoc() const { return SMLoc(); }
+SMLoc MCParsedAsmOperand::getEndLoc() const { return SMLoc(); }
+
+
diff --git a/lib/MC/MCParser/Makefile b/lib/MC/MCParser/Makefile
new file mode 100644
index 0000000..e4eb483
--- /dev/null
+++ b/lib/MC/MCParser/Makefile
@@ -0,0 +1,16 @@
+##===- lib/MC/MCParser/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMMCParser
+BUILD_ARCHIVE := 1
+CXXFLAGS = -fno-rtti
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/MC/TargetAsmParser.cpp b/lib/MC/MCParser/TargetAsmParser.cpp
index 05760c9..05760c9 100644
--- a/lib/MC/TargetAsmParser.cpp
+++ b/lib/MC/MCParser/TargetAsmParser.cpp
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index 4d520ec..ebfe269 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -22,14 +22,12 @@ Create(StringRef Section, unsigned Type, unsigned Flags,
// ShouldOmitSectionDirective - Decides whether a '.section' directive
// should be printed before the section name
-bool MCSectionELF::ShouldOmitSectionDirective(const char *Name,
+bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
const MCAsmInfo &MAI) const {
// FIXME: Does .section .bss/.data/.text work everywhere??
- if (strcmp(Name, ".text") == 0 ||
- strcmp(Name, ".data") == 0 ||
- (strcmp(Name, ".bss") == 0 &&
- !MAI.usesELFSectionDirectiveForBSS()))
+ if (Name == ".text" || Name == ".data" ||
+ (Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS()))
return true;
return false;
@@ -46,7 +44,7 @@ bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const {
void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
raw_ostream &OS) const {
- if (ShouldOmitSectionDirective(SectionName.c_str(), MAI)) {
+ if (ShouldOmitSectionDirective(SectionName, MAI)) {
OS << '\t' << getSectionName() << '\n';
return;
}
@@ -128,7 +126,7 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
// header index.
bool MCSectionELF::HasCommonSymbols() const {
- if (strncmp(SectionName.c_str(), ".gnu.linkonce.", 14) == 0)
+ if (StringRef(SectionName).startswith(".gnu.linkonce."))
return true;
return false;
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 8a6dcda..15b3079 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -8,7 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h"
-
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) {
@@ -16,3 +17,25 @@ MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) {
MCStreamer::~MCStreamer() {
}
+
+raw_ostream &MCStreamer::GetCommentOS() {
+ // By default, discard comments.
+ return nulls();
+}
+
+
+/// EmitIntValue - Special case of EmitValue that avoids the client having to
+/// pass in a MCExpr for constant integers.
+void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
+ unsigned AddrSpace) {
+ EmitValue(MCConstantExpr::Create(Value, 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,
+ unsigned AddrSpace) {
+ const MCExpr *E = MCConstantExpr::Create(FillValue, getContext());
+ for (uint64_t i = 0, e = NumBytes; i != e; ++i)
+ EmitValue(E, 1, AddrSpace);
+}
diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp
index 265d06c..3fb1233 100644
--- a/lib/MC/MCSymbol.cpp
+++ b/lib/MC/MCSymbol.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -26,24 +25,11 @@ static bool isAcceptableChar(char C) {
return true;
}
-static char HexDigit(int V) {
- return V < 10 ? V+'0' : V+'A'-10;
-}
-
-static void MangleLetter(raw_ostream &OS, unsigned char C) {
- OS << '_' << HexDigit(C >> 4) << HexDigit(C & 15) << '_';
-}
-
-/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes
-/// for this assembler.
-static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) {
+/// NameNeedsQuoting - Return true if the identifier \arg Str needs quotes to be
+/// syntactically correct.
+static bool NameNeedsQuoting(StringRef Str) {
assert(!Str.empty() && "Cannot create an empty MCSymbol");
- // If the first character is a number and the target does not allow this, we
- // need quotes.
- if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9')
- return true;
-
// If any of the characters in the string is an unacceptable character, force
// quotes.
for (unsigned i = 0, e = Str.size(); i != e; ++i)
@@ -52,63 +38,18 @@ static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) {
return false;
}
-/// printMangledName - Print the specified string in mangled form if it uses
-/// any unusual characters.
-void MCSymbol::printMangledName(StringRef Str, raw_ostream &OS,
- const MCAsmInfo *MAI) {
- // The first character is not allowed to be a number unless the target
- // explicitly allows it.
- if ((MAI == 0 || !MAI->doesAllowNameToStartWithDigit()) &&
- Str[0] >= '0' && Str[0] <= '9') {
- MangleLetter(OS, Str[0]);
- Str = Str.substr(1);
- }
-
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (!isAcceptableChar(Str[i]))
- MangleLetter(OS, Str[i]);
- else
- OS << Str[i];
- }
-}
-
-/// PrintMangledQuotedName - On systems that support quoted symbols, we still
-/// have to escape some (obscure) characters like " and \n which would break the
-/// assembler's lexing.
-static void PrintMangledQuotedName(raw_ostream &OS, StringRef Str) {
- OS << '"';
-
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (Str[i] == '"')
- OS << "_QQ_";
- else if (Str[i] == '\n')
- OS << "_NL_";
- else
- OS << Str[i];
- }
- OS << '"';
-}
-
-
-void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
- if (MAI == 0 || !NameNeedsEscaping(getName(), *MAI)) {
+void MCSymbol::print(raw_ostream &OS) const {
+ // The name for this MCSymbol is required to be a valid target name. However,
+ // some targets support quoting names with funny characters. If the name
+ // contains a funny character, then print it quoted.
+ if (!NameNeedsQuoting(getName())) {
OS << getName();
return;
}
-
- // On systems that do not allow quoted names, print with mangling.
- if (!MAI->doesAllowQuotesInName())
- return printMangledName(getName(), OS, MAI);
-
- // If the string contains a double quote or newline, we still have to mangle
- // it.
- if (getName().find('"') != std::string::npos ||
- getName().find('\n') != std::string::npos)
- return PrintMangledQuotedName(OS, getName());
OS << '"' << getName() << '"';
}
void MCSymbol::dump() const {
- print(dbgs(), 0);
+ print(dbgs());
}
diff --git a/lib/MC/MCValue.cpp b/lib/MC/MCValue.cpp
index c1222ec..043a49d 100644
--- a/lib/MC/MCValue.cpp
+++ b/lib/MC/MCValue.cpp
@@ -19,12 +19,10 @@ void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
return;
}
- getSymA()->print(OS, MAI);
+ OS << *getSymA();
- if (getSymB()) {
- OS << " - ";
- getSymB()->print(OS, MAI);
- }
+ if (getSymB())
+ OS << " - " << *getSymB();
if (getConstant())
OS << " + " << getConstant();
diff --git a/lib/MC/Makefile b/lib/MC/Makefile
index 314a5b1..371776f 100644
--- a/lib/MC/Makefile
+++ b/lib/MC/Makefile
@@ -10,6 +10,8 @@
LEVEL = ../..
LIBRARYNAME = LLVMMC
BUILD_ARCHIVE := 1
+PARALLEL_DIRS := MCParser
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp
index a035771..82b4b8c 100644
--- a/lib/Support/Debug.cpp
+++ b/lib/Support/Debug.cpp
@@ -115,9 +115,9 @@ raw_ostream &llvm::dbgs() {
#else
// Avoid "has no symbols" warning.
namespace llvm {
- /// dbgs - Return dbgs().
+ /// dbgs - Return errs().
raw_ostream &dbgs() {
- return dbgs();
+ return errs();
}
}
diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp
index 7dd42f4..bdc637a 100644
--- a/lib/Support/SourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -192,18 +192,21 @@ void SMDiagnostic::Print(const char *ProgName, raw_ostream &S) {
if (ProgName && ProgName[0])
S << ProgName << ": ";
- if (Filename == "-")
- S << "<stdin>";
- else
- S << Filename;
+ if (!Filename.empty()) {
+ if (Filename == "-")
+ S << "<stdin>";
+ else
+ S << Filename;
- if (LineNo != -1) {
- S << ':' << LineNo;
- if (ColumnNo != -1)
- S << ':' << (ColumnNo+1);
+ if (LineNo != -1) {
+ S << ':' << LineNo;
+ if (ColumnNo != -1)
+ S << ':' << (ColumnNo+1);
+ }
+ S << ": ";
}
- S << ": " << Message << '\n';
+ S << Message << '\n';
if (LineNo != -1 && ColumnNo != -1 && ShowLine) {
S << LineContents << '\n';
diff --git a/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp
index 785e0ec..eb2fa08 100644
--- a/lib/Support/StringExtras.cpp
+++ b/lib/Support/StringExtras.cpp
@@ -39,13 +39,11 @@ std::pair<StringRef, StringRef> llvm::getToken(StringRef Source,
StringRef Delimiters) {
// Figure out where the token starts.
StringRef::size_type Start = Source.find_first_not_of(Delimiters);
- if (Start == StringRef::npos) Start = Source.size();
// Find the next occurrence of the delimiter.
StringRef::size_type End = Source.find_first_of(Delimiters, Start);
- if (End == StringRef::npos) End = Source.size();
- return std::make_pair(Source.substr(Start, End), Source.substr(End));
+ return std::make_pair(Source.slice(Start, End), Source.substr(End));
}
/// SplitString - Split up the specified string according to the specified
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index a820210..10d7ec0 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -562,6 +562,17 @@ raw_svector_ostream::~raw_svector_ostream() {
flush();
}
+/// resync - This is called when the SmallVector we're appending to is changed
+/// outside of the raw_svector_ostream's control. It is only safe to do this
+/// if the raw_svector_ostream has previously been flushed.
+void raw_svector_ostream::resync() {
+ assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector");
+
+ if (OS.capacity() - OS.size() < 64)
+ OS.reserve(OS.capacity() * 2);
+ SetBuffer(OS.end(), OS.capacity() - OS.size());
+}
+
void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
assert(Ptr == OS.end() && OS.size() + Size <= OS.capacity() &&
"Invalid write_impl() call!");
diff --git a/lib/System/Host.cpp b/lib/System/Host.cpp
index 79897e4..e7193db 100644
--- a/lib/System/Host.cpp
+++ b/lib/System/Host.cpp
@@ -299,3 +299,7 @@ std::string sys::getHostCPUName() {
return "generic";
}
#endif
+
+bool sys::getHostCPUFeatures(StringMap<bool> &Features){
+ return false;
+}
diff --git a/lib/System/Unix/TimeValue.inc b/lib/System/Unix/TimeValue.inc
index 1ae8c71..d8cc8f5 100644
--- a/lib/System/Unix/TimeValue.inc
+++ b/lib/System/Unix/TimeValue.inc
@@ -48,7 +48,7 @@ TimeValue TimeValue::now() {
}
return TimeValue(
- static_cast<TimeValue::SecondsType>( the_time.tv_sec ),
+ static_cast<TimeValue::SecondsType>( the_time.tv_sec + PosixZeroTime.seconds_ ),
static_cast<TimeValue::NanoSecondsType>( the_time.tv_usec *
NANOSECONDS_PER_MICROSECOND ) );
}
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 969c4a4..fd46a4a 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -715,7 +715,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!");
// FIXME: Neon instructions should support predicates
if (Align >= 16
- && (getRegisterInfo().needsStackRealignment(MF))) {
+ && (getRegisterInfo().canRealignStack(MF))) {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64))
.addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
.addMemOperand(MMO)
@@ -760,7 +760,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
RC == ARM::QPR_VFP2RegisterClass ||
RC == ARM::QPR_8RegisterClass) && "Unknown regclass!");
if (Align >= 16
- && (getRegisterInfo().needsStackRealignment(MF))) {
+ && (getRegisterInfo().canRealignStack(MF))) {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg)
.addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
.addMemOperand(MMO));
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index f1b6e1d..ba9e044 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -484,6 +484,14 @@ bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
MFI->isFrameAddressTaken());
}
+bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ return (RealignStack &&
+ !AFI->isThumb1OnlyFunction() &&
+ !MFI->hasVarSizedObjects());
+}
+
bool ARMBaseRegisterInfo::
needsStackRealignment(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h
index 2788d07..f5ca25c 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.h
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.h
@@ -96,6 +96,7 @@ public:
bool hasFP(const MachineFunction &MF) const;
+ bool canRealignStack(const MachineFunction &MF) const;
bool needsStackRealignment(const MachineFunction &MF) const;
bool cannotEliminateFrame(const MachineFunction &MF) const;
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 14a45b3..a260050 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -1296,12 +1296,12 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Ops.push_back(Chain);
if (!IsLoad)
- return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7);
+ return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+8);
std::vector<EVT> ResTys(NumVecs, RegVT);
ResTys.push_back(MVT::Other);
SDNode *VLdLn =
- CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+7);
+ CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+8);
// For a 64-bit vector load to D registers, nothing more needs to be done.
if (is64BitVector)
return VLdLn;
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 7b62c00..76c6a27 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -340,7 +340,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
// ARM does not have ROTL.
setOperationAction(ISD::ROTL, MVT::i32, Expand);
- setOperationAction(ISD::CTTZ, MVT::i32, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i32, Custom);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only())
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
@@ -387,7 +387,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only())
- // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR iff target supports vfp2.
+ // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR
+ // iff target supports vfp2.
setOperationAction(ISD::BIT_CONVERT, MVT::i64, Custom);
// We want to custom lower some of our intrinsics.
@@ -482,6 +483,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
case ARMISD::CMOV: return "ARMISD::CMOV";
case ARMISD::CNEG: return "ARMISD::CNEG";
+ case ARMISD::RBIT: return "ARMISD::RBIT";
+
case ARMISD::FTOSI: return "ARMISD::FTOSI";
case ARMISD::FTOUI: return "ARMISD::FTOUI";
case ARMISD::SITOF: return "ARMISD::SITOF";
@@ -2231,6 +2234,18 @@ SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) {
return DAG.getMergeValues(Ops, 2, dl);
}
+static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG,
+ const ARMSubtarget *ST) {
+ EVT VT = N->getValueType(0);
+ DebugLoc dl = N->getDebugLoc();
+
+ if (!ST->hasV6T2Ops())
+ return SDValue();
+
+ SDValue rbit = DAG.getNode(ARMISD::RBIT, dl, VT, N->getOperand(0));
+ return DAG.getNode(ISD::CTLZ, dl, VT, rbit);
+}
+
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG,
const ARMSubtarget *ST) {
EVT VT = N->getValueType(0);
@@ -3016,6 +3031,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG);
case ISD::SRL_PARTS:
case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG);
+ case ISD::CTTZ: return LowerCTTZ(Op.getNode(), DAG, Subtarget);
case ISD::VSETCC: return LowerVSETCC(Op, DAG);
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
@@ -3516,7 +3532,8 @@ static SDValue PerformSUBCombine(SDNode *N,
return SDValue();
}
-/// PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
+/// PerformVMOVRRDCombine - Target-specific dag combine xforms for
+/// ARMISD::VMOVRRD.
static SDValue PerformVMOVRRDCombine(SDNode *N,
TargetLowering::DAGCombinerInfo &DCI) {
// fmrrd(fmdrr x, y) -> x,y
diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index e1b3348..cd9c027 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/lib/Target/ARM/ARMISelLowering.h
@@ -53,6 +53,8 @@ namespace llvm {
CMOV, // ARM conditional move instructions.
CNEG, // ARM conditional negate instructions.
+ RBIT, // ARM bitreverse instruction
+
FTOSI, // FP to sint within a FP register.
FTOUI, // FP to uint within a FP register.
SITOF, // sint to FP within a FP register.
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index f67e74a..af508ee 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -107,6 +107,8 @@ def ARMMemBarrierV6 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV6,
def ARMSyncBarrierV6 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV6,
[SDNPHasChain]>;
+def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
+
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
@@ -1455,6 +1457,15 @@ def CLZ : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
let Inst{19-16} = 0b1111;
}
+def RBIT : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
+ "rbit", "\t$dst, $src",
+ [(set GPR:$dst, (ARMrbit GPR:$src))]>,
+ Requires<[IsARM, HasV6T2]> {
+ let Inst{7-4} = 0b0011;
+ let Inst{11-8} = 0b1111;
+ let Inst{19-16} = 0b1111;
+}
+
def REV : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
"rev", "\t$dst, $src",
[(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> {
@@ -1528,8 +1539,10 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000),
defm CMP : AI1_cmp_irs<0b1010, "cmp",
BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
-defm CMN : AI1_cmp_irs<0b1011, "cmn",
- BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
+//FIXME: Disable CMN, as CCodes are backwards from compare expectations
+// Compare-to-zero still works out, just not the relationals
+//defm CMN : AI1_cmp_irs<0b1011, "cmn",
+// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
// Note that TST/TEQ don't set all the same flags that CMP does!
defm TST : AI1_cmp_irs<0b1000, "tst",
@@ -1542,11 +1555,11 @@ defm CMPz : AI1_cmp_irs<0b1010, "cmp",
defm CMNz : AI1_cmp_irs<0b1011, "cmn",
BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
-def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
- (CMNri GPR:$src, so_imm_neg:$imm)>;
+//def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
+// (CMNri GPR:$src, so_imm_neg:$imm)>;
def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm),
- (CMNri GPR:$src, so_imm_neg:$imm)>;
+ (CMNzri GPR:$src, so_imm_neg:$imm)>;
// Conditional moves
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 61b7705..cd063bf 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -197,12 +197,12 @@ let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
class VLD2D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b1000,op7_4, (outs DPR:$dst1, DPR:$dst2),
(ins addrmode6:$addr), IIC_VLD2,
- OpcodeStr, Dt, "\\{$dst1,$dst2\\}, $addr", "", []>;
+ OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []>;
class VLD2Q<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b0011,op7_4,
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4),
(ins addrmode6:$addr), IIC_VLD2,
- OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr",
+ OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
"", []>;
def VLD2d8 : VLD2D<0b0000, "vld2", "8">;
@@ -210,7 +210,7 @@ def VLD2d16 : VLD2D<0b0100, "vld2", "16">;
def VLD2d32 : VLD2D<0b1000, "vld2", "32">;
def VLD2d64 : NLdSt<0,0b10,0b1010,0b1100, (outs DPR:$dst1, DPR:$dst2),
(ins addrmode6:$addr), IIC_VLD1,
- "vld1", "64", "\\{$dst1,$dst2\\}, $addr", "", []>;
+ "vld1", "64", "\\{$dst1, $dst2\\}, $addr", "", []>;
def VLD2q8 : VLD2Q<0b0000, "vld2", "8">;
def VLD2q16 : VLD2Q<0b0100, "vld2", "16">;
@@ -220,11 +220,11 @@ def VLD2q32 : VLD2Q<0b1000, "vld2", "32">;
class VLD3D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b0100,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3),
(ins addrmode6:$addr), IIC_VLD3,
- OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>;
+ OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr", "", []>;
class VLD3WB<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b0101,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, GPR:$wb),
(ins addrmode6:$addr), IIC_VLD3,
- OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr",
+ OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr",
"$addr.addr = $wb", []>;
def VLD3d8 : VLD3D<0b0000, "vld3", "8">;
@@ -233,7 +233,7 @@ def VLD3d32 : VLD3D<0b1000, "vld3", "32">;
def VLD3d64 : NLdSt<0,0b10,0b0110,0b1100,
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3),
(ins addrmode6:$addr), IIC_VLD1,
- "vld1", "64", "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>;
+ "vld1", "64", "\\{$dst1, $dst2, $dst3\\}, $addr", "", []>;
// vld3 to double-spaced even registers.
def VLD3q8a : VLD3WB<0b0000, "vld3", "8">;
@@ -250,13 +250,13 @@ class VLD4D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b0000,op7_4,
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4),
(ins addrmode6:$addr), IIC_VLD4,
- OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr",
+ OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
"", []>;
class VLD4WB<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b10,0b0001,op7_4,
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb),
(ins addrmode6:$addr), IIC_VLD4,
- OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr",
+ OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
"$addr.addr = $wb", []>;
def VLD4d8 : VLD4D<0b0000, "vld4", "8">;
@@ -265,7 +265,8 @@ def VLD4d32 : VLD4D<0b1000, "vld4", "32">;
def VLD4d64 : NLdSt<0,0b10,0b0010,0b1100,
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4),
(ins addrmode6:$addr), IIC_VLD1,
- "vld1", "64", "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", "", []>;
+ "vld1", "64", "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
+ "", []>;
// vld4 to double-spaced even registers.
def VLD4q8a : VLD4WB<0b0000, "vld4", "8">;
@@ -285,7 +286,7 @@ class VLD2LN<bits<4> op11_8, string OpcodeStr, string Dt>
: NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane),
IIC_VLD2,
- OpcodeStr, Dt, "\\{$dst1[$lane],$dst2[$lane]\\}, $addr",
+ OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane]\\}, $addr",
"$src1 = $dst1, $src2 = $dst2", []>;
// vld2 to single-spaced registers.
@@ -319,7 +320,7 @@ class VLD3LN<bits<4> op11_8, string OpcodeStr, string Dt>
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3,
nohash_imm:$lane), IIC_VLD3,
OpcodeStr, Dt,
- "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane]\\}, $addr",
+ "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane]\\}, $addr",
"$src1 = $dst1, $src2 = $dst2, $src3 = $dst3", []>;
// vld3 to single-spaced registers.
@@ -356,7 +357,7 @@ class VLD4LN<bits<4> op11_8, string OpcodeStr, string Dt>
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4,
nohash_imm:$lane), IIC_VLD4,
OpcodeStr, Dt,
- "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane],$dst4[$lane]\\}, $addr",
+ "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $addr",
"$src1 = $dst1, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []>;
// vld4 to single-spaced registers.
@@ -423,12 +424,12 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in {
class VST2D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b1000,op7_4, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2\\}, $addr", "", []>;
+ OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []>;
class VST2Q<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b0011,op7_4, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4),
IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr",
+ OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr",
"", []>;
def VST2d8 : VST2D<0b0000, "vst2", "8">;
@@ -436,7 +437,7 @@ def VST2d16 : VST2D<0b0100, "vst2", "16">;
def VST2d32 : VST2D<0b1000, "vst2", "32">;
def VST2d64 : NLdSt<0,0b00,0b1010,0b1100, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST,
- "vst1", "64", "\\{$src1,$src2\\}, $addr", "", []>;
+ "vst1", "64", "\\{$src1, $src2\\}, $addr", "", []>;
def VST2q8 : VST2Q<0b0000, "vst2", "8">;
def VST2q16 : VST2Q<0b0100, "vst2", "16">;
@@ -446,11 +447,11 @@ def VST2q32 : VST2Q<0b1000, "vst2", "32">;
class VST3D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b0100,op7_4, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr", "", []>;
+ OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr", "", []>;
class VST3WB<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b0101,op7_4, (outs GPR:$wb),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr",
+ OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr",
"$addr.addr = $wb", []>;
def VST3d8 : VST3D<0b0000, "vst3", "8">;
@@ -459,7 +460,7 @@ def VST3d32 : VST3D<0b1000, "vst3", "32">;
def VST3d64 : NLdSt<0,0b00,0b0110,0b1100, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3),
IIC_VST,
- "vst1", "64", "\\{$src1,$src2,$src3\\}, $addr", "", []>;
+ "vst1", "64", "\\{$src1, $src2, $src3\\}, $addr", "", []>;
// vst3 to double-spaced even registers.
def VST3q8a : VST3WB<0b0000, "vst3", "8">;
@@ -476,13 +477,13 @@ class VST4D<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b0000,op7_4, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4),
IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr",
+ OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr",
"", []>;
class VST4WB<bits<4> op7_4, string OpcodeStr, string Dt>
: NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4),
IIC_VST,
- OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr",
+ OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr",
"$addr.addr = $wb", []>;
def VST4d8 : VST4D<0b0000, "vst4", "8">;
@@ -491,7 +492,8 @@ def VST4d32 : VST4D<0b1000, "vst4", "32">;
def VST4d64 : NLdSt<0,0b00,0b0010,0b1100, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3,
DPR:$src4), IIC_VST,
- "vst1", "64", "\\{$src1,$src2,$src3,$src4\\}, $addr", "", []>;
+ "vst1", "64", "\\{$src1, $src2, $src3, $src4\\}, $addr",
+ "", []>;
// vst4 to double-spaced even registers.
def VST4q8a : VST4WB<0b0000, "vst4", "8">;
@@ -511,7 +513,7 @@ class VST2LN<bits<4> op11_8, string OpcodeStr, string Dt>
: NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs),
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane),
IIC_VST,
- OpcodeStr, Dt, "\\{$src1[$lane],$src2[$lane]\\}, $addr",
+ OpcodeStr, Dt, "\\{$src1[$lane], $src2[$lane]\\}, $addr",
"", []>;
// vst2 to single-spaced registers.
@@ -545,7 +547,7 @@ class VST3LN<bits<4> op11_8, string OpcodeStr, string Dt>
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3,
nohash_imm:$lane), IIC_VST,
OpcodeStr, Dt,
- "\\{$src1[$lane],$src2[$lane],$src3[$lane]\\}, $addr", "", []>;
+ "\\{$src1[$lane], $src2[$lane], $src3[$lane]\\}, $addr", "", []>;
// vst3 to single-spaced registers.
def VST3LNd8 : VST3LN<0b0010, "vst3", "8"> {
@@ -580,7 +582,7 @@ class VST4LN<bits<4> op11_8, string OpcodeStr, string Dt>
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4,
nohash_imm:$lane), IIC_VST,
OpcodeStr, Dt,
- "\\{$src1[$lane],$src2[$lane],$src3[$lane],$src4[$lane]\\}, $addr",
+ "\\{$src1[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $addr",
"", []>;
// vst4 to single-spaced registers.
@@ -2116,7 +2118,7 @@ def VACGTq : N3VQInt<1, 0, 0b10, 0b1110, 1, IIC_VBINQ, "vacgt", "f32",
v4i32, v4f32, int_arm_neon_vacgtq, 0>;
// VTST : Vector Test Bits
defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q,
- IIC_VBINi4Q, "vtst", "i", NEONvtst, 1>;
+ IIC_VBINi4Q, "vtst", "", NEONvtst, 1>;
// Vector Bitwise Operations.
@@ -3022,19 +3024,19 @@ let hasExtraSrcRegAllocReq = 1 in {
def VTBL2
: N3V<1,1,0b11,0b1001,0,0, (outs DPR:$dst),
(ins DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTB2,
- "vtbl", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "",
+ "vtbl", "8", "$dst, \\{$tbl1, $tbl2\\}, $src", "",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbl2
DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>;
def VTBL3
: N3V<1,1,0b11,0b1010,0,0, (outs DPR:$dst),
(ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTB3,
- "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "",
+ "vtbl", "8", "$dst, \\{$tbl1, $tbl2, $tbl3\\}, $src", "",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbl3
DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>;
def VTBL4
: N3V<1,1,0b11,0b1011,0,0, (outs DPR:$dst),
(ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTB4,
- "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "",
+ "vtbl", "8", "$dst, \\{$tbl1, $tbl2, $tbl3, $tbl4\\}, $src", "",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbl4 DPR:$tbl1, DPR:$tbl2,
DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>;
} // hasExtraSrcRegAllocReq = 1
@@ -3050,19 +3052,20 @@ let hasExtraSrcRegAllocReq = 1 in {
def VTBX2
: N3V<1,1,0b11,0b1001,1,0, (outs DPR:$dst),
(ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTBX2,
- "vtbx", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "$orig = $dst",
+ "vtbx", "8", "$dst, \\{$tbl1, $tbl2\\}, $src", "$orig = $dst",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbx2
DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>;
def VTBX3
: N3V<1,1,0b11,0b1010,1,0, (outs DPR:$dst),
(ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTBX3,
- "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "$orig = $dst",
+ "vtbx", "8", "$dst, \\{$tbl1, $tbl2, $tbl3\\}, $src", "$orig = $dst",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbx3 DPR:$orig, DPR:$tbl1,
DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>;
def VTBX4
: N3V<1,1,0b11,0b1011,1,0, (outs DPR:$dst), (ins DPR:$orig, DPR:$tbl1,
DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTBX4,
- "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "$orig = $dst",
+ "vtbx", "8", "$dst, \\{$tbl1, $tbl2, $tbl3, $tbl4\\}, $src",
+ "$orig = $dst",
[(set DPR:$dst, (v8i8 (int_arm_neon_vtbx4 DPR:$orig, DPR:$tbl1,
DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>;
} // hasExtraSrcRegAllocReq = 1
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 603ccf5..746caff 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -208,7 +208,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst",
[(brind GPR:$dst)]>,
- T1Special<{1,0,1,1}> {
+ T1Special<{1,0,1,?}> {
// <Rd> = Inst{7:2-0} = pc
let Inst{2-0} = 0b111;
}
@@ -534,10 +534,12 @@ def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr,
// CMN register
let Defs = [CPSR] in {
-def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
- "cmn", "\t$lhs, $rhs",
- [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>,
- T1DataProcessing<0b1011>;
+//FIXME: Disable CMN, as CCodes are backwards from compare expectations
+// Compare-to-zero still works out, just not the relationals
+//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
+// "cmn", "\t$lhs, $rhs",
+// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>,
+// T1DataProcessing<0b1011>;
def tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
"cmn", "\t$lhs, $rhs",
[(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>,
@@ -630,13 +632,13 @@ def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
// FIXME: Make these predicable.
def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr,
"mov\t$dst, $src", []>,
- T1Special<{1,0,0,1}>;
+ T1Special<{1,0,0,?}>;
def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr,
"mov\t$dst, $src", []>,
- T1Special<{1,0,1,0}>;
+ T1Special<{1,0,?,0}>;
def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
"mov\t$dst, $src", []>,
- T1Special<{1,0,1,1}>;
+ T1Special<{1,0,?,?}>;
} // neverHasSideEffects
// multiply register
@@ -771,7 +773,7 @@ let usesCustomInserter = 1 in // Expanded after instruction selection.
// 16-bit movcc in IT blocks for Thumb2.
def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr,
"mov", "\t$dst, $rhs", []>,
- T1Special<{1,0,1,1}>;
+ T1Special<{1,0,?,?}>;
def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi,
"mov", "\t$dst, $rhs", []>,
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 769df7e..c7591d2 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -1540,6 +1540,10 @@ class T2I_misc<bits<2> op1, bits<2> op2, dag oops, dag iops, InstrItinClass itin
def t2CLZ : T2I_misc<0b11, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
"clz", "\t$dst, $src", [(set GPR:$dst, (ctlz GPR:$src))]>;
+def t2RBIT : T2I_misc<0b01, 0b10, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
+ "rbit", "\t$dst, $src",
+ [(set GPR:$dst, (ARMrbit GPR:$src))]>;
+
def t2REV : T2I_misc<0b01, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
"rev", ".w\t$dst, $src", [(set GPR:$dst, (bswap GPR:$src))]>;
@@ -1605,16 +1609,18 @@ defm t2CMP : T2I_cmp_irs<0b1101, "cmp",
defm t2CMPz : T2I_cmp_irs<0b1101, "cmp",
BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
-defm t2CMN : T2I_cmp_irs<0b1000, "cmn",
- BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
+//FIXME: Disable CMN, as CCodes are backwards from compare expectations
+// Compare-to-zero still works out, just not the relationals
+//defm t2CMN : T2I_cmp_irs<0b1000, "cmn",
+// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
defm t2CMNz : T2I_cmp_irs<0b1000, "cmn",
BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
-def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
- (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
+//def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
+// (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
- (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
+ (t2CMNzri GPR:$src, t2_so_imm_neg:$imm)>;
defm t2TST : T2I_cmp_irs<0b0000, "tst",
BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/ARMMCAsmInfo.cpp
index 0ff65d2..3dd87c0 100644
--- a/lib/Target/ARM/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/ARMMCAsmInfo.cpp
@@ -64,7 +64,7 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
PrivateGlobalPrefix = ".L";
WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
- LCOMMDirective = "\t.lcomm\t";
+ HasLCOMMDirective = true;
DwarfRequiresFrameSection = false;
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 1c6fca7..4d20a5c 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -93,10 +93,6 @@ bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
if (Subtarget.hasNEON())
PM.add(createNEONPreAllocPass());
- // Calculate and set max stack object alignment early, so we can decide
- // whether we will need stack realignment (and thus FP).
- PM.add(createMaxStackAlignmentCalculatorPass());
-
// FIXME: temporarily disabling load / store optimization pass for Thumb1.
if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only())
PM.add(createARMLoadStoreOptimizationPass(true));
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 132738e..89c7769 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -8,18 +8,18 @@
//===----------------------------------------------------------------------===//
#include "ARM.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAsmLexer.h"
-#include "llvm/MC/MCAsmParser.h"
-#include "llvm/MC/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
using namespace llvm;
namespace {
@@ -222,7 +222,7 @@ struct ARMOperand : public MCParsedAsmOperand {
/// TODO this is likely to change to allow different register types and or to
/// parse for a specific register type.
bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
// FIXME: Validate register for the current architecture; we have to do
@@ -232,14 +232,14 @@ bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
RegNum = MatchRegisterName(Tok.getString());
if (RegNum == -1)
return true;
- getLexer().Lex(); // Eat identifier token.
+ Parser.Lex(); // Eat identifier token.
bool Writeback = false;
if (ParseWriteBack) {
- const AsmToken &ExclaimTok = getLexer().getTok();
+ const AsmToken &ExclaimTok = Parser.getTok();
if (ExclaimTok.is(AsmToken::Exclaim)) {
Writeback = true;
- getLexer().Lex(); // Eat exclaim token
+ Parser.Lex(); // Eat exclaim token
}
}
@@ -251,26 +251,26 @@ bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
/// Parse a register list, return false if successful else return true or an
/// error. The first token must be a '{' when called.
bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
- assert(getLexer().getTok().is(AsmToken::LCurly) &&
+ assert(Parser.getTok().is(AsmToken::LCurly) &&
"Token is not an Left Curly Brace");
- getLexer().Lex(); // Eat left curly brace token.
+ Parser.Lex(); // Eat left curly brace token.
- const AsmToken &RegTok = getLexer().getTok();
+ const AsmToken &RegTok = Parser.getTok();
SMLoc RegLoc = RegTok.getLoc();
if (RegTok.isNot(AsmToken::Identifier))
return Error(RegLoc, "register expected");
int RegNum = MatchRegisterName(RegTok.getString());
if (RegNum == -1)
return Error(RegLoc, "register expected");
- getLexer().Lex(); // Eat identifier token.
+ Parser.Lex(); // Eat identifier token.
unsigned RegList = 1 << RegNum;
int HighRegNum = RegNum;
// TODO ranges like "{Rn-Rm}"
- while (getLexer().getTok().is(AsmToken::Comma)) {
- getLexer().Lex(); // Eat comma token.
+ while (Parser.getTok().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat comma token.
- const AsmToken &RegTok = getLexer().getTok();
+ const AsmToken &RegTok = Parser.getTok();
SMLoc RegLoc = RegTok.getLoc();
if (RegTok.isNot(AsmToken::Identifier))
return Error(RegLoc, "register expected");
@@ -285,12 +285,12 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
RegList |= 1 << RegNum;
HighRegNum = RegNum;
- getLexer().Lex(); // Eat identifier token.
+ Parser.Lex(); // Eat identifier token.
}
- const AsmToken &RCurlyTok = getLexer().getTok();
+ const AsmToken &RCurlyTok = Parser.getTok();
if (RCurlyTok.isNot(AsmToken::RCurly))
return Error(RCurlyTok.getLoc(), "'}' expected");
- getLexer().Lex(); // Eat left curly brace token.
+ Parser.Lex(); // Eat left curly brace token.
return false;
}
@@ -300,11 +300,11 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
/// TODO Only preindexing and postindexing addressing are started, unindexed
/// with option, etc are still to do.
bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
- assert(getLexer().getTok().is(AsmToken::LBrac) &&
+ assert(Parser.getTok().is(AsmToken::LBrac) &&
"Token is not an Left Bracket");
- getLexer().Lex(); // Eat left bracket token.
+ Parser.Lex(); // Eat left bracket token.
- const AsmToken &BaseRegTok = getLexer().getTok();
+ const AsmToken &BaseRegTok = Parser.getTok();
if (BaseRegTok.isNot(AsmToken::Identifier))
return Error(BaseRegTok.getLoc(), "register expected");
if (MaybeParseRegister(Op, false))
@@ -319,10 +319,10 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
// First look for preindexed address forms, that is after the "[Rn" we now
// have to see if the next token is a comma.
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.is(AsmToken::Comma)) {
Preindexed = true;
- getLexer().Lex(); // Eat comma token.
+ Parser.Lex(); // Eat comma token.
int OffsetRegNum;
bool OffsetRegShifted;
enum ShiftType ShiftType;
@@ -331,15 +331,15 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Offset, OffsetIsReg, OffsetRegNum))
return true;
- const AsmToken &RBracTok = getLexer().getTok();
+ const AsmToken &RBracTok = Parser.getTok();
if (RBracTok.isNot(AsmToken::RBrac))
return Error(RBracTok.getLoc(), "']' expected");
- getLexer().Lex(); // Eat right bracket token.
+ Parser.Lex(); // Eat right bracket token.
- const AsmToken &ExclaimTok = getLexer().getTok();
+ const AsmToken &ExclaimTok = Parser.getTok();
if (ExclaimTok.is(AsmToken::Exclaim)) {
Writeback = true;
- getLexer().Lex(); // Eat exclaim token
+ Parser.Lex(); // Eat exclaim token
}
Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
OffsetRegShifted, ShiftType, ShiftAmount,
@@ -352,7 +352,7 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
// the "[Rn".
Postindexed = true;
Writeback = true;
- getLexer().Lex(); // Eat right bracket token.
+ Parser.Lex(); // Eat right bracket token.
int OffsetRegNum = 0;
bool OffsetRegShifted = false;
@@ -360,11 +360,11 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
const MCExpr *ShiftAmount;
const MCExpr *Offset;
- const AsmToken &NextTok = getLexer().getTok();
+ const AsmToken &NextTok = Parser.getTok();
if (NextTok.isNot(AsmToken::EndOfStatement)) {
if (NextTok.isNot(AsmToken::Comma))
return Error(NextTok.getLoc(), "',' expected");
- getLexer().Lex(); // Eat comma token.
+ Parser.Lex(); // Eat comma token.
if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
ShiftAmount, Offset, OffsetIsReg, OffsetRegNum))
return true;
@@ -398,15 +398,15 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
OffsetRegShifted = false;
OffsetIsReg = false;
OffsetRegNum = -1;
- const AsmToken &NextTok = getLexer().getTok();
+ const AsmToken &NextTok = Parser.getTok();
if (NextTok.is(AsmToken::Plus))
- getLexer().Lex(); // Eat plus token.
+ Parser.Lex(); // Eat plus token.
else if (NextTok.is(AsmToken::Minus)) {
Negative = true;
- getLexer().Lex(); // Eat minus token
+ Parser.Lex(); // Eat minus token
}
// See if there is a register following the "[Rn," or "[Rn]," we have so far.
- const AsmToken &OffsetRegTok = getLexer().getTok();
+ const AsmToken &OffsetRegTok = Parser.getTok();
if (OffsetRegTok.is(AsmToken::Identifier)) {
OffsetIsReg = !MaybeParseRegister(Op, false);
if (OffsetIsReg)
@@ -415,11 +415,11 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
// If we parsed a register as the offset then their can be a shift after that
if (OffsetRegNum != -1) {
// Look for a comma then a shift
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.is(AsmToken::Comma)) {
- getLexer().Lex(); // Eat comma token.
+ Parser.Lex(); // Eat comma token.
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (ParseShift(ShiftType, ShiftAmount))
return Error(Tok.getLoc(), "shift expected");
OffsetRegShifted = true;
@@ -427,10 +427,10 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
}
else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
// Look for #offset following the "[Rn," or "[Rn],"
- const AsmToken &HashTok = getLexer().getTok();
+ const AsmToken &HashTok = Parser.getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
- getLexer().Lex(); // Eat hash token.
+ Parser.Lex(); // Eat hash token.
if (getParser().ParseExpression(Offset))
return true;
@@ -443,7 +443,7 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
/// rrx
/// and returns true if it parses a shift otherwise it returns false.
bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return true;
const StringRef &ShiftName = Tok.getString();
@@ -459,17 +459,17 @@ bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
St = Rrx;
else
return true;
- getLexer().Lex(); // Eat shift type token.
+ Parser.Lex(); // Eat shift type token.
// Rrx stands alone.
if (St == Rrx)
return false;
// Otherwise, there must be a '#' and a shift amount.
- const AsmToken &HashTok = getLexer().getTok();
+ const AsmToken &HashTok = Parser.getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
- getLexer().Lex(); // Eat hash token.
+ Parser.Lex(); // Eat hash token.
if (getParser().ParseExpression(ShiftAmount))
return true;
@@ -569,14 +569,14 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
case AsmToken::Hash:
// #42 -> immediate.
// TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
- getLexer().Lex();
+ Parser.Lex();
const MCExpr *ImmVal;
if (getParser().ParseExpression(ImmVal))
return true;
Op = ARMOperand::CreateImm(ImmVal);
return false;
default:
- return Error(getLexer().getTok().getLoc(), "unexpected token in operand");
+ return Error(Parser.getTok().getLoc(), "unexpected token in operand");
}
}
@@ -585,7 +585,7 @@ bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Operands.push_back(new ARMOperand(ARMOperand::CreateToken(Name)));
- SMLoc Loc = getLexer().getTok().getLoc();
+ SMLoc Loc = Parser.getTok().getLoc();
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
@@ -594,7 +594,7 @@ bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc,
Operands.push_back(new ARMOperand(Op));
while (getLexer().is(AsmToken::Comma)) {
- getLexer().Lex(); // Eat the comma.
+ Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
if (ParseOperand(Op)) return true;
@@ -629,7 +629,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
if (getParser().ParseExpression(Value))
return true;
- getParser().getStreamer().EmitValue(Value, Size);
+ getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -637,11 +637,11 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
// FIXME: Improve diagnostic.
if (getLexer().isNot(AsmToken::Comma))
return Error(L, "unexpected token in directive");
- getLexer().Lex();
+ Parser.Lex();
}
}
- getLexer().Lex();
+ Parser.Lex();
return false;
}
@@ -650,7 +650,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(L, "unexpected token in directive");
- getLexer().Lex();
+ Parser.Lex();
// TODO: set thumb mode
// TODO: tell the MC streamer the mode
@@ -661,15 +661,15 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
/// ParseDirectiveThumbFunc
/// ::= .thumbfunc symbol_name
bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
return Error(L, "unexpected token in .syntax directive");
- StringRef ATTRIBUTE_UNUSED SymbolName = getLexer().getTok().getIdentifier();
- getLexer().Lex(); // Consume the identifier token.
+ StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
+ Parser.Lex(); // Consume the identifier token.
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(L, "unexpected token in directive");
- getLexer().Lex();
+ Parser.Lex();
// TODO: mark symbol as a thumb symbol
// getParser().getStreamer().Emit???();
@@ -679,25 +679,25 @@ bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
/// ParseDirectiveSyntax
/// ::= .syntax unified | divided
bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return Error(L, "unexpected token in .syntax directive");
const StringRef &Mode = Tok.getString();
bool unified_syntax;
if (Mode == "unified" || Mode == "UNIFIED") {
- getLexer().Lex();
+ Parser.Lex();
unified_syntax = true;
}
else if (Mode == "divided" || Mode == "DIVIDED") {
- getLexer().Lex();
+ Parser.Lex();
unified_syntax = false;
}
else
return Error(L, "unrecognized syntax mode in .syntax directive");
if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getTok().getLoc(), "unexpected token in directive");
- getLexer().Lex();
+ return Error(Parser.getTok().getLoc(), "unexpected token in directive");
+ Parser.Lex();
// TODO tell the MC streamer the mode
// getParser().getStreamer().Emit???();
@@ -707,25 +707,25 @@ bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
/// ParseDirectiveCode
/// ::= .code 16 | 32
bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Integer))
return Error(L, "unexpected token in .code directive");
- int64_t Val = getLexer().getTok().getIntVal();
+ int64_t Val = Parser.getTok().getIntVal();
bool thumb_mode;
if (Val == 16) {
- getLexer().Lex();
+ Parser.Lex();
thumb_mode = true;
}
else if (Val == 32) {
- getLexer().Lex();
+ Parser.Lex();
thumb_mode = false;
}
else
return Error(L, "invalid operand to .code directive");
if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getTok().getLoc(), "unexpected token in directive");
- getLexer().Lex();
+ return Error(Parser.getTok().getLoc(), "unexpected token in directive");
+ Parser.Lex();
// TODO tell the MC streamer the mode
// getParser().getStreamer().Emit???();
diff --git a/lib/Target/ARM/AsmParser/Makefile b/lib/Target/ARM/AsmParser/Makefile
index 97e5612..4fb8564 100644
--- a/lib/Target/ARM/AsmParser/Makefile
+++ b/lib/Target/ARM/AsmParser/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMARMAsmParser
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' ARM target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
index 2d13533..e1f386e 100644
--- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
@@ -49,7 +49,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
using namespace llvm;
@@ -160,7 +159,6 @@ namespace {
unsigned AsmVariant,
const char *ExtraCode);
- void PrintGlobalVariable(const GlobalVariable* GVar);
void printInstruction(const MachineInstr *MI); // autogenerated.
static const char *getRegisterName(unsigned RegNo);
@@ -172,7 +170,12 @@ namespace {
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
/// the .s file.
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
- printDataDirective(MCPV->getType());
+ switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
+ case 1: O << MAI->getData8bitsDirective(0); break;
+ case 2: O << MAI->getData16bitsDirective(0); break;
+ case 4: O << MAI->getData32bitsDirective(0); break;
+ default: assert(0 && "Unknown CPV size");
+ }
ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
SmallString<128> TmpNameStr;
@@ -184,32 +187,27 @@ namespace {
} else if (ACPV->isBlockAddress()) {
O << GetBlockAddressSymbol(ACPV->getBlockAddress())->getName();
} else if (ACPV->isGlobalValue()) {
- std::string Name;
GlobalValue *GV = ACPV->getGV();
bool isIndirect = Subtarget->isTargetDarwin() &&
Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
if (!isIndirect)
- Name = Mang->getMangledName(GV);
+ O << *GetGlobalValueSymbol(GV);
else {
// FIXME: Remove this when Darwin transition to @GOT like syntax.
- Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
- MCSymbol *Sym = OutContext.GetOrCreateSymbol(StringRef(Name));
+ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
+ O << *Sym;
MachineModuleInfoMachO &MMIMachO =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
const MCSymbol *&StubSym =
GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
MMIMachO.getGVStubEntry(Sym);
- if (StubSym == 0) {
- Mang->getNameWithPrefix(TmpNameStr, GV, false);
- StubSym = OutContext.GetOrCreateSymbol(TmpNameStr.str());
- }
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
}
- O << Name;
} else {
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
- Mang->getNameWithPrefix(TmpNameStr, ACPV->getSymbol());
- OutContext.GetOrCreateSymbol(TmpNameStr.str())->print(O, MAI);
+ O << *GetExternalSymbolSymbol(ACPV->getSymbol());
}
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
@@ -219,9 +217,9 @@ namespace {
<< "+" << (unsigned)ACPV->getPCAdjustment();
if (ACPV->mustAddCurrentAddress())
O << "-.";
- O << ")";
+ O << ')';
}
- O << "\n";
+ O << '\n';
}
void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -262,7 +260,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::InternalLinkage:
break;
case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << "\n";
+ O << "\t.globl\t" << *CurrentFnSym << "\n";
break;
case Function::LinkerPrivateLinkage:
case Function::WeakAnyLinkage:
@@ -270,15 +268,15 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
if (Subtarget->isTargetDarwin()) {
- O << "\t.globl\t" << CurrentFnName << "\n";
- O << "\t.weak_definition\t" << CurrentFnName << "\n";
+ O << "\t.globl\t" << *CurrentFnSym << "\n";
+ O << "\t.weak_definition\t" << *CurrentFnSym << "\n";
} else {
- O << MAI->getWeakRefDirective() << CurrentFnName << "\n";
+ O << MAI->getWeakRefDirective() << *CurrentFnSym << "\n";
}
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2.
if (AFI->isThumbFunction()) {
@@ -286,13 +284,13 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\t.code\t16\n";
O << "\t.thumb_func";
if (Subtarget->isTargetDarwin())
- O << "\t" << CurrentFnName;
+ O << "\t" << *CurrentFnSym;
O << "\n";
} else {
EmitAlignment(FnAlign, F);
}
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
// Emit pre-function debug information.
DW->BeginFunction(&MF);
@@ -320,7 +318,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
+ O << "\t.size " << *CurrentFnSym << ", .-" << *CurrentFnSym << "\n";
// Emit post-function debug information.
DW->EndFunction(&MF);
@@ -369,7 +367,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
break;
}
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
@@ -381,7 +379,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
(TF & ARMII::MO_HI16))
O << ":upper16:";
- O << Mang->getMangledName(GV);
+ O << *GetGlobalValueSymbol(GV);
printOffset(MO.getOffset());
@@ -392,9 +390,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
}
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
- SmallString<128> NameStr;
- Mang->getNameWithPrefix(NameStr, MO.getSymbolName());
- OutContext.GetOrCreateSymbol(NameStr.str())->print(O, MAI);
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
if (isCallOp && Subtarget->isTargetELF() &&
TM.getRelocationModel() == Reloc::PIC_)
@@ -402,12 +398,10 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
break;
}
case MachineOperand::MO_ConstantPoolIndex:
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ O << *GetCPISymbol(MO.getIndex());
break;
case MachineOperand::MO_JumpTableIndex:
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ O << *GetJTISymbol(MO.getIndex());
break;
}
}
@@ -895,8 +889,7 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum,
// data itself.
if (!strcmp(Modifier, "label")) {
unsigned ID = MI->getOperand(OpNum).getImm();
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << ID << ":\n";
+ O << *GetCPISymbol(ID) << ":\n";
} else {
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
unsigned CPI = MI->getOperand(OpNum).getIndex();
@@ -916,6 +909,7 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
+
unsigned JTI = MO1.getIndex();
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << JTI << '_' << MO2.getImm() << ":\n";
@@ -941,11 +935,11 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
<< '_' << JTI << '_' << MO2.getImm()
<< "_set_" << MBB->getNumber();
else if (TM.getRelocationModel() == Reloc::PIC_) {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI"
+ O << *GetMBBSymbol(MBB->getNumber())
+ << '-' << MAI->getPrivateGlobalPrefix() << "JTI"
<< getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
} else {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MBB->getNumber());
}
if (i != e-1)
O << '\n';
@@ -976,13 +970,11 @@ void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) {
else if (HalfWordOffset)
O << MAI->getData16bitsDirective();
if (ByteOffset || HalfWordOffset) {
- O << '(';
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << '(' << *GetMBBSymbol(MBB->getNumber());
O << "-" << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << JTI << '_' << MO2.getImm() << ")/2";
} else {
- O << "\tb.w ";
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << "\tb.w " << *GetMBBSymbol(MBB->getNumber());
}
if (i != e-1)
O << '\n';
@@ -1174,146 +1166,6 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
}
}
-void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer()) // External global require no code
- return;
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
-
- if (EmitSpecialLLVMGlobal(GVar)) {
- if (Subtarget->isTargetDarwin() &&
- TM.getRelocationModel() == Reloc::Static) {
- if (GVar->getName() == "llvm.global_ctors")
- O << ".reference .constructors_used\n";
- else if (GVar->getName() == "llvm.global_dtors")
- O << ".reference .destructors_used\n";
- }
- return;
- }
-
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
- bool isDarwin = Subtarget->isTargetDarwin();
-
- printVisibility(name, GVar->getVisibility());
-
- if (Subtarget->isTargetELF())
- O << "\t.type " << name << ",%object\n";
-
- const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, Mang, TM);
- OutStreamer.SwitchSection(TheSection);
-
- // FIXME: get this stuff from section kind flags.
- if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() &&
- // Don't put things that should go in the cstring section into "comm".
- !TheSection->getKind().isMergeableCString()) {
- if (GVar->hasExternalLinkage()) {
- if (const char *Directive = MAI->getZeroFillDirective()) {
- O << "\t.globl\t" << name << "\n";
- O << Directive << "__DATA, __common, " << name << ", "
- << Size << ", " << Align << "\n";
- return;
- }
- }
-
- if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (isDarwin) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << "," << Size
- << ',' << Align;
- } else if (GVar->hasCommonLinkage()) {
- O << MAI->getCOMMDirective() << name << "," << Size
- << ',' << Align;
- } else {
- OutStreamer.SwitchSection(TheSection);
- O << "\t.globl " << name << '\n'
- << MAI->getWeakDefDirective() << name << '\n';
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- }
- } else if (MAI->getLCOMMDirective() != NULL) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << "," << Size;
- } else {
- O << MAI->getCOMMDirective() << name << "," << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- } else {
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << "\n";
- O << MAI->getCOMMDirective() << name << "," << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << "\n";
- return;
- }
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- if (isDarwin) {
- O << "\t.globl " << name << "\n"
- << "\t.weak_definition " << name << "\n";
- } else {
- O << "\t.weak " << name << "\n";
- }
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- O << "\t.globl " << name << "\n";
- break;
- case GlobalValue::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << "\n";
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size " << name << ", " << Size << "\n";
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetDarwin()) {
@@ -1333,10 +1185,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
EmitAlignment(2);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- Stubs[i].first->print(O, MAI);
- O << ":\n\t.indirect_symbol ";
- Stubs[i].second->print(O, MAI);
- O << "\n\t.long\t0\n";
+ O << *Stubs[i].first << ":\n\t.indirect_symbol ";
+ O << *Stubs[i].second << "\n\t.long\t0\n";
}
}
@@ -1344,12 +1194,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (!Stubs.empty()) {
OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
EmitAlignment(2);
- for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- Stubs[i].first->print(O, MAI);
- O << ":\n\t.long ";
- Stubs[i].second->print(O, MAI);
- O << "\n";
- }
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i)
+ O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n";
}
// Funny Darwin hack: This flag tells the linker that no global symbols
@@ -1357,7 +1203,7 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
- OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+ OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
}
}
@@ -1416,12 +1262,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
EmitAlignment(2);
-
- const char *Prefix = MAI->getPrivateGlobalPrefix();
- MCSymbol *Label = OutContext.GetOrCreateSymbol(Twine(Prefix)+"CPI"+
- Twine(getFunctionNumber())+
- "_"+ Twine(LabelId));
- OutStreamer.EmitLabel(Label);
+ OutStreamer.EmitLabel(GetCPISymbol(LabelId));
const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
if (MCPE.isMachineConstantPoolEntry())
diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
index 9fc57e0..6885ecb 100644
--- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
@@ -62,7 +62,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
} else {
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
assert(Op.isExpr() && "unknown operand kind in printOperand");
- Op.getExpr()->print(O, &MAI);
+ O << *Op.getExpr();
}
}
diff --git a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
index c49fee3..f843ee2 100644
--- a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp
@@ -22,7 +22,6 @@
#include "llvm/MC/MCInst.h"
//#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
@@ -40,33 +39,24 @@ MachineModuleInfoMachO &ARMMCInstLower::getMachOMMI() const {
MCSymbol *ARMMCInstLower::
GetGlobalAddressSymbol(const MachineOperand &MO) const {
- const GlobalValue *GV = MO.getGlobal();
-
- SmallString<128> Name;
- Mang.getNameWithPrefix(Name, GV, false);
-
// FIXME: HANDLE PLT references how??
switch (MO.getTargetFlags()) {
default: assert(0 && "Unknown target flag on GV operand");
case 0: break;
}
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Printer.GetGlobalValueSymbol(MO.getGlobal());
}
MCSymbol *ARMMCInstLower::
GetExternalSymbolSymbol(const MachineOperand &MO) const {
- SmallString<128> Name;
- Name += Printer.MAI->getGlobalPrefix();
- Name += MO.getSymbolName();
-
// FIXME: HANDLE PLT references how??
switch (MO.getTargetFlags()) {
default: assert(0 && "Unknown target flag on GV operand");
case 0: break;
}
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
}
diff --git a/lib/Target/ARM/AsmPrinter/Makefile b/lib/Target/ARM/AsmPrinter/Makefile
index 208becc..93b8fc9 100644
--- a/lib/Target/ARM/AsmPrinter/Makefile
+++ b/lib/Target/ARM/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMARMAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' arm target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile
index a8dd38c..b766a86 100644
--- a/lib/Target/ARM/Makefile
+++ b/lib/Target/ARM/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMARMCodeGen
TARGET = ARM
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \
diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt
index 11c48ad..a6f26a5 100644
--- a/lib/Target/ARM/README.txt
+++ b/lib/Target/ARM/README.txt
@@ -596,3 +596,12 @@ Make use of the "rbit" instruction.
Take a look at test/CodeGen/Thumb2/machine-licm.ll. ARM should be taught how
to licm and cse the unnecessary load from cp#1.
+
+//===---------------------------------------------------------------------===//
+
+The CMN instruction sets the flags like an ADD instruction, while CMP sets
+them like a subtract. Therefore to be able to use CMN for comparisons other
+than the Z bit, we'll need additional logic to reverse the conditionals
+associated with the comparison. Perhaps a pseudo-instruction for the comparison,
+with a post-codegen pass to clean up and handle the condition codes?
+See PR5694 for testcase.
diff --git a/lib/Target/ARM/TargetInfo/Makefile b/lib/Target/ARM/TargetInfo/Makefile
index 6292ab1..589dbe5 100644
--- a/lib/Target/ARM/TargetInfo/Makefile
+++ b/lib/Target/ARM/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMARMInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp
index e875394..7f42c82 100644
--- a/lib/Target/ARM/Thumb1InstrInfo.cpp
+++ b/lib/Target/ARM/Thumb1InstrInfo.cpp
@@ -105,7 +105,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
isARMLowRegister(SrcReg))) && "Unknown regclass!");
- if (RC == ARM::tGPRRegisterClass) {
+ if (RC == ARM::tGPRRegisterClass ||
+ (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
+ isARMLowRegister(SrcReg))) {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
MachineMemOperand *MMO =
@@ -130,7 +132,9 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
(TargetRegisterInfo::isPhysicalRegister(DestReg) &&
isARMLowRegister(DestReg))) && "Unknown regclass!");
- if (RC == ARM::tGPRRegisterClass) {
+ if (RC == ARM::tGPRRegisterClass ||
+ (TargetRegisterInfo::isPhysicalRegister(DestReg) &&
+ isARMLowRegister(DestReg))) {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
MachineMemOperand *MMO =
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp
index 9f3816a..d6630ce 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.cpp
+++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp
@@ -479,11 +479,15 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
"Thumb add/sub sp, #imm immediate must be multiple of 4!");
}
- if (Offset == 0) {
+ unsigned PredReg;
+ if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
// Turn it into a move.
MI.setDesc(TII.get(ARM::tMOVgpr2tgpr));
MI.getOperand(i).ChangeToRegister(FrameReg, false);
- MI.RemoveOperand(i+1);
+ // Remove offset and remaining explicit predicate operands.
+ do MI.RemoveOperand(i+1);
+ while (MI.getNumOperands() > i+1 &&
+ (!MI.getOperand(i+1).isReg() || !MI.getOperand(i+1).isImm()));
return 0;
}
diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp
index f4a8c27..387edaf 100644
--- a/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -329,12 +329,16 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
Offset += MI.getOperand(FrameRegIdx+1).getImm();
bool isSP = FrameReg == ARM::SP;
- if (Offset == 0) {
+ unsigned PredReg;
+ if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
// Turn it into a move.
MI.setDesc(TII.get(ARM::tMOVgpr2gpr));
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
- MI.RemoveOperand(FrameRegIdx+1);
- Offset = 0;
+ // Remove offset and remaining explicit predicate operands.
+ do MI.RemoveOperand(FrameRegIdx+1);
+ while (MI.getNumOperands() > FrameRegIdx+1 &&
+ (!MI.getOperand(FrameRegIdx+1).isReg() ||
+ !MI.getOperand(FrameRegIdx+1).isImm()));
return true;
}
diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp
index 35359aa..95288bf 100644
--- a/lib/Target/ARM/Thumb2SizeReduction.cpp
+++ b/lib/Target/ARM/Thumb2SizeReduction.cpp
@@ -65,7 +65,8 @@ namespace {
{ ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 0 },
{ ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 0 },
{ ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 0 },
- { ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 },
+ //FIXME: Disable CMN, as CCodes are backwards from compare expectations
+ //{ ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 },
{ ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0 },
{ ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0 },
{ ARM::t2CMPzri,ARM::tCMPzi8, 0, 8, 0, 1, 0, 2,0, 0 },
diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
index 338057b..b13f544 100644
--- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
+++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
@@ -28,7 +28,6 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
@@ -53,7 +52,6 @@ namespace {
void printOp(const MachineOperand &MO, bool IsCallOp = false);
void printOperand(const MachineInstr *MI, int opNum);
void printBaseOffsetPair(const MachineInstr *MI, int i, bool brackets=true);
- void PrintGlobalVariable(const GlobalVariable *GVar);
bool runOnMachineFunction(MachineFunction &F);
void EmitStartOfAsmFile(Module &M);
@@ -95,7 +93,7 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_ConstantPoolIndex:
@@ -108,7 +106,7 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
return;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
return;
case MachineOperand::MO_JumpTableIndex:
@@ -148,29 +146,29 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::PrivateLinkage:
case Function::LinkerPrivateLinkage:
break;
- case Function::ExternalLinkage:
- O << "\t.globl " << CurrentFnName << "\n";
- break;
+ case Function::ExternalLinkage:
+ O << "\t.globl " << *CurrentFnSym << '\n';
+ break;
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
- O << MAI->getWeakRefDirective() << CurrentFnName << "\n";
+ O << MAI->getWeakRefDirective() << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
- O << "\t.ent " << CurrentFnName << "\n";
+ O << "\t.ent " << *CurrentFnSym << "\n";
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
- if (I != MF.begin()) {
+ if (I != MF.begin())
EmitBasicBlockStart(I);
- }
+
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
@@ -185,7 +183,7 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
}
- O << "\t.end " << CurrentFnName << "\n";
+ O << "\t.end " << *CurrentFnSym << "\n";
// We didn't modify anything.
return false;
@@ -199,62 +197,6 @@ void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) {
O << "\t.set noat\n";
}
-void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer()) return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- unsigned Size = TD->getTypeAllocSize(C->getType());
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- // 0: Switch to section
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- // 1: Check visibility
- printVisibility(name, GVar->getVisibility());
-
- // 2: Kind
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::CommonLinkage:
- O << MAI->getWeakRefDirective() << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- case GlobalValue::ExternalLinkage:
- O << MAI->getGlobalDirective() << name << "\n";
- break;
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- // 3: Type, Size, Align
- if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type\t" << name << ", @object\n";
- O << "\t.size\t" << name << ", " << Size << "\n";
- }
-
- EmitAlignment(Align, GVar);
-
- O << name << ":\n";
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/lib/Target/Alpha/AsmPrinter/Makefile b/lib/Target/Alpha/AsmPrinter/Makefile
index 3c64a3c..3f64aac 100644
--- a/lib/Target/Alpha/AsmPrinter/Makefile
+++ b/lib/Target/Alpha/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMAlphaAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' alpha target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile
index d2d7109..14cbc6c 100644
--- a/lib/Target/Alpha/Makefile
+++ b/lib/Target/Alpha/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMAlphaCodeGen
TARGET = Alpha
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \
diff --git a/lib/Target/Alpha/TargetInfo/Makefile b/lib/Target/Alpha/TargetInfo/Makefile
index de01d7f..6f7b898 100644
--- a/lib/Target/Alpha/TargetInfo/Makefile
+++ b/lib/Target/Alpha/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMAlphaInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp
index 0bd94d4..749f735 100644
--- a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp
+++ b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp
@@ -30,7 +30,6 @@
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
@@ -55,13 +54,12 @@ namespace {
void printInstruction(const MachineInstr *MI); // autogenerated.
static const char *getRegisterName(unsigned RegNo);
- void emitLinkage(const std::string &n, GlobalValue::LinkageTypes l);
+ void emitLinkage(const MCSymbol *GVSym, GlobalValue::LinkageTypes l);
bool runOnMachineFunction(MachineFunction &F);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
- void PrintGlobalVariable(const GlobalVariable* GVar);
};
} // end of anonymous namespace
@@ -71,48 +69,27 @@ extern "C" void LLVMInitializeBlackfinAsmPrinter() {
RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget);
}
-void BlackfinAsmPrinter::emitLinkage(const std::string &name,
- GlobalValue::LinkageTypes l) {
- switch (l) {
+void BlackfinAsmPrinter::emitLinkage(const MCSymbol *GVSym,
+ GlobalValue::LinkageTypes L) {
+ switch (L) {
default: llvm_unreachable("Unknown linkage type!");
case GlobalValue::InternalLinkage: // Symbols default to internal.
case GlobalValue::PrivateLinkage:
case GlobalValue::LinkerPrivateLinkage:
break;
case GlobalValue::ExternalLinkage:
- O << MAI->getGlobalDirective() << name << "\n";
+ O << MAI->getGlobalDirective() << *GVSym << "\n";
break;
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
- O << MAI->getGlobalDirective() << name << "\n";
- O << MAI->getWeakDefDirective() << name << "\n";
+ O << MAI->getGlobalDirective() << *GVSym << "\n";
+ O << MAI->getWeakDefDirective() << *GVSym << "\n";
break;
}
}
-void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV))
- return;
-
- std::string name = Mang->getMangledName(GV);
- Constant *C = GV->getInitializer();
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,
- TM));
- emitLinkage(name, GV->getLinkage());
- EmitAlignment(TD->getPreferredAlignmentLog(GV), GV);
- printVisibility(name, GV->getVisibility());
-
- O << "\t.type " << name << ", STT_OBJECT\n";
- O << "\t.size " << name << ',' << TD->getTypeAllocSize(C->getType()) << '\n';
- O << name << ":\n";
- EmitGlobalConstant(C);
-}
-
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
@@ -124,11 +101,11 @@ bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
const Function *F = MF.getFunction();
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
EmitAlignment(2, F);
- emitLinkage(CurrentFnName, F->getLinkage());
- printVisibility(CurrentFnName, F->getVisibility());
+ emitLinkage(CurrentFnSym, F->getLinkage());
+ printVisibility(CurrentFnSym, F->getVisibility());
- O << "\t.type\t" << CurrentFnName << ", STT_FUNC\n"
- << CurrentFnName << ":\n";
+ O << "\t.type\t" << *CurrentFnSym << ", STT_FUNC\n";
+ O << *CurrentFnSym << ":\n";
if (DW)
DW->BeginFunction(&MF);
@@ -154,7 +131,7 @@ bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
}
- O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
+ O << "\t.size " << *CurrentFnSym << ", .-" << *CurrentFnSym << "\n";
if (DW)
DW->EndFunction(&MF);
@@ -175,18 +152,15 @@ void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
printOffset(MO.getOffset());
break;
- case MachineOperand::MO_ExternalSymbol: {
- SmallString<60> NameStr;
- Mang->getNameWithPrefix(NameStr, MO.getSymbolName());
- OutContext.GetOrCreateSymbol(NameStr.str())->print(O, MAI);
+ case MachineOperand::MO_ExternalSymbol:
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
- }
case MachineOperand::MO_ConstantPoolIndex:
O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
<< MO.getIndex();
diff --git a/lib/Target/Blackfin/AsmPrinter/Makefile b/lib/Target/Blackfin/AsmPrinter/Makefile
index 091d4df..30e8285 100644
--- a/lib/Target/Blackfin/AsmPrinter/Makefile
+++ b/lib/Target/Blackfin/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMBlackfinAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' Blackfin target directory to grab private
# headers
diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile
index c68760b..4fdaf27 100644
--- a/lib/Target/Blackfin/Makefile
+++ b/lib/Target/Blackfin/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMBlackfinCodeGen
TARGET = Blackfin
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \
diff --git a/lib/Target/Blackfin/TargetInfo/Makefile b/lib/Target/Blackfin/TargetInfo/Makefile
index c49cfbe..5c770cf 100644
--- a/lib/Target/Blackfin/TargetInfo/Makefile
+++ b/lib/Target/Blackfin/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMBlackfinInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 0fd975c..e765655 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -33,6 +33,7 @@
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h"
@@ -44,7 +45,6 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/System/Host.h"
#include "llvm/Config/config.h"
@@ -58,6 +58,13 @@ extern "C" void LLVMInitializeCBackendTarget() {
}
namespace {
+ class CBEMCAsmInfo : public MCAsmInfo {
+ public:
+ CBEMCAsmInfo() {
+ GlobalPrefix = "";
+ PrivateGlobalPrefix = "";
+ }
+ };
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
/// any unnamed structure types that are used by the program, and merges
/// external functions with the same name.
@@ -344,11 +351,19 @@ namespace {
char CWriter::ID = 0;
-static std::string Mangle(const std::string &S) {
+static std::string CBEMangle(const std::string &S) {
std::string Result;
- raw_string_ostream OS(Result);
- MCSymbol::printMangledName(S, OS, 0);
- return OS.str();
+
+ for (unsigned i = 0, e = S.size(); i != e; ++i)
+ if (isalnum(S[i]) || S[i] == '_') {
+ Result += S[i];
+ } else {
+ Result += '_';
+ Result += 'A'+(S[i]&15);
+ Result += 'A'+((S[i]>>4)&15);
+ Result += '_';
+ }
+ return Result;
}
@@ -1445,7 +1460,7 @@ std::string CWriter::GetValueName(const Value *Operand) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(Operand)) {
SmallString<128> Str;
Mang->getNameWithPrefix(Str, GV, false);
- return Mangle(Str.str().str());
+ return CBEMangle(Str.str().str());
}
std::string Name = Operand->getName();
@@ -1869,8 +1884,17 @@ bool CWriter::doInitialization(Module &M) {
IL = new IntrinsicLowering(*TD);
IL->AddPrototypes(M);
- // Ensure that all structure types have names...
- Mang = new Mangler(M);
+#if 0
+ std::string Triple = TheModule->getTargetTriple();
+ if (Triple.empty())
+ Triple = llvm::sys::getHostTriple();
+
+ std::string E;
+ if (const Target *Match = TargetRegistry::lookupTarget(Triple, E))
+ TAsm = Match->createAsmInfo(Triple);
+#endif
+ TAsm = new CBEMCAsmInfo();
+ Mang = new Mangler(*TAsm);
// Keep track of which functions are static ctors/dtors so they can have
// an attribute added to their prototypes.
@@ -2223,7 +2247,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
// Print out forward declarations for structure types before anything else!
Out << "/* Structure forward decls */\n";
for (; I != End; ++I) {
- std::string Name = "struct " + Mangle("l_"+I->first);
+ std::string Name = "struct " + CBEMangle("l_"+I->first);
Out << Name << ";\n";
TypeNames.insert(std::make_pair(I->second, Name));
}
@@ -2234,7 +2258,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
// for struct or opaque types.
Out << "/* Typedefs */\n";
for (I = TST.begin(); I != End; ++I) {
- std::string Name = Mangle("l_"+I->first);
+ std::string Name = CBEMangle("l_"+I->first);
Out << "typedef ";
printType(Out, I->second, false, Name);
Out << ";\n";
@@ -3240,30 +3264,31 @@ bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID,
// of the per target tables
// handle multiple constraint codes
std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) {
-
assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
- const char *const *table = 0;
-
// Grab the translation table from MCAsmInfo if it exists.
- if (!TAsm) {
- std::string Triple = TheModule->getTargetTriple();
- if (Triple.empty())
- Triple = llvm::sys::getHostTriple();
-
- std::string E;
- if (const Target *Match = TargetRegistry::lookupTarget(Triple, E))
- TAsm = Match->createAsmInfo(Triple);
- }
- if (TAsm)
- table = TAsm->getAsmCBE();
+ const MCAsmInfo *TargetAsm;
+ std::string Triple = TheModule->getTargetTriple();
+ if (Triple.empty())
+ Triple = llvm::sys::getHostTriple();
+
+ std::string E;
+ if (const Target *Match = TargetRegistry::lookupTarget(Triple, E))
+ TargetAsm = Match->createAsmInfo(Triple);
+ else
+ return c.Codes[0];
+
+ const char *const *table = TargetAsm->getAsmCBE();
// Search the translation table if it exists.
for (int i = 0; table && table[i]; i += 2)
- if (c.Codes[0] == table[i])
+ if (c.Codes[0] == table[i]) {
+ delete TargetAsm;
return table[i+1];
+ }
// Default is identity.
+ delete TargetAsm;
return c.Codes[0];
}
diff --git a/lib/Target/CBackend/Makefile b/lib/Target/CBackend/Makefile
index 3b5ef0f..f82d277 100644
--- a/lib/Target/CBackend/Makefile
+++ b/lib/Target/CBackend/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMCBackend
+CXXFLAGS = -fno-rtti
DIRS = TargetInfo
diff --git a/lib/Target/CBackend/TargetInfo/Makefile b/lib/Target/CBackend/TargetInfo/Makefile
index d4d5e15..6407904 100644
--- a/lib/Target/CBackend/TargetInfo/Makefile
+++ b/lib/Target/CBackend/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMCBackendInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt
index 8769ee2..10478b4 100644
--- a/lib/Target/CMakeLists.txt
+++ b/lib/Target/CMakeLists.txt
@@ -1,6 +1,8 @@
add_llvm_library(LLVMTarget
+ Mangler.cpp
SubtargetFeature.cpp
Target.cpp
+ TargetAsmLexer.cpp
TargetData.cpp
TargetELFWriterInfo.cpp
TargetFrameInfo.cpp
diff --git a/lib/Target/CellSPU/AsmPrinter/Makefile b/lib/Target/CellSPU/AsmPrinter/Makefile
index 69639ef..aa0db52 100644
--- a/lib/Target/CellSPU/AsmPrinter/Makefile
+++ b/lib/Target/CellSPU/AsmPrinter/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMCellSPUAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' CellSPU target directory to grab
# private headers
diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
index dc9f81c4..59d6ddd 100644
--- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
+++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
@@ -39,9 +39,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
-#include <set>
using namespace llvm;
namespace {
@@ -50,7 +48,6 @@ namespace {
const std::string bss_section(".bss");
class SPUAsmPrinter : public AsmPrinter {
- std::set<std::string> FnStubs, GVStubs;
public:
explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const MCAsmInfo *T, bool V) :
@@ -302,9 +299,6 @@ namespace {
AU.addRequired<DwarfWriter>();
SPUAsmPrinter::getAnalysisUsage(AU);
}
-
- //! Emit a global variable according to its section and type
- void PrintGlobalVariable(const GlobalVariable* GVar);
};
} // end of anonymous namespace
@@ -318,7 +312,7 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
@@ -331,32 +325,25 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
case MachineOperand::MO_ExternalSymbol:
// Computing the address of an external symbol, not calling it.
if (TM.getRelocationModel() != Reloc::Static) {
- std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName();
- GVStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
+ O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName()
+ << "$non_lazy_ptr";
return;
}
- O << MAI->getGlobalPrefix() << MO.getSymbolName();
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
return;
- case MachineOperand::MO_GlobalAddress: {
- // Computing the address of a global symbol, not calling it.
- GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getMangledName(GV);
-
+ case MachineOperand::MO_GlobalAddress:
// External or weakly linked global variables need non-lazily-resolved
// stubs
if (TM.getRelocationModel() != Reloc::Static) {
+ GlobalValue *GV = MO.getGlobal();
if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
- GVStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
+ O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
return;
}
}
- O << Name;
+ O << *GetGlobalValueSymbol(MO.getGlobal());
return;
- }
-
default:
O << "<unknown operand type: " << MO.getType() << ">";
return;
@@ -437,18 +424,19 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::ExternalLinkage:
- O << "\t.global\t" << CurrentFnName << "\n"
- << "\t.type\t" << CurrentFnName << ", @function\n";
+ O << "\t.global\t" << *CurrentFnSym << "\n" << "\t.type\t";
+ O << *CurrentFnSym << ", @function\n";
break;
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
- O << "\t.global\t" << CurrentFnName << "\n";
- O << "\t.weak_definition\t" << CurrentFnName << "\n";
+ O << "\t.global\t" << *CurrentFnSym << "\n";
+ O << "\t.weak_definition\t" << *CurrentFnSym << "\n";
break;
}
- O << CurrentFnName << ":\n";
+
+ O << *CurrentFnSym << ":\n";
// Emit pre-function debug information.
DW->BeginFunction(&MF);
@@ -467,7 +455,7 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
}
- O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
+ O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << "\n";
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
@@ -479,93 +467,6 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
return false;
}
-
-/*!
- Emit a global variable according to its section, alignment, etc.
-
- \note This code was shamelessly copied from the PowerPC's assembly printer,
- which sort of screams for some kind of refactorization of common code.
- */
-void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return;
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- std::string name = Mang->getMangledName(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && /* FIXME: Verify correct */
- !GVar->hasSection() &&
- (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
- GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasExternalLinkage()) {
- O << "\t.global " << name << '\n';
- O << "\t.type " << name << ", @object\n";
- O << name << ":\n";
- O << "\t.zero " << Size << '\n';
- } else if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << ',' << Size;
- } else {
- O << ".comm " << name << ',' << Size;
- }
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'\n";
- return;
- }
-
- switch (GVar->getLinkage()) {
- // Should never be seen for the CellSPU platform...
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::CommonLinkage:
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n"
- << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n";
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- llvm_report_error("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":\t\t\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'\n";
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
// Force static initialization.
extern "C" void LLVMInitializeCellSPUAsmPrinter() {
RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile
index 8415168..9f3ff74 100644
--- a/lib/Target/CellSPU/Makefile
+++ b/lib/Target/CellSPU/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMCellSPUCodeGen
TARGET = SPU
+CXXFLAGS = -fno-rtti
BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterNames.inc \
SPUGenAsmWriter.inc SPUGenCodeEmitter.inc \
diff --git a/lib/Target/CellSPU/SPUMCAsmInfo.cpp b/lib/Target/CellSPU/SPUMCAsmInfo.cpp
index 1c921ab..03cdb29 100644
--- a/lib/Target/CellSPU/SPUMCAsmInfo.cpp
+++ b/lib/Target/CellSPU/SPUMCAsmInfo.cpp
@@ -19,7 +19,7 @@ SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, const StringRef &TT) {
SetDirective = "\t.set";
Data64bitsDirective = "\t.quad\t";
AlignmentIsInBytes = false;
- LCOMMDirective = "\t.lcomm\t";
+ HasLCOMMDirective = true;
PCSymbol = ".";
CommentString = "#";
diff --git a/lib/Target/CellSPU/TargetInfo/Makefile b/lib/Target/CellSPU/TargetInfo/Makefile
index 9cb6827..30ca5cf 100644
--- a/lib/Target/CellSPU/TargetInfo/Makefile
+++ b/lib/Target/CellSPU/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMCellSPUInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index a872fbd..73272bc 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -472,7 +472,6 @@ namespace {
HANDLE_ATTR(Nest);
HANDLE_ATTR(ReadNone);
HANDLE_ATTR(ReadOnly);
- HANDLE_ATTR(InlineHint);
HANDLE_ATTR(NoInline);
HANDLE_ATTR(AlwaysInline);
HANDLE_ATTR(OptimizeForSize);
diff --git a/lib/Target/CppBackend/Makefile b/lib/Target/CppBackend/Makefile
index dc9cf48..52f2aad 100644
--- a/lib/Target/CppBackend/Makefile
+++ b/lib/Target/CppBackend/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMCppBackend
+CXXFLAGS = -fno-rtti
DIRS = TargetInfo
diff --git a/lib/Target/CppBackend/TargetInfo/Makefile b/lib/Target/CppBackend/TargetInfo/Makefile
index 6e68283..7e44aab 100644
--- a/lib/Target/CppBackend/TargetInfo/Makefile
+++ b/lib/Target/CppBackend/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMCppBackendInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp
index b3b91da..1bc708e 100644
--- a/lib/Target/MSIL/MSILWriter.cpp
+++ b/lib/Target/MSIL/MSILWriter.cpp
@@ -102,7 +102,6 @@ bool MSILWriter::runOnFunction(Function &F) {
bool MSILWriter::doInitialization(Module &M) {
ModulePtr = &M;
- Mang = new Mangler(M);
Out << ".assembly extern mscorlib {}\n";
Out << ".assembly MSIL {}\n\n";
Out << "// External\n";
@@ -118,7 +117,6 @@ bool MSILWriter::doInitialization(Module &M) {
bool MSILWriter::doFinalization(Module &M) {
- delete Mang;
return false;
}
@@ -232,7 +230,7 @@ bool MSILWriter::isZeroValue(const Value* V) {
std::string MSILWriter::getValueName(const Value* V) {
std::string Name;
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
- Name = Mang->getMangledName(GV);
+ Name = GV->getName();
else {
unsigned &No = AnonValueNumbers[V];
if (No == 0) No = ++NextAnonValueNumber;
@@ -259,7 +257,7 @@ std::string MSILWriter::getLabelName(const std::string& Name) {
std::string MSILWriter::getLabelName(const Value* V) {
std::string Name;
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
- Name = Mang->getMangledName(GV);
+ Name = GV->getName();
else {
unsigned &No = AnonValueNumbers[V];
if (No == 0) No = ++NextAnonValueNumber;
@@ -1616,7 +1614,7 @@ const char* MSILWriter::getLibraryName(const Function* F) {
const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
- return getLibraryForSymbol(Mang->getMangledName(GV), false, CallingConv::C);
+ return getLibraryForSymbol(GV->getName(), false, CallingConv::C);
}
@@ -1674,7 +1672,7 @@ void MSILWriter::printExternals() {
std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
printSimpleInstruction("ldsflda",Tmp.c_str());
Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
- Out << "\tldstr\t\"" << Mang->getMangledName(&*I) << "\"\n";
+ Out << "\tldstr\t\"" << I->getName() << "\"\n";
printSimpleInstruction("call","void* $MSIL_Import(string,string)");
printIndirectSave(I->getType());
}
diff --git a/lib/Target/MSIL/MSILWriter.h b/lib/Target/MSIL/MSILWriter.h
index 2280a3b..a95ae23 100644
--- a/lib/Target/MSIL/MSILWriter.h
+++ b/lib/Target/MSIL/MSILWriter.h
@@ -27,7 +27,6 @@
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Mangler.h"
namespace llvm {
extern Target TheMSILTarget;
@@ -78,7 +77,6 @@ namespace llvm {
formatted_raw_ostream &Out;
Module* ModulePtr;
const TargetData* TD;
- Mangler* Mang;
LoopInfo *LInfo;
std::vector<StaticInitializer>* InitListPtr;
std::map<const GlobalVariable*,std::vector<StaticInitializer> >
diff --git a/lib/Target/MSIL/Makefile b/lib/Target/MSIL/Makefile
index 8057cc7..9fecba5 100644
--- a/lib/Target/MSIL/Makefile
+++ b/lib/Target/MSIL/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMMSIL
+CXXFLAGS = -fno-rtti
DIRS = TargetInfo
diff --git a/lib/Target/MSIL/TargetInfo/Makefile b/lib/Target/MSIL/TargetInfo/Makefile
index 30b0950..710f5a1 100644
--- a/lib/Target/MSIL/TargetInfo/Makefile
+++ b/lib/Target/MSIL/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMMSILInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
index 145359f..6033197 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp
@@ -38,9 +38,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/ErrorHandling.h"
-
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
@@ -80,7 +78,6 @@ namespace {
const char *ExtraCode);
void printInstructionThroughMCStreamer(const MachineInstr *MI);
- void PrintGlobalVariable(const GlobalVariable* GVar);
void emitFunctionHeader(const MachineFunction &MF);
bool runOnMachineFunction(MachineFunction &F);
@@ -91,89 +88,6 @@ namespace {
};
} // end of anonymous namespace
-void MSP430AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- const TargetData *TD = TM.getTargetData();
-
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- unsigned Size = TD->getTypeAllocSize(C->getType());
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- O << "\t.type\t" << name << ",@object\n";
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && !GVar->hasSection() &&
- !GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
-
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
-
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
-
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- return;
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- O << "\t.weak\t" << name << '\n';
- break;
- case GlobalValue::DLLExportLinkage:
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << '\n';
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- // Use 16-bit alignment by default to simplify bunch of stuff
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
-
- EmitGlobalConstant(C);
-
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << name << ", " << Size << '\n';
-}
void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
const Function *F = MF.getFunction();
@@ -190,20 +104,20 @@ void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
case Function::LinkerPrivateLinkage:
break;
case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
+ O << "\t.globl\t" << *CurrentFnSym << '\n';
break;
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
- O << "\t.weak\t" << CurrentFnName << '\n';
+ O << "\t.weak\t" << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
- O << "\t.type\t" << CurrentFnName << ",@function\n"
- << CurrentFnName << ":\n";
+ O << "\t.type\t" << *CurrentFnSym << ",@function\n";
+ O << *CurrentFnSym << ":\n";
}
bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
@@ -226,7 +140,7 @@ bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
// We didn't modify anything
return false;
@@ -259,18 +173,18 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- std::string Name = Mang->getMangledName(MO.getGlobal());
uint64_t Offset = MO.getOffset();
O << (isMemOp ? '&' : '#');
if (Offset)
O << '(' << Offset << '+';
- O << Name;
+ O << *GetGlobalValueSymbol(MO.getGlobal());
+
if (Offset)
O << ')';
@@ -278,11 +192,8 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
}
case MachineOperand::MO_ExternalSymbol: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- std::string Name(MAI->getGlobalPrefix());
- Name += MO.getSymbolName();
-
- O << (isMemOp ? '&' : '#') << Name;
-
+ O << (isMemOp ? '&' : '#');
+ O << MAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
default:
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
index 0a403c4..a480307 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp
@@ -39,7 +39,7 @@ void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) {
O << Op.getImm();
else {
assert(Op.isExpr() && "unknown pcrel immediate operand");
- Op.getExpr()->print(O, &MAI);
+ O << *Op.getExpr();
}
}
@@ -53,8 +53,7 @@ void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << '#' << Op.getImm();
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
- O << '#';
- Op.getExpr()->print(O, &MAI);
+ O << '#' << *Op.getExpr();
}
}
@@ -65,8 +64,7 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
// Print displacement first
if (Disp.isExpr()) {
- O << '&';
- Disp.getExpr()->print(O, &MAI);
+ O << '&' << *Disp.getExpr();
} else {
assert(Disp.isImm() && "Expected immediate in displacement field");
if (!Base.getReg())
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
index 595b7e7..e1f80b7 100644
--- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
+++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp
@@ -22,37 +22,27 @@
#include "llvm/MC/MCInst.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
MCSymbol *MSP430MCInstLower::
GetGlobalAddressSymbol(const MachineOperand &MO) const {
- const GlobalValue *GV = MO.getGlobal();
-
- SmallString<128> Name;
- Mang.getNameWithPrefix(Name, GV, false);
-
switch (MO.getTargetFlags()) {
default: llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
}
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Printer.GetGlobalValueSymbol(MO.getGlobal());
}
MCSymbol *MSP430MCInstLower::
GetExternalSymbolSymbol(const MachineOperand &MO) const {
- SmallString<128> Name;
- Name += Printer.MAI->getGlobalPrefix();
- Name += MO.getSymbolName();
-
switch (MO.getTargetFlags()) {
default: assert(0 && "Unknown target flag on GV operand");
case 0: break;
}
- return Ctx.GetOrCreateSymbol(Name.str());
+ return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
}
MCSymbol *MSP430MCInstLower::
diff --git a/lib/Target/MSP430/AsmPrinter/Makefile b/lib/Target/MSP430/AsmPrinter/Makefile
index 4f340c6..c8a44a1 100644
--- a/lib/Target/MSP430/AsmPrinter/Makefile
+++ b/lib/Target/MSP430/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMMSP430AsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' MSP430 target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt
index 60e0bb1..29abe46 100644
--- a/lib/Target/MSP430/CMakeLists.txt
+++ b/lib/Target/MSP430/CMakeLists.txt
@@ -11,9 +11,10 @@ tablegen(MSP430GenCallingConv.inc -gen-callingconv)
tablegen(MSP430GenSubtarget.inc -gen-subtarget)
add_llvm_target(MSP430CodeGen
- MSP430InstrInfo.cpp
+ MSP430BranchSelector.cpp
MSP430ISelDAGToDAG.cpp
MSP430ISelLowering.cpp
+ MSP430InstrInfo.cpp
MSP430MCAsmInfo.cpp
MSP430RegisterInfo.cpp
MSP430Subtarget.cpp
diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h
index 1ff178d..e742118 100644
--- a/lib/Target/MSP430/MSP430.h
+++ b/lib/Target/MSP430/MSP430.h
@@ -39,6 +39,8 @@ namespace llvm {
FunctionPass *createMSP430ISelDag(MSP430TargetMachine &TM,
CodeGenOpt::Level OptLevel);
+ FunctionPass *createMSP430BranchSelectionPass();
+
extern Target TheMSP430Target;
} // end namespace llvm;
diff --git a/lib/Target/MSP430/MSP430.td b/lib/Target/MSP430/MSP430.td
index 870a3df..fe533d3 100644
--- a/lib/Target/MSP430/MSP430.td
+++ b/lib/Target/MSP430/MSP430.td
@@ -48,8 +48,14 @@ include "MSP430CallingConv.td"
include "MSP430InstrInfo.td"
-def MSP430InstrInfo : InstrInfo {}
-
+def MSP430InstrInfo : InstrInfo {
+ // Define how we want to layout our TargetSpecific information field... This
+ // should be kept up-to-date with the fields in the MSP430InstrInfo.h file.
+ let TSFlagsFields = ["FormBits",
+ "Size"];
+ let TSFlagsShifts = [0,
+ 2];
+}
def MSP430InstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
diff --git a/lib/Target/MSP430/MSP430BranchSelector.cpp b/lib/Target/MSP430/MSP430BranchSelector.cpp
new file mode 100644
index 0000000..836e425
--- /dev/null
+++ b/lib/Target/MSP430/MSP430BranchSelector.cpp
@@ -0,0 +1,179 @@
+//===-- MSP430BranchSelector.cpp - Emit long conditional branches--*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that scans a machine function to determine which
+// conditional branches need more than 10 bits of displacement to reach their
+// target basic block. It does this in two passes; a calculation of basic block
+// positions pass, and a branch psuedo op to machine branch opcode pass. This
+// pass should be run last, just before the assembly printer.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "msp430-branch-select"
+#include "MSP430.h"
+#include "MSP430InstrInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MathExtras.h"
+using namespace llvm;
+
+STATISTIC(NumExpanded, "Number of branches expanded to long format");
+
+namespace {
+ struct MSP430BSel : public MachineFunctionPass {
+ static char ID;
+ MSP430BSel() : MachineFunctionPass(&ID) {}
+
+ /// BlockSizes - The sizes of the basic blocks in the function.
+ std::vector<unsigned> BlockSizes;
+
+ virtual bool runOnMachineFunction(MachineFunction &Fn);
+
+ virtual const char *getPassName() const {
+ return "MSP430 Branch Selector";
+ }
+ };
+ char MSP430BSel::ID = 0;
+}
+
+/// createMSP430BranchSelectionPass - returns an instance of the Branch
+/// Selection Pass
+///
+FunctionPass *llvm::createMSP430BranchSelectionPass() {
+ return new MSP430BSel();
+}
+
+bool MSP430BSel::runOnMachineFunction(MachineFunction &Fn) {
+ const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
+ // Give the blocks of the function a dense, in-order, numbering.
+ Fn.RenumberBlocks();
+ BlockSizes.resize(Fn.getNumBlockIDs());
+
+ // Measure each MBB and compute a size for the entire function.
+ unsigned FuncSize = 0;
+ for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
+ ++MFI) {
+ MachineBasicBlock *MBB = MFI;
+
+ unsigned BlockSize = 0;
+ for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
+ MBBI != EE; ++MBBI)
+ BlockSize += TII->GetInstSizeInBytes(MBBI);
+
+ BlockSizes[MBB->getNumber()] = BlockSize;
+ FuncSize += BlockSize;
+ }
+
+ // If the entire function is smaller than the displacement of a branch field,
+ // we know we don't need to shrink any branches in this function. This is a
+ // common case.
+ if (FuncSize < (1 << 9)) {
+ BlockSizes.clear();
+ return false;
+ }
+
+ // For each conditional branch, if the offset to its destination is larger
+ // than the offset field allows, transform it into a long branch sequence
+ // like this:
+ // short branch:
+ // bCC MBB
+ // long branch:
+ // b!CC $PC+6
+ // b MBB
+ //
+ bool MadeChange = true;
+ bool EverMadeChange = false;
+ while (MadeChange) {
+ // Iteratively expand branches until we reach a fixed point.
+ MadeChange = false;
+
+ for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
+ ++MFI) {
+ MachineBasicBlock &MBB = *MFI;
+ unsigned MBBStartOffset = 0;
+ for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
+ I != E; ++I) {
+ if ((I->getOpcode() != MSP430::JCC || I->getOperand(0).isImm()) &&
+ I->getOpcode() != MSP430::JMP) {
+ MBBStartOffset += TII->GetInstSizeInBytes(I);
+ continue;
+ }
+
+ // Determine the offset from the current branch to the destination
+ // block.
+ MachineBasicBlock *Dest = I->getOperand(0).getMBB();
+
+ int BranchSize;
+ if (Dest->getNumber() <= MBB.getNumber()) {
+ // If this is a backwards branch, the delta is the offset from the
+ // start of this block to this branch, plus the sizes of all blocks
+ // from this block to the dest.
+ BranchSize = MBBStartOffset;
+
+ for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i)
+ BranchSize += BlockSizes[i];
+ } else {
+ // Otherwise, add the size of the blocks between this block and the
+ // dest to the number of bytes left in this block.
+ BranchSize = -MBBStartOffset;
+
+ for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i)
+ BranchSize += BlockSizes[i];
+ }
+
+ // If this branch is in range, ignore it.
+ if (isInt<10>(BranchSize)) {
+ MBBStartOffset += 2;
+ continue;
+ }
+
+ // Otherwise, we have to expand it to a long branch.
+ unsigned NewSize;
+ MachineInstr *OldBranch = I;
+ DebugLoc dl = OldBranch->getDebugLoc();
+
+ if (I->getOpcode() == MSP430::JMP) {
+ NewSize = 4;
+ } else {
+ // The BCC operands are:
+ // 0. MSP430 branch predicate
+ // 1. Target MBB
+ SmallVector<MachineOperand, 1> Cond;
+ Cond.push_back(I->getOperand(1));
+
+ // Jump over the uncond branch inst (i.e. $+6) on opposite condition.
+ TII->ReverseBranchCondition(Cond);
+ BuildMI(MBB, I, dl, TII->get(MSP430::JCC))
+ .addImm(4).addOperand(Cond[0]);
+
+ NewSize = 6;
+ }
+ // Uncond branch to the real destination.
+ I = BuildMI(MBB, I, dl, TII->get(MSP430::B)).addMBB(Dest);
+
+ // Remove the old branch from the function.
+ OldBranch->eraseFromParent();
+
+ // Remember that this instruction is NewSize bytes, increase the size of the
+ // block by NewSize-2, remember to iterate.
+ BlockSizes[MBB.getNumber()] += NewSize-2;
+ MBBStartOffset += NewSize;
+
+ ++NumExpanded;
+ MadeChange = true;
+ }
+ }
+ EverMadeChange |= MadeChange;
+ }
+
+ BlockSizes.clear();
+ return true;
+}
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index d3dce4b..b794911 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -675,21 +675,53 @@ static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,
case ISD::SETULE:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETUGE:
+ // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to
+ // fold constant into instruction.
+ if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
+ LHS = RHS;
+ RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
+ TCC = MSP430CC::COND_LO;
+ break;
+ }
TCC = MSP430CC::COND_HS; // aka COND_C
break;
case ISD::SETUGT:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETULT:
+ // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to
+ // fold constant into instruction.
+ if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
+ LHS = RHS;
+ RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
+ TCC = MSP430CC::COND_HS;
+ break;
+ }
TCC = MSP430CC::COND_LO; // aka COND_NC
break;
case ISD::SETLE:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETGE:
+ // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to
+ // fold constant into instruction.
+ if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
+ LHS = RHS;
+ RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
+ TCC = MSP430CC::COND_L;
+ break;
+ }
TCC = MSP430CC::COND_GE;
break;
case ISD::SETGT:
std::swap(LHS, RHS); // FALLTHROUGH
case ISD::SETLT:
+ // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to
+ // fold constant into instruction.
+ if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
+ LHS = RHS;
+ RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
+ TCC = MSP430CC::COND_GE;
+ break;
+ }
TCC = MSP430CC::COND_L;
break;
}
@@ -723,6 +755,8 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
// If we are doing an AND and testing against zero, then the CMP
// will not be generated. The AND (or BIT) will generate the condition codes,
// but they are different from CMP.
+ // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
+ // lowering & isel wouldn't diverge.
bool andCC = false;
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
if (RHSC->isNullValue() && LHS.hasOneUse() &&
@@ -750,11 +784,11 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
case MSP430CC::COND_HS:
// Res = SRW & 1, no processing is required
break;
- case MSP430CC::COND_LO:
+ case MSP430CC::COND_LO:
// Res = ~(SRW & 1)
Invert = true;
break;
- case MSP430CC::COND_NE:
+ case MSP430CC::COND_NE:
if (andCC) {
// C = ~Z, thus Res = SRW & 1, no processing is required
} else {
@@ -762,7 +796,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
Shift = true;
}
break;
- case MSP430CC::COND_E:
+ case MSP430CC::COND_E:
if (andCC) {
// C = ~Z, thus Res = ~(SRW & 1)
} else {
@@ -776,7 +810,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
SDValue One = DAG.getConstant(1, VT);
if (Convert) {
SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW,
- MVT::i16, Flag);
+ MVT::i16, Flag);
if (Shift)
// FIXME: somewhere this is turned into a SRL, lower it MSP specific?
SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);
@@ -933,6 +967,31 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
}
}
+bool MSP430TargetLowering::isTruncateFree(const Type *Ty1,
+ const Type *Ty2) const {
+ if (!Ty1->isInteger() || !Ty2->isInteger())
+ return false;
+
+ return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits());
+}
+
+bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
+ if (!VT1.isInteger() || !VT2.isInteger())
+ return false;
+
+ return (VT1.getSizeInBits() > VT2.getSizeInBits());
+}
+
+bool MSP430TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const {
+ // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.
+ return 0 && Ty1->isInteger(8) && Ty2->isInteger(16);
+}
+
+bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const {
+ // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.
+ return 0 && VT1 == MVT::i8 && VT2 == MVT::i16;
+}
+
//===----------------------------------------------------------------------===//
// Other Lowering Code
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h
index 4921500..6152a05 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/lib/Target/MSP430/MSP430ISelLowering.h
@@ -99,6 +99,23 @@ namespace llvm {
std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const;
+ /// isTruncateFree - Return true if it's free to truncate a value of type
+ /// Ty1 to type Ty2. e.g. On msp430 it's free to truncate a i16 value in
+ /// register R15W to i8 by referencing its sub-register R15B.
+ virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const;
+ virtual bool isTruncateFree(EVT VT1, EVT VT2) const;
+
+ /// isZExtFree - Return true if any actual instruction that defines a value
+ /// of type Ty1 implicit zero-extends the value to Ty2 in the result
+ /// register. This does not necessarily include registers defined in unknown
+ /// ways, such as incoming arguments, or copies from unknown virtual
+ /// registers. Also, if isTruncateFree(Ty2, Ty1) is true, this does not
+ /// necessarily apply to truncate instructions. e.g. on msp430, all
+ /// instructions that define 8-bit values implicit zero-extend the result
+ /// out to 16 bits.
+ virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const;
+ virtual bool isZExtFree(EVT VT1, EVT VT2) const;
+
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB,
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
diff --git a/lib/Target/MSP430/MSP430InstrFormats.td b/lib/Target/MSP430/MSP430InstrFormats.td
index 61b3399..4ccc7df 100644
--- a/lib/Target/MSP430/MSP430InstrFormats.td
+++ b/lib/Target/MSP430/MSP430InstrFormats.td
@@ -11,8 +11,48 @@
// Describe MSP430 instructions format here
//
+// Format specifies the encoding used by the instruction. This is part of the
+// ad-hoc solution used to emit machine instruction encodings by our machine
+// code emitter.
+class Format<bits<2> val> {
+ bits<2> Value = val;
+}
+
+def PseudoFrm : Format<0>;
+def SingleOpFrm : Format<1>;
+def DoubleOpFrm : Format<2>;
+def CondJumpFrm : Format<3>;
+
+class SourceMode<bits<2> val> {
+ bits<2> Value = val;
+}
+
+def SrcReg : SourceMode<0>;
+def SrcMem : SourceMode<1>;
+def SrcIndReg : SourceMode<2>;
+def SrcPostInc : SourceMode<3>;
+def SrcImm : SourceMode<3>;
+
+class DestMode<bit val> {
+ bit Value = val;
+}
+
+def DstReg : DestMode<0>;
+def DstMem : DestMode<1>;
+
+class SizeVal<bits<3> val> {
+ bits<3> Value = val;
+}
+
+def SizeUnknown : SizeVal<0>; // Unknown / unset size
+def SizeSpecial : SizeVal<1>; // Special instruction, e.g. pseudo
+def Size2Bytes : SizeVal<2>;
+def Size4Bytes : SizeVal<3>;
+def Size6Bytes : SizeVal<4>;
+
// Generic MSP430 Format
-class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction {
+class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f,
+ string asmstr> : Instruction {
field bits<16> Inst;
let Namespace = "MSP430";
@@ -20,48 +60,150 @@ class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction {
dag OutOperandList = outs;
dag InOperandList = ins;
+ Format Form = f;
+ bits<2> FormBits = Form.Value;
+
+ SizeVal Sz = sz;
+ bits<3> Size = Sz.Value;
+
let AsmString = asmstr;
}
// FIXME: Create different classes for different addressing modes.
// MSP430 Double Operand (Format I) Instructions
-class IForm<bits<4> opcode, bit ad, bit bw, bits<2> as,
+class IForm<bits<4> opcode, DestMode dest, bit bw, SourceMode src, SizeVal sz,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, asmstr> {
+ : MSP430Inst<outs, ins, sz, DoubleOpFrm, asmstr> {
let Pattern = pattern;
+
+ DestMode ad = dest;
+ SourceMode as = src;
let Inst{12-15} = opcode;
- let Inst{7} = ad;
+ let Inst{7} = ad.Value;
let Inst{6} = bw;
- let Inst{4-5} = as;
+ let Inst{4-5} = as.Value;
}
+// 8 bit IForm instructions
+class IForm8<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm<opcode, dest, 1, src, sz, outs, ins, asmstr, pattern>;
+
+class I8rr<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+
+class I8ri<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I8rm<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I8mr<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I8mi<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>;
+
+class I8mm<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>;
+
+// 16 bit IForm instructions
+class IForm16<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm<opcode, dest, 0, src, sz, outs, ins, asmstr, pattern>;
+
+class I16rr<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+
+class I16ri<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I16rm<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I16mr<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class I16mi<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>;
+
+class I16mm<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>;
+
// MSP430 Single Operand (Format II) Instructions
-class IIForm<bits<9> opcode, bit bw, bits<2> ad,
+class IIForm<bits<9> opcode, bit bw, SourceMode src, SizeVal sz,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, asmstr> {
+ : MSP430Inst<outs, ins, sz, SingleOpFrm, asmstr> {
let Pattern = pattern;
+ SourceMode as = src;
+
let Inst{7-15} = opcode;
let Inst{6} = bw;
- let Inst{4-5} = ad;
+ let Inst{4-5} = as.Value;
}
+// 8 bit IIForm instructions
+class IIForm8<bits<9> opcode, SourceMode src, SizeVal sz,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm<opcode, 1, src, sz, outs, ins, asmstr, pattern>;
+
+class II8r<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+
+class II8m<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class II8i<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+
+// 16 bit IIForm instructions
+class IIForm16<bits<9> opcode, SourceMode src, SizeVal sz,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm<opcode, 0, src, sz, outs, ins, asmstr, pattern>;
+
+class II16r<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm16<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+
+class II16m<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm16<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+
+class II16i<bits<9> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm16<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+
// MSP430 Conditional Jumps Instructions
-class CJForm<bits<3> opcode, bits<3> cond, bit s,
+class CJForm<bits<3> opcode, bits<3> cond,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, asmstr> {
+ : MSP430Inst<outs, ins, Size2Bytes, CondJumpFrm, asmstr> {
let Pattern = pattern;
let Inst{13-15} = opcode;
let Inst{10-12} = cond;
- let Inst{9} = s;
}
// Pseudo instructions
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, asmstr> {
+ : MSP430Inst<outs, ins, SizeSpecial, PseudoFrm, asmstr> {
let Pattern = pattern;
let Inst{15-0} = 0;
}
diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp
index 2ae6759..9dc69e0 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.cpp
+++ b/lib/Target/MSP430/MSP430InstrInfo.cpp
@@ -344,3 +344,45 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
}
return Count;
}
+
+/// GetInstSize - Return the number of bytes of code the specified
+/// instruction may be. This returns the maximum number of bytes.
+///
+unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
+ const TargetInstrDesc &Desc = MI->getDesc();
+
+ switch (Desc.TSFlags & MSP430II::SizeMask) {
+ default:
+ switch (Desc.getOpcode()) {
+ default:
+ assert(0 && "Unknown instruction size!");
+ case TargetInstrInfo::DBG_LABEL:
+ case TargetInstrInfo::EH_LABEL:
+ case TargetInstrInfo::IMPLICIT_DEF:
+ case TargetInstrInfo::KILL:
+ return 0;
+ case TargetInstrInfo::INLINEASM: {
+ const MachineFunction *MF = MI->getParent()->getParent();
+ const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
+ return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(),
+ *MF->getTarget().getMCAsmInfo());
+ }
+ }
+ case MSP430II::SizeSpecial:
+ switch (MI->getOpcode()) {
+ default:
+ assert(0 && "Unknown instruction size!");
+ case MSP430::SAR8r1c:
+ case MSP430::SAR16r1c:
+ return 4;
+ }
+ case MSP430II::Size2Bytes:
+ return 2;
+ case MSP430II::Size4Bytes:
+ return 4;
+ case MSP430II::Size6Bytes:
+ return 6;
+ }
+
+ return 6;
+}
diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h
index e4ceeb9..6ef4b0a 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.h
+++ b/lib/Target/MSP430/MSP430InstrInfo.h
@@ -21,6 +21,22 @@ namespace llvm {
class MSP430TargetMachine;
+/// MSP430II - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace MSP430II {
+ enum {
+ SizeShift = 2,
+ SizeMask = 7 << SizeShift,
+
+ SizeUnknown = 0 << SizeShift,
+ SizeSpecial = 1 << SizeShift,
+ Size2Bytes = 2 << SizeShift,
+ Size4Bytes = 3 << SizeShift,
+ Size6Bytes = 4 << SizeShift
+ };
+}
+
class MSP430InstrInfo : public TargetInstrInfoImpl {
const MSP430RegisterInfo RI;
MSP430TargetMachine &TM;
@@ -59,6 +75,8 @@ public:
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const;
+ unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
+
// Branch folding goodness
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
bool isUnpredicatedTerminator(const MachineInstr *MI) const;
diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td
index 022d171..cd502cf 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.td
+++ b/lib/Target/MSP430/MSP430InstrInfo.td
@@ -157,23 +157,35 @@ def NOP : Pseudo<(outs), (ins), "nop", []>;
// FIXME: Provide proper encoding!
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
- def RET : Pseudo<(outs), (ins), "ret", [(MSP430retflag)]>;
- def RETI : Pseudo<(outs), (ins), "reti", [(MSP430retiflag)]>;
+ def RET : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs), (ins), "ret", [(MSP430retflag)]>;
+ def RETI : II16r<0x0, (outs), (ins), "reti", [(MSP430retiflag)]>;
}
let isBranch = 1, isTerminator = 1 in {
+// FIXME: expand opcode & cond field for branches!
+
// Direct branch
-let isBarrier = 1 in
- def JMP : Pseudo<(outs), (ins brtarget:$dst),
+let isBarrier = 1 in {
+ // Short branch
+ def JMP : CJForm<0, 0,
+ (outs), (ins brtarget:$dst),
"jmp\t$dst",
[(br bb:$dst)]>;
+ // Long branch
+ def B : I16ri<0,
+ (outs), (ins brtarget:$dst),
+ "br\t$dst",
+ []>;
+}
// Conditional branches
let Uses = [SRW] in
- def JCC : Pseudo<(outs), (ins brtarget:$dst, cc:$cc),
- "j$cc\t$dst",
- [(MSP430brcc bb:$dst, imm:$cc)]>;
+ def JCC : CJForm<0, 0,
+ (outs), (ins brtarget:$dst, cc:$cc),
+ "j$cc\t$dst",
+ [(MSP430brcc bb:$dst, imm:$cc)]>;
} // isBranch, isTerminator
//===----------------------------------------------------------------------===//
@@ -186,12 +198,15 @@ let isCall = 1 in
// registers are added manually.
let Defs = [R12W, R13W, R14W, R15W, SRW],
Uses = [SPW] in {
- def CALLi : Pseudo<(outs), (ins i16imm:$dst, variable_ops),
- "call\t$dst", [(MSP430call imm:$dst)]>;
- def CALLr : Pseudo<(outs), (ins GR16:$dst, variable_ops),
- "call\t$dst", [(MSP430call GR16:$dst)]>;
- def CALLm : Pseudo<(outs), (ins memsrc:$dst, variable_ops),
- "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>;
+ def CALLi : II16i<0x0,
+ (outs), (ins i16imm:$dst, variable_ops),
+ "call\t$dst", [(MSP430call imm:$dst)]>;
+ def CALLr : II16r<0x0,
+ (outs), (ins GR16:$dst, variable_ops),
+ "call\t$dst", [(MSP430call GR16:$dst)]>;
+ def CALLm : II16m<0x0,
+ (outs), (ins memsrc:$dst, variable_ops),
+ "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>;
}
@@ -200,10 +215,12 @@ let isCall = 1 in
//
let Defs = [SPW], Uses = [SPW], neverHasSideEffects=1 in {
let mayLoad = 1 in
-def POP16r : Pseudo<(outs GR16:$reg), (ins), "pop.w\t$reg", []>;
+def POP16r : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$reg), (ins), "pop.w\t$reg", []>;
let mayStore = 1 in
-def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>;
+def PUSH16r : II16r<0x0,
+ (outs), (ins GR16:$reg), "push.w\t$reg",[]>;
}
//===----------------------------------------------------------------------===//
@@ -211,45 +228,55 @@ def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>;
// FIXME: Provide proper encoding!
let neverHasSideEffects = 1 in {
-def MOV8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src),
- "mov.b\t{$src, $dst}",
- []>;
-def MOV16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "mov.w\t{$src, $dst}",
- []>;
+def MOV8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src),
+ "mov.b\t{$src, $dst}",
+ []>;
+def MOV16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "mov.w\t{$src, $dst}",
+ []>;
}
// FIXME: Provide proper encoding!
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
-def MOV8ri : Pseudo<(outs GR8:$dst), (ins i8imm:$src),
- "mov.b\t{$src, $dst}",
- [(set GR8:$dst, imm:$src)]>;
-def MOV16ri : Pseudo<(outs GR16:$dst), (ins i16imm:$src),
- "mov.w\t{$src, $dst}",
- [(set GR16:$dst, imm:$src)]>;
+def MOV8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins i8imm:$src),
+ "mov.b\t{$src, $dst}",
+ [(set GR8:$dst, imm:$src)]>;
+def MOV16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins i16imm:$src),
+ "mov.w\t{$src, $dst}",
+ [(set GR16:$dst, imm:$src)]>;
}
let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in {
-def MOV8rm : Pseudo<(outs GR8:$dst), (ins memsrc:$src),
- "mov.b\t{$src, $dst}",
- [(set GR8:$dst, (load addr:$src))]>;
-def MOV16rm : Pseudo<(outs GR16:$dst), (ins memsrc:$src),
- "mov.w\t{$src, $dst}",
- [(set GR16:$dst, (load addr:$src))]>;
+def MOV8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins memsrc:$src),
+ "mov.b\t{$src, $dst}",
+ [(set GR8:$dst, (load addr:$src))]>;
+def MOV16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins memsrc:$src),
+ "mov.w\t{$src, $dst}",
+ [(set GR16:$dst, (load addr:$src))]>;
}
-def MOVZX16rr8 : Pseudo<(outs GR16:$dst), (ins GR8:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zext GR8:$src))]>;
-def MOVZX16rm8 : Pseudo<(outs GR16:$dst), (ins memsrc:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zextloadi16i8 addr:$src))]>;
+def MOVZX16rr8 : I8rr<0x0,
+ (outs GR16:$dst), (ins GR8:$src),
+ "mov.b\t{$src, $dst}",
+ [(set GR16:$dst, (zext GR8:$src))]>;
+def MOVZX16rm8 : I8rm<0x0,
+ (outs GR16:$dst), (ins memsrc:$src),
+ "mov.b\t{$src, $dst}",
+ [(set GR16:$dst, (zextloadi16i8 addr:$src))]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb" in {
-def MOV8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR16:$base),
- "mov.b\t{@$base+, $dst}", []>;
-def MOV16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$base),
- "mov.w\t{@$base+, $dst}", []>;
+def MOV8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb), (ins GR16:$base),
+ "mov.b\t{@$base+, $dst}", []>;
+def MOV16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb), (ins GR16:$base),
+ "mov.w\t{@$base+, $dst}", []>;
}
// Any instruction that defines a 8-bit result leaves the high half of the
@@ -267,27 +294,32 @@ def def8 : PatLeaf<(i8 GR8:$src), [{
def : Pat<(i16 (zext def8:$src)),
(SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>;
-
-def MOV8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "mov.b\t{$src, $dst}",
- [(store (i8 imm:$src), addr:$dst)]>;
-def MOV16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "mov.w\t{$src, $dst}",
- [(store (i16 imm:$src), addr:$dst)]>;
-
-def MOV8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "mov.b\t{$src, $dst}",
- [(store GR8:$src, addr:$dst)]>;
-def MOV16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "mov.w\t{$src, $dst}",
- [(store GR16:$src, addr:$dst)]>;
-
-def MOV8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "mov.b\t{$src, $dst}",
- [(store (i8 (load addr:$src)), addr:$dst)]>;
-def MOV16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "mov.w\t{$src, $dst}",
- [(store (i16 (load addr:$src)), addr:$dst)]>;
+def MOV8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "mov.b\t{$src, $dst}",
+ [(store (i8 imm:$src), addr:$dst)]>;
+def MOV16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "mov.w\t{$src, $dst}",
+ [(store (i16 imm:$src), addr:$dst)]>;
+
+def MOV8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "mov.b\t{$src, $dst}",
+ [(store GR8:$src, addr:$dst)]>;
+def MOV16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "mov.w\t{$src, $dst}",
+ [(store GR16:$src, addr:$dst)]>;
+
+def MOV8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "mov.b\t{$src, $dst}",
+ [(store (i8 (load addr:$src)), addr:$dst)]>;
+def MOV16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "mov.w\t{$src, $dst}",
+ [(store (i16 (load addr:$src)), addr:$dst)]>;
//===----------------------------------------------------------------------===//
// Arithmetic Instructions
@@ -297,496 +329,624 @@ let isTwoAddress = 1 in {
let Defs = [SRW] in {
let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y
-// FIXME: Provide proper encoding!
-def ADD8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def ADD16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
+
+def ADD8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "add.b\t{$src2, $dst}",
+ [(set GR8:$dst, (add GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def ADD16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "add.w\t{$src2, $dst}",
+ [(set GR16:$dst, (add GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
}
-def ADD8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def ADD16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def ADD8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "add.b\t{$src2, $dst}",
+ [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def ADD16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "add.w\t{$src2, $dst}",
+ [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1,
Constraints = "$base = $base_wb, $src1 = $dst" in {
-def ADD8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base),
- "add.b\t{@$base+, $dst}", []>;
-def ADD16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base),
+def ADD8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb),
+ (ins GR8:$src1, GR16:$base),
+ "add.b\t{@$base+, $dst}", []>;
+def ADD16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb),
+ (ins GR16:$src1, GR16:$base),
"add.w\t{@$base+, $dst}", []>;
}
-def ADD8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def ADD16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
+def ADD8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "add.b\t{$src2, $dst}",
+ [(set GR8:$dst, (add GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def ADD16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "add.w\t{$src2, $dst}",
+ [(set GR16:$dst, (add GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
let isTwoAddress = 0 in {
-def ADD8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def ADD16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def ADD8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def ADD16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def ADD8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def ADD16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def ADD8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "add.b\t{$src, $dst}",
+ [(store (add (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def ADD16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "add.w\t{$src, $dst}",
+ [(store (add (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def ADD8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "add.b\t{$src, $dst}",
+ [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def ADD16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "add.w\t{$src, $dst}",
+ [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def ADD8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "add.b\t{$src, $dst}",
+ [(store (add (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def ADD16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "add.w\t{$src, $dst}",
+ [(store (add (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
let Uses = [SRW] in {
let isCommutable = 1 in { // X = ADDC Y, Z == X = ADDC Z, Y
-def ADC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def ADC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
+def ADC8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "addc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def ADC16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "addc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
} // isCommutable
-def ADC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def ADC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def ADC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def ADC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def ADC8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "addc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (adde GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def ADC16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "addc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (adde GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
+
+def ADC8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "addc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def ADC16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "addc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let isTwoAddress = 0 in {
-def ADC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def ADC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def ADC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def ADC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def ADC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def ADC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def ADC8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "addc.b\t{$src, $dst}",
+ [(store (adde (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def ADC16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "addc.w\t{$src, $dst}",
+ [(store (adde (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def ADC8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "addc.b\t{$src, $dst}",
+ [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def ADC16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "addc.w\t{$src, $dst}",
+ [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def ADC8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "addc.b\t{$src, $dst}",
+ [(store (adde (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def ADC16mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "addc.w\t{$src, $dst}",
+ [(store (adde (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
} // Uses = [SRW]
let isCommutable = 1 in { // X = AND Y, Z == X = AND Z, Y
-def AND8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def AND16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
+def AND8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "and.b\t{$src2, $dst}",
+ [(set GR8:$dst, (and GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def AND16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "and.w\t{$src2, $dst}",
+ [(set GR16:$dst, (and GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
}
-def AND8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def AND16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def AND8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def AND16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def AND8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "and.b\t{$src2, $dst}",
+ [(set GR8:$dst, (and GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def AND16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "and.w\t{$src2, $dst}",
+ [(set GR16:$dst, (and GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
+
+def AND8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "and.b\t{$src2, $dst}",
+ [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def AND16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "and.w\t{$src2, $dst}",
+ [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1,
Constraints = "$base = $base_wb, $src1 = $dst" in {
-def AND8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base),
- "and.b\t{@$base+, $dst}", []>;
-def AND16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base),
- "and.w\t{@$base+, $dst}", []>;
+def AND8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb),
+ (ins GR8:$src1, GR16:$base),
+ "and.b\t{@$base+, $dst}", []>;
+def AND16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb),
+ (ins GR16:$src1, GR16:$base),
+ "and.w\t{@$base+, $dst}", []>;
}
let isTwoAddress = 0 in {
-def AND8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def AND16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def AND8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def AND16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def AND8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def AND16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def AND8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "and.b\t{$src, $dst}",
+ [(store (and (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def AND16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "and.w\t{$src, $dst}",
+ [(store (and (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def AND8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "and.b\t{$src, $dst}",
+ [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def AND16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "and.w\t{$src, $dst}",
+ [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def AND8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "and.b\t{$src, $dst}",
+ [(store (and (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def AND16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "and.w\t{$src, $dst}",
+ [(store (and (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
let isCommutable = 1 in { // X = OR Y, Z == X = OR Z, Y
-def OR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>;
-def OR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>;
+def OR8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "bis.b\t{$src2, $dst}",
+ [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>;
+def OR16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "bis.w\t{$src2, $dst}",
+ [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>;
}
-def OR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>;
-def OR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>;
-
-def OR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>;
-def OR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>;
+def OR8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "bis.b\t{$src2, $dst}",
+ [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>;
+def OR16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "bis.w\t{$src2, $dst}",
+ [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>;
+
+def OR8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "bis.b\t{$src2, $dst}",
+ [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>;
+def OR16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "bis.w\t{$src2, $dst}",
+ [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1,
Constraints = "$base = $base_wb, $src1 = $dst" in {
-def OR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base),
+def OR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb),
+ (ins GR8:$src1, GR16:$base),
"bis.b\t{@$base+, $dst}", []>;
-def OR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base),
- "bis.w\t{@$base+, $dst}", []>;
+def OR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb),
+ (ins GR16:$src1, GR16:$base),
+ "bis.w\t{@$base+, $dst}", []>;
}
let isTwoAddress = 0 in {
-def OR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>;
-def OR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>;
-
-def OR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>;
-def OR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>;
-
-def OR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (i8 (load addr:$dst)),
- (i8 (load addr:$src))), addr:$dst)]>;
-def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (i16 (load addr:$dst)),
- (i16 (load addr:$src))), addr:$dst)]>;
+def OR8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "bis.b\t{$src, $dst}",
+ [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>;
+def OR16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "bis.w\t{$src, $dst}",
+ [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>;
+
+def OR8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "bis.b\t{$src, $dst}",
+ [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+def OR16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "bis.w\t{$src, $dst}",
+ [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>;
+
+def OR8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "bis.b\t{$src, $dst}",
+ [(store (or (i8 (load addr:$dst)),
+ (i8 (load addr:$src))), addr:$dst)]>;
+def OR16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "bis.w\t{$src, $dst}",
+ [(store (or (i16 (load addr:$dst)),
+ (i16 (load addr:$src))), addr:$dst)]>;
}
// bic does not modify condition codes
-def BIC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "bic.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>;
-def BIC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "bic.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>;
-
-def BIC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "bic.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>;
-def BIC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "bic.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>;
+def BIC8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "bic.b\t{$src2, $dst}",
+ [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>;
+def BIC16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "bic.w\t{$src2, $dst}",
+ [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>;
+
+def BIC8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "bic.b\t{$src2, $dst}",
+ [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>;
+def BIC16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "bic.w\t{$src2, $dst}",
+ [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>;
let isTwoAddress = 0 in {
-def BIC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "bic.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>;
-def BIC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "bic.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>;
-
-def BIC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "bic.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (not (i8 (load addr:$src)))), addr:$dst)]>;
-def BIC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "bic.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (not (i16 (load addr:$src)))), addr:$dst)]>;
+def BIC8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "bic.b\t{$src, $dst}",
+ [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>;
+def BIC16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "bic.w\t{$src, $dst}",
+ [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>;
+
+def BIC8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "bic.b\t{$src, $dst}",
+ [(store (and (load addr:$dst),
+ (not (i8 (load addr:$src)))), addr:$dst)]>;
+def BIC16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "bic.w\t{$src, $dst}",
+ [(store (and (load addr:$dst),
+ (not (i16 (load addr:$src)))), addr:$dst)]>;
}
let isCommutable = 1 in { // X = XOR Y, Z == X = XOR Z, Y
-def XOR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def XOR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
+def XOR8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "xor.b\t{$src2, $dst}",
+ [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def XOR16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "xor.w\t{$src2, $dst}",
+ [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
}
-def XOR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def XOR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def XOR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def XOR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def XOR8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "xor.b\t{$src2, $dst}",
+ [(set GR8:$dst, (xor GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def XOR16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "xor.w\t{$src2, $dst}",
+ [(set GR16:$dst, (xor GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
+
+def XOR8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "xor.b\t{$src2, $dst}",
+ [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def XOR16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "xor.w\t{$src2, $dst}",
+ [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1,
Constraints = "$base = $base_wb, $src1 = $dst" in {
-def XOR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base),
- "xor.b\t{@$base+, $dst}", []>;
-def XOR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base),
- "xor.w\t{@$base+, $dst}", []>;
+def XOR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb),
+ (ins GR8:$src1, GR16:$base),
+ "xor.b\t{@$base+, $dst}", []>;
+def XOR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb),
+ (ins GR16:$src1, GR16:$base),
+ "xor.w\t{@$base+, $dst}", []>;
}
let isTwoAddress = 0 in {
-def XOR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def XOR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def XOR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def XOR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def XOR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def XOR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def XOR8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "xor.b\t{$src, $dst}",
+ [(store (xor (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def XOR16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "xor.w\t{$src, $dst}",
+ [(store (xor (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def XOR8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "xor.b\t{$src, $dst}",
+ [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def XOR16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "xor.w\t{$src, $dst}",
+ [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def XOR8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "xor.b\t{$src, $dst}",
+ [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def XOR16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "xor.w\t{$src, $dst}",
+ [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
-def SUB8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def SUB16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
-
-def SUB8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def SUB16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def SUB8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def SUB16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def SUB8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "sub.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def SUB16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "sub.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
+
+def SUB8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "sub.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sub GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def SUB16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "sub.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sub GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
+
+def SUB8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "sub.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def SUB16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "sub.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let mayLoad = 1, hasExtraDefRegAllocReq = 1,
Constraints = "$base = $base_wb, $src1 = $dst" in {
-def SUB8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base),
- "sub.b\t{@$base+, $dst}", []>;
-def SUB16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base),
+def SUB8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR8:$dst, GR16:$base_wb),
+ (ins GR8:$src1, GR16:$base),
+ "sub.b\t{@$base+, $dst}", []>;
+def SUB16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
+ (outs GR16:$dst, GR16:$base_wb),
+ (ins GR16:$src1, GR16:$base),
"sub.w\t{@$base+, $dst}", []>;
}
let isTwoAddress = 0 in {
-def SUB8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def SUB16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def SUB8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def SUB16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def SUB8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def SUB16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def SUB8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "sub.b\t{$src, $dst}",
+ [(store (sub (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def SUB16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "sub.w\t{$src, $dst}",
+ [(store (sub (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def SUB8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "sub.b\t{$src, $dst}",
+ [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def SUB16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "sub.w\t{$src, $dst}",
+ [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def SUB8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "sub.b\t{$src, $dst}",
+ [(store (sub (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def SUB16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "sub.w\t{$src, $dst}",
+ [(store (sub (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
let Uses = [SRW] in {
-def SBC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def SBC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
-
-def SBC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def SBC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def SBC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def SBC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
+def SBC8rr : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
+ "subc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)),
+ (implicit SRW)]>;
+def SBC16rr : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "subc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)),
+ (implicit SRW)]>;
+
+def SBC8ri : I8ri<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
+ "subc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sube GR8:$src1, imm:$src2)),
+ (implicit SRW)]>;
+def SBC16ri : I16ri<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
+ "subc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sube GR16:$src1, imm:$src2)),
+ (implicit SRW)]>;
+
+def SBC8rm : I8rm<0x0,
+ (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2),
+ "subc.b\t{$src2, $dst}",
+ [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
+def SBC16rm : I16rm<0x0,
+ (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2),
+ "subc.w\t{$src2, $dst}",
+ [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))),
+ (implicit SRW)]>;
let isTwoAddress = 0 in {
-def SBC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SRW)]>;
-def SBC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SRW)]>;
-
-def SBC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-def SBC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SRW)]>;
-
-def SBC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
-def SBC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
- (implicit SRW)]>;
+def SBC8mr : I8mr<0x0,
+ (outs), (ins memdst:$dst, GR8:$src),
+ "subc.b\t{$src, $dst}",
+ [(store (sube (load addr:$dst), GR8:$src), addr:$dst),
+ (implicit SRW)]>;
+def SBC16mr : I16mr<0x0,
+ (outs), (ins memdst:$dst, GR16:$src),
+ "subc.w\t{$src, $dst}",
+ [(store (sube (load addr:$dst), GR16:$src), addr:$dst),
+ (implicit SRW)]>;
+
+def SBC8mi : I8mi<0x0,
+ (outs), (ins memdst:$dst, i8imm:$src),
+ "subc.b\t{$src, $dst}",
+ [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+def SBC16mi : I16mi<0x0,
+ (outs), (ins memdst:$dst, i16imm:$src),
+ "subc.w\t{$src, $dst}",
+ [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst),
+ (implicit SRW)]>;
+
+def SBC8mm : I8mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "subc.b\t{$src, $dst}",
+ [(store (sube (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
+def SBC16mm : I16mm<0x0,
+ (outs), (ins memdst:$dst, memsrc:$src),
+ "subc.w\t{$src, $dst}",
+ [(store (sube (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
+ (implicit SRW)]>;
}
} // Uses = [SRW]
-// FIXME: Provide proper encoding!
-def SAR8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src),
- "rra.b\t$dst",
- [(set GR8:$dst, (MSP430rra GR8:$src)),
- (implicit SRW)]>;
-def SAR16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "rra.w\t$dst",
- [(set GR16:$dst, (MSP430rra GR16:$src)),
- (implicit SRW)]>;
-
-def SHL8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src),
- "rla.b\t$dst",
- [(set GR8:$dst, (MSP430rla GR8:$src)),
- (implicit SRW)]>;
-def SHL16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "rla.w\t$dst",
- [(set GR16:$dst, (MSP430rla GR16:$src)),
- (implicit SRW)]>;
+// FIXME: memory variant!
+def SAR8r1 : II8r<0x0,
+ (outs GR8:$dst), (ins GR8:$src),
+ "rra.b\t$dst",
+ [(set GR8:$dst, (MSP430rra GR8:$src)),
+ (implicit SRW)]>;
+def SAR16r1 : II16r<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "rra.w\t$dst",
+ [(set GR16:$dst, (MSP430rra GR16:$src)),
+ (implicit SRW)]>;
+
+def SHL8r1 : I8rr<0x0,
+ (outs GR8:$dst), (ins GR8:$src),
+ "rla.b\t$dst",
+ [(set GR8:$dst, (MSP430rla GR8:$src)),
+ (implicit SRW)]>;
+def SHL16r1 : I16rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "rla.w\t$dst",
+ [(set GR16:$dst, (MSP430rla GR16:$src)),
+ (implicit SRW)]>;
def SAR8r1c : Pseudo<(outs GR8:$dst), (ins GR8:$src),
"clrc\n\t"
@@ -799,121 +959,154 @@ def SAR16r1c : Pseudo<(outs GR16:$dst), (ins GR16:$src),
[(set GR16:$dst, (MSP430rrc GR16:$src)),
(implicit SRW)]>;
-def SEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "sxt\t$dst",
- [(set GR16:$dst, (sext_inreg GR16:$src, i8)),
- (implicit SRW)]>;
+// FIXME: Memory sext's ?
+def SEXT16r : II16r<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "sxt\t$dst",
+ [(set GR16:$dst, (sext_inreg GR16:$src, i8)),
+ (implicit SRW)]>;
} // Defs = [SRW]
-def ZEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zext (trunc GR16:$src)))]>;
+def ZEXT16r : I8rr<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "mov.b\t{$src, $dst}",
+ [(set GR16:$dst, (zext (trunc GR16:$src)))]>;
-def SWPB16r : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "swpb\t$dst",
- [(set GR16:$dst, (bswap GR16:$src))]>;
+// FIXME: Memory bitswaps?
+def SWPB16r : II16r<0x0,
+ (outs GR16:$dst), (ins GR16:$src),
+ "swpb\t$dst",
+ [(set GR16:$dst, (bswap GR16:$src))]>;
} // isTwoAddress = 1
// Integer comparisons
let Defs = [SRW] in {
-def CMP8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2),
- "cmp.b\t{$src2, $src1}",
- [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>;
-def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2),
- "cmp.w\t{$src2, $src1}",
- [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>;
-
-def CMP8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2),
+def CMP8rr : I8rr<0x0,
+ (outs), (ins GR8:$src1, GR8:$src2),
+ "cmp.b\t{$src2, $src1}",
+ [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>;
+def CMP16rr : I16rr<0x0,
+ (outs), (ins GR16:$src1, GR16:$src2),
+ "cmp.w\t{$src2, $src1}",
+ [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>;
+
+def CMP8ri : I8ri<0x0,
+ (outs), (ins GR8:$src1, i8imm:$src2),
"cmp.b\t{$src2, $src1}",
[(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>;
-def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2),
- "cmp.w\t{$src2, $src1}",
- [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>;
-
-def CMP8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2),
- "cmp.b\t{$src2, $src1}",
- [(MSP430cmp (load addr:$src1),
- (i8 imm:$src2)), (implicit SRW)]>;
-def CMP16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2),
- "cmp.w\t{$src2, $src1}",
- [(MSP430cmp (load addr:$src1),
- (i16 imm:$src2)), (implicit SRW)]>;
-
-def CMP8rm : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2),
- "cmp.b\t{$src2, $src1}",
- [(MSP430cmp GR8:$src1, (load addr:$src2)), (implicit SRW)]>;
-def CMP16rm : Pseudo<(outs), (ins GR16:$src1, memsrc:$src2),
- "cmp.w\t{$src2, $src1}",
- [(MSP430cmp GR16:$src1, (load addr:$src2)), (implicit SRW)]>;
-
-def CMP8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2),
- "cmp.b\t{$src2, $src1}",
- [(MSP430cmp (load addr:$src1), GR8:$src2), (implicit SRW)]>;
-def CMP16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2),
- "cmp.w\t{$src2, $src1}",
- [(MSP430cmp (load addr:$src1), GR16:$src2), (implicit SRW)]>;
+def CMP16ri : I16ri<0x0,
+ (outs), (ins GR16:$src1, i16imm:$src2),
+ "cmp.w\t{$src2, $src1}",
+ [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>;
+
+def CMP8mi : I8mi<0x0,
+ (outs), (ins memsrc:$src1, i8imm:$src2),
+ "cmp.b\t{$src2, $src1}",
+ [(MSP430cmp (load addr:$src1),
+ (i8 imm:$src2)), (implicit SRW)]>;
+def CMP16mi : I16mi<0x0,
+ (outs), (ins memsrc:$src1, i16imm:$src2),
+ "cmp.w\t{$src2, $src1}",
+ [(MSP430cmp (load addr:$src1),
+ (i16 imm:$src2)), (implicit SRW)]>;
+
+def CMP8rm : I8rm<0x0,
+ (outs), (ins GR8:$src1, memsrc:$src2),
+ "cmp.b\t{$src2, $src1}",
+ [(MSP430cmp GR8:$src1, (load addr:$src2)),
+ (implicit SRW)]>;
+def CMP16rm : I16rm<0x0,
+ (outs), (ins GR16:$src1, memsrc:$src2),
+ "cmp.w\t{$src2, $src1}",
+ [(MSP430cmp GR16:$src1, (load addr:$src2)),
+ (implicit SRW)]>;
+
+def CMP8mr : I8mr<0x0,
+ (outs), (ins memsrc:$src1, GR8:$src2),
+ "cmp.b\t{$src2, $src1}",
+ [(MSP430cmp (load addr:$src1), GR8:$src2),
+ (implicit SRW)]>;
+def CMP16mr : I16mr<0x0,
+ (outs), (ins memsrc:$src1, GR16:$src2),
+ "cmp.w\t{$src2, $src1}",
+ [(MSP430cmp (load addr:$src1), GR16:$src2),
+ (implicit SRW)]>;
// BIT TESTS, just sets condition codes
// Note that the C condition is set differently than when using CMP.
let isCommutable = 1 in {
-def BIT8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR8:$src1, GR8:$src2)),
- (implicit SRW)]>;
-def BIT16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR16:$src1, GR16:$src2)),
- (implicit SRW)]>;
+def BIT8rr : I8rr<0x0,
+ (outs), (ins GR8:$src1, GR8:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR8:$src1, GR8:$src2), 0),
+ (implicit SRW)]>;
+def BIT16rr : I16rr<0x0,
+ (outs), (ins GR16:$src1, GR16:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR16:$src1, GR16:$src2), 0),
+ (implicit SRW)]>;
}
-def BIT8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR8:$src1, imm:$src2)),
- (implicit SRW)]>;
-def BIT16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR16:$src1, imm:$src2)),
- (implicit SRW)]>;
-
-def BIT8rm : Pseudo<(outs), (ins GR8:$src1, memdst:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR8:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-def BIT16rm : Pseudo<(outs), (ins GR16:$src1, memdst:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su GR16:$src1, (load addr:$src2))),
- (implicit SRW)]>;
-
-def BIT8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (load addr:$src1), GR8:$src2)),
- (implicit SRW)]>;
-def BIT16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (load addr:$src1), GR16:$src2)),
- (implicit SRW)]>;
-
-def BIT8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (load addr:$src1), (i8 imm:$src2))),
- (implicit SRW)]>;
-def BIT16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (load addr:$src1), (i16 imm:$src2))),
- (implicit SRW)]>;
-
-def BIT8mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2),
- "bit.b\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (i8 (load addr:$src1)),
- (load addr:$src2))),
- (implicit SRW)]>;
-def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2),
- "bit.w\t{$src2, $src1}",
- [(MSP430cmp 0, (and_su (i16 (load addr:$src1)),
- (load addr:$src2))),
+def BIT8ri : I8ri<0x0,
+ (outs), (ins GR8:$src1, i8imm:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR8:$src1, imm:$src2), 0),
+ (implicit SRW)]>;
+def BIT16ri : I16ri<0x0,
+ (outs), (ins GR16:$src1, i16imm:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR16:$src1, imm:$src2), 0),
+ (implicit SRW)]>;
+
+def BIT8rm : I8rm<0x0,
+ (outs), (ins GR8:$src1, memdst:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR8:$src1, (load addr:$src2)), 0),
+ (implicit SRW)]>;
+def BIT16rm : I16rm<0x0,
+ (outs), (ins GR16:$src1, memdst:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su GR16:$src1, (load addr:$src2)), 0),
+ (implicit SRW)]>;
+
+def BIT8mr : I8mr<0x0,
+ (outs), (ins memsrc:$src1, GR8:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su (load addr:$src1), GR8:$src2), 0),
+ (implicit SRW)]>;
+def BIT16mr : I16mr<0x0,
+ (outs), (ins memsrc:$src1, GR16:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su (load addr:$src1), GR16:$src2), 0),
+ (implicit SRW)]>;
+
+def BIT8mi : I8mi<0x0,
+ (outs), (ins memsrc:$src1, i8imm:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su (load addr:$src1), (i8 imm:$src2)), 0),
+ (implicit SRW)]>;
+def BIT16mi : I16mi<0x0,
+ (outs), (ins memsrc:$src1, i16imm:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su (load addr:$src1), (i16 imm:$src2)), 0),
+ (implicit SRW)]>;
+
+def BIT8mm : I8mm<0x0,
+ (outs), (ins memsrc:$src1, memsrc:$src2),
+ "bit.b\t{$src2, $src1}",
+ [(MSP430cmp (and_su (i8 (load addr:$src1)),
+ (load addr:$src2)),
+ 0),
(implicit SRW)]>;
+def BIT16mm : I16mm<0x0,
+ (outs), (ins memsrc:$src1, memsrc:$src2),
+ "bit.w\t{$src2, $src1}",
+ [(MSP430cmp (and_su (i16 (load addr:$src1)),
+ (load addr:$src2)),
+ 0),
+ (implicit SRW)]>;
} // Defs = [SRW]
//===----------------------------------------------------------------------===//
@@ -923,7 +1116,8 @@ def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2),
def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>;
// anyext
-def : Pat<(anyext addr:$src), (MOVZX16rr8 GR8:$src)>;
+def : Pat<(i16 (anyext GR8:$src)),
+ (SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>;
// truncs
def : Pat<(i8 (trunc GR16:$src)),
@@ -996,6 +1190,6 @@ def : Pat<(store (subc (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
// peephole patterns
def : Pat<(and GR16:$src, 255), (ZEXT16r GR16:$src)>;
-def : Pat<(MSP430cmp 0, (trunc (and_su GR16:$src1, GR16:$src2))),
+def : Pat<(MSP430cmp (trunc (and_su GR16:$src1, GR16:$src2)), 0),
(BIT8rr (EXTRACT_SUBREG GR16:$src1, subreg_8bit),
(EXTRACT_SUBREG GR16:$src2, subreg_8bit))>;
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 14db406..a0dbac2 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -44,3 +44,9 @@ bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM,
return false;
}
+bool MSP430TargetMachine::addPreEmitPass(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ // Must run branch selection immediately preceding the asm printer.
+ PM.add(createMSP430BranchSelectionPass());
+ return false;
+}
diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h
index d386140..d93ac5c 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.h
+++ b/lib/Target/MSP430/MSP430TargetMachine.h
@@ -55,6 +55,7 @@ public:
}
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
+ virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
}; // MSP430TargetMachine.
} // end namespace llvm
diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile
index 4b18bc9..11195a4 100644
--- a/lib/Target/MSP430/Makefile
+++ b/lib/Target/MSP430/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMMSP430CodeGen
TARGET = MSP430
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \
diff --git a/lib/Target/MSP430/TargetInfo/Makefile b/lib/Target/MSP430/TargetInfo/Makefile
index abb08f2..d17fa7b 100644
--- a/lib/Target/MSP430/TargetInfo/Makefile
+++ b/lib/Target/MSP430/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMMSP430Info
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/Makefile b/lib/Target/Makefile
index 50a360f..281d58b 100644
--- a/lib/Target/Makefile
+++ b/lib/Target/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../..
LIBRARYNAME = LLVMTarget
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
# We include this early so we can access the value of TARGETS_TO_BUILD as the
# value for PARALLEL_DIRS which must be set before Makefile.rules is included
diff --git a/lib/Target/Mangler.cpp b/lib/Target/Mangler.cpp
new file mode 100644
index 0000000..ef6defc
--- /dev/null
+++ b/lib/Target/Mangler.cpp
@@ -0,0 +1,179 @@
+//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Unified name mangler for assembly backends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Target/Mangler.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+using namespace llvm;
+
+static bool isAcceptableChar(char C) {
+ if ((C < 'a' || C > 'z') &&
+ (C < 'A' || C > 'Z') &&
+ (C < '0' || C > '9') &&
+ C != '_' && C != '$' && C != '.' && C != '@')
+ return false;
+ return true;
+}
+
+static char HexDigit(int V) {
+ return V < 10 ? V+'0' : V+'A'-10;
+}
+
+static void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) {
+ OutName.push_back('_');
+ OutName.push_back(HexDigit(C >> 4));
+ OutName.push_back(HexDigit(C & 15));
+ OutName.push_back('_');
+}
+
+/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes
+/// for this assembler.
+static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) {
+ assert(!Str.empty() && "Cannot create an empty MCSymbol");
+
+ // If the first character is a number and the target does not allow this, we
+ // need quotes.
+ if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9')
+ return true;
+
+ // If any of the characters in the string is an unacceptable character, force
+ // quotes.
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ if (!isAcceptableChar(Str[i]))
+ return true;
+ return false;
+}
+
+/// appendMangledName - Add the specified string in mangled form if it uses
+/// any unusual characters.
+static void appendMangledName(SmallVectorImpl<char> &OutName, StringRef Str,
+ const MCAsmInfo *MAI) {
+ // The first character is not allowed to be a number unless the target
+ // explicitly allows it.
+ if ((MAI == 0 || !MAI->doesAllowNameToStartWithDigit()) &&
+ Str[0] >= '0' && Str[0] <= '9') {
+ MangleLetter(OutName, Str[0]);
+ Str = Str.substr(1);
+ }
+
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (!isAcceptableChar(Str[i]))
+ MangleLetter(OutName, Str[i]);
+ else
+ OutName.push_back(Str[i]);
+ }
+}
+
+
+/// appendMangledQuotedName - On systems that support quoted symbols, we still
+/// have to escape some (obscure) characters like " and \n which would break the
+/// assembler's lexing.
+static void appendMangledQuotedName(SmallVectorImpl<char> &OutName,
+ StringRef Str) {
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] == '"' || Str[i] == '\n')
+ MangleLetter(OutName, Str[i]);
+ else
+ OutName.push_back(Str[i]);
+ }
+}
+
+
+/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
+/// and the specified name as the global variable name. GVName must not be
+/// empty.
+void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
+ const Twine &GVName, ManglerPrefixTy PrefixTy) {
+ SmallString<256> TmpData;
+ StringRef Name = GVName.toStringRef(TmpData);
+ assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
+
+ // If the global name is not led with \1, add the appropriate prefixes.
+ if (Name[0] == '\1') {
+ Name = Name.substr(1);
+ } else {
+ if (PrefixTy == Mangler::Private) {
+ const char *Prefix = MAI.getPrivateGlobalPrefix();
+ OutName.append(Prefix, Prefix+strlen(Prefix));
+ } else if (PrefixTy == Mangler::LinkerPrivate) {
+ const char *Prefix = MAI.getLinkerPrivateGlobalPrefix();
+ OutName.append(Prefix, Prefix+strlen(Prefix));
+ }
+
+ const char *Prefix = MAI.getGlobalPrefix();
+ if (Prefix[0] == 0)
+ ; // Common noop, no prefix.
+ else if (Prefix[1] == 0)
+ OutName.push_back(Prefix[0]); // Common, one character prefix.
+ else
+ OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary length prefix.
+ }
+
+ // If this is a simple string that doesn't need escaping, just append it.
+ if (!NameNeedsEscaping(Name, MAI) ||
+ // If quotes are supported, they can be used unless the string contains
+ // a quote or newline.
+ (MAI.doesAllowQuotesInName() &&
+ Name.find_first_of("\n\"") == StringRef::npos)) {
+ OutName.append(Name.begin(), Name.end());
+ return;
+ }
+
+ // On systems that do not allow quoted names, we need to mangle most
+ // strange characters.
+ if (!MAI.doesAllowQuotesInName())
+ return appendMangledName(OutName, Name, &MAI);
+
+ // Okay, the system allows quoted strings. We can quote most anything, the
+ // only characters that need escaping are " and \n.
+ assert(Name.find_first_of("\n\"") != StringRef::npos);
+ return appendMangledQuotedName(OutName, Name);
+}
+
+
+/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
+/// and the specified global variable's name. If the global variable doesn't
+/// have a name, this fills in a unique name for the global.
+void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
+ const GlobalValue *GV,
+ bool isImplicitlyPrivate) {
+ ManglerPrefixTy PrefixTy = Mangler::Default;
+ if (GV->hasPrivateLinkage() || isImplicitlyPrivate)
+ PrefixTy = Mangler::Private;
+ else if (GV->hasLinkerPrivateLinkage())
+ PrefixTy = Mangler::LinkerPrivate;
+
+ // If this global has a name, handle it simply.
+ if (GV->hasName())
+ return getNameWithPrefix(OutName, GV->getName(), PrefixTy);
+
+ // Get the ID for the global, assigning a new one if we haven't got one
+ // already.
+ unsigned &ID = AnonGlobalIDs[GV];
+ if (ID == 0) ID = NextAnonGlobalID++;
+
+ // Must mangle the global into a unique ID.
+ getNameWithPrefix(OutName, "__unnamed_" + Twine(ID), PrefixTy);
+}
+
+/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
+/// and the specified global variable's name. If the global variable doesn't
+/// have a name, this fills in a unique name for the global.
+std::string Mangler::getNameWithPrefix(const GlobalValue *GV,
+ bool isImplicitlyPrivate) {
+ SmallString<64> Buf;
+ getNameWithPrefix(Buf, GV, isImplicitlyPrivate);
+ return std::string(Buf.begin(), Buf.end());
+}
diff --git a/lib/Target/Mips/AsmPrinter/Makefile b/lib/Target/Mips/AsmPrinter/Makefile
index a2fecf4..aed801e 100644
--- a/lib/Target/Mips/AsmPrinter/Makefile
+++ b/lib/Target/Mips/AsmPrinter/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMMipsAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' Mips target directory to grab
# private headers
diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
index efd3fb7..9af9bd8 100644
--- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
@@ -37,7 +37,6 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
@@ -45,7 +44,6 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
-
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
@@ -72,7 +70,6 @@ namespace {
const char *Modifier = 0);
void printFCCOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
- void PrintGlobalVariable(const GlobalVariable *GVar);
void printSavedRegsBitmask(MachineFunction &MF);
void printHex32(unsigned int Value);
@@ -219,15 +216,15 @@ void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) {
// 2 bits aligned
EmitAlignment(MF.getAlignment(), F);
- O << "\t.globl\t" << CurrentFnName << '\n';
- O << "\t.ent\t" << CurrentFnName << '\n';
+ O << "\t.globl\t" << *CurrentFnSym << '\n';
+ O << "\t.ent\t" << *CurrentFnSym << '\n';
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
if ((MAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
- O << "\t.type\t" << CurrentFnName << ", @function\n";
+ O << "\t.type\t" << *CurrentFnSym << ", @function\n";
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
emitFrameDirective(MF);
printSavedRegsBitmask(MF);
@@ -243,9 +240,9 @@ void MipsAsmPrinter::emitFunctionEnd(MachineFunction &MF) {
O << "\t.set\tmacro\n";
O << "\t.set\treorder\n";
- O << "\t.end\t" << CurrentFnName << '\n';
+ O << "\t.end\t" << *CurrentFnSym << '\n';
if (MAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
}
/// runOnMachineFunction - This uses the printMachineInstruction()
@@ -346,20 +343,20 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
break;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ << '_' << MO.getIndex();
break;
case MachineOperand::MO_ConstantPoolIndex:
@@ -425,102 +422,6 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
O << "\t.previous" << '\n';
}
-void MipsAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- O << "\n\n";
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- const Type *CTy = C->getType();
- unsigned Size = TD->getTypeAllocSize(CTy);
- const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
- bool printSizeAndType = true;
-
- // A data structure or array is aligned in memory to the largest
- // alignment boundary required by any data type inside it (this matches
- // the Preferred Type Alignment). For integral types, the alignment is
- // the type size.
- unsigned Align;
- if (CTy->getTypeID() == Type::IntegerTyID ||
- CTy->getTypeID() == Type::VoidTyID) {
- assert(!(Size & (Size-1)) && "Alignment is not a power of two!");
- Align = Log2_32(Size);
- } else
- Align = TD->getPreferredTypeAlignmentShift(CTy);
-
- printVisibility(name, GVar->getVisibility());
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && !GVar->hasSection()) {
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
-
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (1 << Align);
-
- O << '\n';
- return;
- }
- }
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::CommonLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- // FIXME: Verify correct for weak.
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of their name
- // or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << MAI->getGlobalDirective() << name << '\n';
- // Fall Through
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- if (CVA && CVA->isCString())
- printSizeAndType = false;
- break;
- case GlobalValue::GhostLinkage:
- llvm_unreachable("Should not have any unmaterialized functions!");
- case GlobalValue::DLLImportLinkage:
- llvm_unreachable("DLLImport linkage is not supported by this target!");
- case GlobalValue::DLLExportLinkage:
- llvm_unreachable("DLLExport linkage is not supported by this target!");
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
-
- if (MAI->hasDotTypeDotSizeDirective() && printSizeAndType) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << ',' << Size << '\n';
- }
-
- O << name << ":\n";
- EmitGlobalConstant(C);
-}
-
-
// Force static initialization.
extern "C" void LLVMInitializeMipsAsmPrinter() {
RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);
diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
index 0780345..4e4d874 100644
--- a/lib/Target/Mips/Makefile
+++ b/lib/Target/Mips/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMMipsCodeGen
TARGET = Mips
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \
diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td
index 01fe92e..c2bfb8f 100644
--- a/lib/Target/Mips/MipsCallingConv.td
+++ b/lib/Target/Mips/MipsCallingConv.td
@@ -23,11 +23,11 @@ def RetCC_MipsO32 : CallingConv<[
// i32 are returned in registers V0, V1
CCIfType<[i32], CCAssignToReg<[V0, V1]>>,
- // f32 are returned in registers F0, F1
- CCIfType<[f32], CCAssignToReg<[F0, F1]>>,
+ // f32 are returned in registers F0, F2
+ CCIfType<[f32], CCAssignToReg<[F0, F2]>>,
- // f64 are returned in register D0
- CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[D0]>>>
+ // f64 are returned in register D0, D1
+ CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[D0, D1]>>>
]>;
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index a53e918..e3a45d2 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -396,9 +396,9 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
else
Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV);
- SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2);
+ SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2);
- SDValue InFlag = SDValue(Node, 0);
+ SDValue InFlag = SDValue(MulDiv, 0);
SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32,
MVT::Flag, InFlag);
InFlag = SDValue(Lo,1);
@@ -461,9 +461,18 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
case ISD::ConstantFP: {
ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node);
if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
- SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32);
- ReplaceUses(SDValue(Node, 0), Zero);
- return Zero.getNode();
+ SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
+ Mips::ZERO, MVT::i32);
+ SDValue Undef = SDValue(
+ CurDAG->getMachineNode(
+ TargetInstrInfo::IMPLICIT_DEF, dl, MVT::f64), 0);
+ SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero);
+ SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPEVEN, dl,
+ MVT::f64, Undef, SDValue(MTC, 0));
+ SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPODD, dl,
+ MVT::f64, I0, SDValue(MTC, 0));
+ ReplaceUses(SDValue(Node, 0), I1);
+ return I1.getNode();
}
break;
}
@@ -486,10 +495,15 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
/// be loaded with 3 instructions.
case MipsISD::JmpLink: {
if (TM.getRelocationModel() == Reloc::PIC_) {
+ unsigned LastOpNum = Node->getNumOperands()-1;
+
SDValue Chain = Node->getOperand(0);
SDValue Callee = Node->getOperand(1);
- SDValue T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
- SDValue InFlag(0, 0);
+ SDValue InFlag;
+
+ // Skip the incomming flag if present
+ if (Node->getOperand(LastOpNum).getValueType() == MVT::Flag)
+ LastOpNum--;
if ( (isa<GlobalAddressSDNode>(Callee)) ||
(isa<ExternalSymbolSDNode>(Callee)) )
@@ -504,18 +518,28 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
Chain = Load.getValue(1);
// Call target must be on T9
- Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Load, InFlag);
+ Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Load, InFlag);
} else
/// Indirect call
- Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Callee, InFlag);
+ Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Callee, InFlag);
+
+ // Map the JmpLink operands to JALR
+ SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Flag);
+ SmallVector<SDValue, 8> Ops;
+ Ops.push_back(CurDAG->getRegister(Mips::T9, MVT::i32));
+
+ for (unsigned i = 2, e = LastOpNum+1; i != e; ++i)
+ Ops.push_back(Node->getOperand(i));
+ Ops.push_back(Chain);
+ Ops.push_back(Chain.getValue(1));
// Emit Jump and Link Register
- SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, MVT::Other,
- MVT::Flag, T9Reg, Chain);
- Chain = SDValue(ResNode, 0);
- InFlag = SDValue(ResNode, 1);
- ReplaceUses(SDValue(Node, 0), Chain);
- ReplaceUses(SDValue(Node, 1), InFlag);
+ SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, NodeTys,
+ &Ops[0], Ops.size());
+
+ // Replace Chain and InFlag
+ ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0));
+ ReplaceUses(SDValue(Node, 1), SDValue(ResNode, 1));
return ResNode;
}
}
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 48b9bdf..1a9bffc 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -134,8 +134,6 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const {
DebugLoc DL = DebugLoc::getUnknownLoc();
- const MachineFunction *MF = MBB.getParent();
- const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
if (I != MBB.end()) DL = I->getDebugLoc();
@@ -156,13 +154,6 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
else if ((DestRC == Mips::FGR32RegisterClass) &&
(SrcRC == Mips::CPURegsRegisterClass))
BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg).addReg(SrcReg);
- else if ((DestRC == Mips::AFGR64RegisterClass) &&
- (SrcRC == Mips::CPURegsRegisterClass) &&
- (SrcReg == Mips::ZERO)) {
- const unsigned *AliasSet = TRI->getAliasSet(DestReg);
- BuildMI(MBB, I, DL, get(Mips::MTC1), AliasSet[0]).addReg(SrcReg);
- BuildMI(MBB, I, DL, get(Mips::MTC1), AliasSet[1]).addReg(SrcReg);
- }
// Move from/to Hi/Lo registers
else if ((DestRC == Mips::HILORegisterClass) &&
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 46cf43e..e67bcbf 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -28,8 +28,8 @@ def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
// Call
-def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
- SDNPOutFlag]>;
+def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
+ [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
// Hi and Lo nodes are used to handle global addresses. Used on
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
@@ -306,7 +306,7 @@ let isCall=1, hasDelaySlot=1,
class JumpLink<bits<6> op, string instr_asm>:
FJ< op,
(outs),
- (ins calltarget:$target),
+ (ins calltarget:$target, variable_ops),
!strconcat(instr_asm, "\t$target"),
[(MipsJmpLink imm:$target)], IIBranch>;
@@ -315,14 +315,14 @@ let isCall=1, hasDelaySlot=1,
FR< op,
func,
(outs),
- (ins CPURegs:$rs),
+ (ins CPURegs:$rs, variable_ops),
!strconcat(instr_asm, "\t$rs"),
[(MipsJmpLink CPURegs:$rs)], IIBranch>;
class BranchLink<string instr_asm>:
FI< 0x1,
(outs),
- (ins CPURegs:$rs, brtarget:$target),
+ (ins CPURegs:$rs, brtarget:$target, variable_ops),
!strconcat(instr_asm, "\t$rs, $target"),
[], IIBranch>;
}
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index cae4181..80fd917 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -172,7 +172,7 @@ getReservedRegs(const MachineFunction &MF) const
//
// The stack is allocated decrementing the stack pointer on
// the first instruction of a function prologue. Once decremented,
-// all stack referencesare are done thought a positive offset
+// all stack references are done thought a positive offset
// from the stack/frame pointer, so the stack is considering
// to grow up! Otherwise terrible hacks would have to be made
// to get this stack ABI compliant :)
diff --git a/lib/Target/Mips/TargetInfo/Makefile b/lib/Target/Mips/TargetInfo/Makefile
index 32f4e16..f27d49e 100644
--- a/lib/Target/Mips/TargetInfo/Makefile
+++ b/lib/Target/Mips/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMMipsInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/PIC16/AsmPrinter/Makefile b/lib/Target/PIC16/AsmPrinter/Makefile
index f4db57e..27c4045 100644
--- a/lib/Target/PIC16/AsmPrinter/Makefile
+++ b/lib/Target/PIC16/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMPIC16AsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' pic16 target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
index 87f5aad..0463596 100644
--- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
@@ -29,7 +29,6 @@
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include <cstring>
using namespace llvm;
@@ -82,7 +81,7 @@ static int getFunctionColor(const Function *F) {
// Color the Auto section of the given function.
void PIC16AsmPrinter::ColorAutoSection(const Function *F) {
- std::string SectionName = PAN::getAutosSectionName(CurrentFnName);
+ std::string SectionName = PAN::getAutosSectionName(CurrentFnSym->getName());
PIC16Section* Section = PTOF->findPIC16Section(SectionName);
if (Section != NULL) {
int Color = getFunctionColor(F);
@@ -103,11 +102,8 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// of runOnMachineFunction.
SetupMachineFunction(MF);
- // Get the mangled name.
- const Function *F = MF.getFunction();
- CurrentFnName = Mang->getMangledName(F);
-
// Put the color information from function to its auto section.
+ const Function *F = MF.getFunction();
ColorAutoSection(F);
// Emit the function frame (args and temps).
@@ -117,18 +113,18 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Now emit the instructions of function in its code section.
const MCSection *fCodeSection
- = getObjFileLowering().SectionForCode(CurrentFnName);
+ = getObjFileLowering().SectionForCode(CurrentFnSym->getName());
// Start the Code Section.
O << "\n";
OutStreamer.SwitchSection(fCodeSection);
// Emit the frame address of the function at the beginning of code.
- O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
- O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
+ O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n";
+ O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n";
// Emit function start label.
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
DebugLoc CurDL;
O << "\n";
@@ -187,24 +183,22 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
return;
case MachineOperand::MO_GlobalAddress: {
- std::string Sname = Mang->getMangledName(MO.getGlobal());
+ MCSymbol *Sym = GetGlobalValueSymbol(MO.getGlobal());
// FIXME: currently we do not have a memcpy def coming in the module
// by any chance, as we do not link in those as .bc lib. So these calls
// are always external and it is safe to emit an extern.
- if (PAN::isMemIntrinsic(Sname)) {
- LibcallDecls.push_back(createESName(Sname));
- }
+ if (PAN::isMemIntrinsic(Sym->getName()))
+ LibcallDecls.push_back(createESName(Sym->getName()));
- O << Sname;
+ O << *Sym;
break;
}
case MachineOperand::MO_ExternalSymbol: {
const char *Sname = MO.getSymbolName();
// If its a libcall name, record it to decls section.
- if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
+ if (PAN::getSymbolTag(Sname) == PAN::LIBCALL)
LibcallDecls.push_back(Sname);
- }
// Record a call to intrinsic to print the extern declaration for it.
std::string Sym = Sname;
@@ -213,11 +207,11 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
LibcallDecls.push_back(createESName(Sym));
}
- O << Sym;
+ O << Sym;
break;
}
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
default:
@@ -319,16 +313,14 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
// Emit declarations for external functions.
O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
- if (I->isIntrinsic())
- continue;
-
- std::string Name = Mang->getMangledName(I);
- if (Name.compare("@abort") == 0)
+ if (I->isIntrinsic() || I->getName() == "@abort")
continue;
if (!I->isDeclaration() && !I->hasExternalLinkage())
continue;
+ MCSymbol *Sym = GetGlobalValueSymbol(I);
+
// Do not emit memcpy, memset, and memmove here.
// Calls to these routines can be generated in two ways,
// 1. User calling the standard lib function
@@ -337,14 +329,14 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
// second case the call is via and externalsym and the prototype is missing.
// So declarations for these are currently always getting printing by
// tracking both kind of references in printInstrunction.
- if (I->isDeclaration() && PAN::isMemIntrinsic(Name)) continue;
+ if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue;
const char *directive = I->isDeclaration() ? MAI->getExternDirective() :
MAI->getGlobalDirective();
- O << directive << Name << "\n";
- O << directive << PAN::getRetvalLabel(Name) << "\n";
- O << directive << PAN::getArgsLabel(Name) << "\n";
+ O << directive << Sym->getName() << "\n";
+ O << directive << PAN::getRetvalLabel(Sym->getName()) << "\n";
+ O << directive << PAN::getArgsLabel(Sym->getName()) << "\n";
}
O << MAI->getCommentString() << "Function Declarations - END." <<"\n";
@@ -356,9 +348,8 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
if (!Items.size()) return;
O << "\n" << MAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
- for (unsigned j = 0; j < Items.size(); j++) {
- O << MAI->getExternDirective() << Mang->getMangledName(Items[j]) << "\n";
- }
+ for (unsigned j = 0; j < Items.size(); j++)
+ O << MAI->getExternDirective() << *GetGlobalValueSymbol(Items[j]) << "\n";
O << MAI->getCommentString() << "Imported Variables - END" << "\n";
}
@@ -368,9 +359,8 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
if (!Items.size()) return;
O << "\n" << MAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
- for (unsigned j = 0; j < Items.size(); j++) {
- O << MAI->getGlobalDirective() << Mang->getMangledName(Items[j]) << "\n";
- }
+ for (unsigned j = 0; j < Items.size(); j++)
+ O << MAI->getGlobalDirective() << *GetGlobalValueSymbol(Items[j]) << "\n";
O << MAI->getCommentString() << "Exported Variables - END" << "\n";
}
@@ -394,19 +384,19 @@ bool PIC16AsmPrinter::doFinalization(Module &M) {
void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
const Function *F = MF.getFunction();
- std::string FuncName = Mang->getMangledName(F);
const TargetData *TD = TM.getTargetData();
// Emit the data section name.
O << "\n";
- PIC16Section *fPDataSection = const_cast<PIC16Section *>(getObjFileLowering().
- SectionForFrame(CurrentFnName));
+ PIC16Section *fPDataSection =
+ const_cast<PIC16Section *>(getObjFileLowering().
+ SectionForFrame(CurrentFnSym->getName()));
fPDataSection->setColor(getFunctionColor(F));
OutStreamer.SwitchSection(fPDataSection);
// Emit function frame label
- O << PAN::getFrameLabel(CurrentFnName) << ":\n";
+ O << PAN::getFrameLabel(CurrentFnSym->getName()) << ":\n";
const Type *RetType = F->getReturnType();
unsigned RetSize = 0;
@@ -418,9 +408,10 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
// we will need to avoid printing a global directive for Retval label
// in emitExternandGloblas.
if(RetSize > 0)
- O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
+ O << PAN::getRetvalLabel(CurrentFnSym->getName())
+ << " RES " << RetSize << "\n";
else
- O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
+ O << PAN::getRetvalLabel(CurrentFnSym->getName()) << ": \n";
// Emit variable to hold the space for function arguments
unsigned ArgSize = 0;
@@ -430,12 +421,13 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
ArgSize += TD->getTypeAllocSize(Ty);
}
- O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
+ O << PAN::getArgsLabel(CurrentFnSym->getName()) << " RES " << ArgSize << "\n";
// Emit temporary space
int TempSize = PTLI->GetTmpSize();
if (TempSize > 0)
- O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize << '\n';
+ O << PAN::getTempdataLabel(CurrentFnSym->getName()) << " RES "
+ << TempSize << '\n';
}
@@ -445,10 +437,9 @@ void PIC16AsmPrinter::EmitInitializedDataSection(const PIC16Section *S) {
std::vector<const GlobalVariable*> Items = S->Items;
for (unsigned j = 0; j < Items.size(); j++) {
- std::string Name = Mang->getMangledName(Items[j]);
Constant *C = Items[j]->getInitializer();
int AddrSpace = Items[j]->getType()->getAddressSpace();
- O << Name;
+ O << *GetGlobalValueSymbol(Items[j]);
EmitGlobalConstant(C, AddrSpace);
}
}
@@ -464,11 +455,10 @@ EmitUninitializedDataSection(const PIC16Section *S) {
OutStreamer.SwitchSection(S);
std::vector<const GlobalVariable*> Items = S->Items;
for (unsigned j = 0; j < Items.size(); j++) {
- std::string Name = Mang->getMangledName(Items[j]);
Constant *C = Items[j]->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypeAllocSize(Ty);
- O << Name << " RES " << Size << "\n";
+ O << *GetGlobalValueSymbol(Items[j]) << " RES " << Size << "\n";
}
}
diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
index 838c970..74ab72c 100644
--- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
+++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
@@ -69,9 +69,9 @@ namespace llvm {
bool doInitialization(Module &M);
bool doFinalization(Module &M);
- /// PrintGlobalVariable - Emit the specified global variable and its
+ /// EmitGlobalVariable - Emit the specified global variable and its
/// initializer to the output stream.
- virtual void PrintGlobalVariable(const GlobalVariable *GV) {
+ virtual void EmitGlobalVariable(const GlobalVariable *GV) {
// PIC16 doesn't use normal hooks for this.
}
diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile
index 4382eba7..a1dbde5 100644
--- a/lib/Target/PIC16/Makefile
+++ b/lib/Target/PIC16/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMPIC16CodeGen
TARGET = PIC16
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \
diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp
index 6e0e3ce..8368a3c 100644
--- a/lib/Target/PIC16/PIC16DebugInfo.cpp
+++ b/lib/Target/PIC16/PIC16DebugInfo.cpp
@@ -259,8 +259,9 @@ void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF,
if (! EmitDebugDirectives) return;
assert (! DL.isUnknown() && "can't change to invalid debug loc");
- MDNode *CU = MF.getDebugLocTuple(DL).Scope;
- unsigned line = MF.getDebugLocTuple(DL).Line;
+ DILocation Loc = MF.getDILocation(DL);
+ MDNode *CU = Loc.getScope().getNode();
+ unsigned line = Loc.getLineNumber();
SwitchToCU(CU);
SwitchToLine(line, IsInBeginFunction);
diff --git a/lib/Target/PIC16/PIC16Passes/Makefile b/lib/Target/PIC16/PIC16Passes/Makefile
index 9684b8d..fb45d71 100644
--- a/lib/Target/PIC16/PIC16Passes/Makefile
+++ b/lib/Target/PIC16/PIC16Passes/Makefile
@@ -10,6 +10,7 @@ LEVEL = ../../../..
TARGET = PIC16
LIBRARYNAME = LLVMpic16passes
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Target/PIC16/TargetInfo/Makefile b/lib/Target/PIC16/TargetInfo/Makefile
index 76609f6..9004be8 100644
--- a/lib/Target/PIC16/TargetInfo/Makefile
+++ b/lib/Target/PIC16/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMPIC16Info
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/PowerPC/AsmPrinter/Makefile b/lib/Target/PowerPC/AsmPrinter/Makefile
index 269ef92..4378151 100644
--- a/lib/Target/PowerPC/AsmPrinter/Makefile
+++ b/lib/Target/PowerPC/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMPowerPCAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' PowerPC target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
index d505d38..b89c2b4 100644
--- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
@@ -27,21 +27,21 @@
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -58,48 +58,7 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
class PPCAsmPrinter : public AsmPrinter {
protected:
- struct FnStubInfo {
- MCSymbol *Stub, *LazyPtr, *AnonSymbol;
-
- FnStubInfo() {
- Stub = LazyPtr = AnonSymbol = 0;
- }
-
- void Init(const GlobalValue *GV, Mangler *Mang, MCContext &Ctx) {
- // Already initialized.
- if (Stub != 0) return;
-
- // Get the names.
- SmallString<128> TmpStr;
- Mang->getNameWithPrefix(TmpStr, GV, true);
- MakeSymbols(TmpStr, Ctx);
- }
-
- void Init(StringRef GVName, Mangler *Mang, MCContext &Ctx) {
- assert(!GVName.empty() && "external symbol name shouldn't be empty");
- if (Stub != 0) return; // Already initialized.
- // Get the names for the external symbol name.
- SmallString<128> TmpStr;
- Mang->getNameWithPrefix(TmpStr, GVName, Mangler::Private);
- MakeSymbols(TmpStr, Ctx);
- }
-
- void MakeSymbols(SmallString<128> &TmpStr, MCContext &Ctx) {
- TmpStr += "$stub";
- Stub = Ctx.GetOrCreateSymbol(TmpStr.str());
- TmpStr.erase(TmpStr.end()-5, TmpStr.end()); // Remove $stub
-
- TmpStr += "$lazy_ptr";
- LazyPtr = Ctx.GetOrCreateSymbol(TmpStr.str());
- TmpStr.erase(TmpStr.end()-9, TmpStr.end()); // Remove $lazy_ptr
-
- TmpStr += "$stub$tmp";
- AnonSymbol = Ctx.GetOrCreateSymbol(TmpStr.str());
- }
- };
-
- StringMap<FnStubInfo> FnStubs;
- StringMap<std::string> GVStubs, HiddenGVStubs, TOC;
+ DenseMap<const MCSymbol*, const MCSymbol*> TOC;
const PPCSubtarget &Subtarget;
uint64_t LabelID;
public:
@@ -240,18 +199,26 @@ namespace {
GlobalValue *GV = MO.getGlobal();
if (GV->isDeclaration() || GV->isWeakForLinker()) {
// Dynamically-resolved functions need a stub for the function.
- FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)];
- FnInfo.Init(GV, Mang, OutContext);
- FnInfo.Stub->print(O, MAI);
+ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub");
+ const MCSymbol *&StubSym =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
+ O << *Sym;
return;
}
}
if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
- SmallString<128> MangledName;
- Mang->getNameWithPrefix(MangledName, MO.getSymbolName());
- FnStubInfo &FnInfo = FnStubs[MangledName.str()];
- FnInfo.Init(MO.getSymbolName(), Mang, OutContext);
- FnInfo.Stub->print(O, MAI);
+ SmallString<128> TempNameStr;
+ TempNameStr += StringRef(MO.getSymbolName());
+ TempNameStr += StringRef("$stub");
+
+ const MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str());
+ const MCSymbol *&StubSym =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
+ if (StubSym == 0)
+ StubSym = GetExternalSymbolSymbol(MO.getSymbolName());
+ O << *Sym;
return;
}
}
@@ -338,21 +305,16 @@ namespace {
assert(MO.getType() == MachineOperand::MO_GlobalAddress);
- GlobalValue *GV = MO.getGlobal();
-
- std::string Name = Mang->getMangledName(GV);
+ const MCSymbol *Sym = GetGlobalValueSymbol(MO.getGlobal());
// Map symbol -> label of TOC entry.
- if (TOC.count(Name) == 0) {
- std::string Label;
- Label += MAI->getPrivateGlobalPrefix();
- Label += "C";
- Label += utostr(LabelID++);
+ const MCSymbol *&TOCEntry = TOC[Sym];
+ if (TOCEntry == 0)
+ TOCEntry = OutContext.
+ GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + "C" +
+ Twine(LabelID++));
- TOC[Name] = Label;
- }
-
- O << TOC[Name] << "@toc";
+ O << *TOCEntry << "@toc";
}
void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
@@ -381,8 +343,6 @@ namespace {
AU.addRequired<DwarfWriter>();
PPCAsmPrinter::getAnalysisUsage(AU);
}
-
- void PrintGlobalVariable(const GlobalVariable *GVar);
};
/// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac
@@ -402,14 +362,14 @@ namespace {
bool doFinalization(Module &M);
void EmitStartOfAsmFile(Module &M);
+ void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs);
+
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<MachineModuleInfo>();
AU.addRequired<DwarfWriter>();
PPCAsmPrinter::getAnalysisUsage(AU);
}
-
- void PrintGlobalVariable(const GlobalVariable *GVar);
};
} // end of anonymous namespace
@@ -422,7 +382,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
llvm_unreachable("printOp() does not handle immediate values");
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
@@ -434,42 +394,57 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
<< '_' << MO.getIndex();
return;
case MachineOperand::MO_BlockAddress:
- GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
+ O << *GetBlockAddressSymbol(MO.getBlockAddress());
return;
case MachineOperand::MO_ExternalSymbol: {
// Computing the address of an external symbol, not calling it.
- std::string Name(MAI->getGlobalPrefix());
- Name += MO.getSymbolName();
-
- if (TM.getRelocationModel() != Reloc::Static) {
- GVStubs[Name] = Name+"$non_lazy_ptr";
- Name += "$non_lazy_ptr";
+ if (TM.getRelocationModel() == Reloc::Static) {
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ return;
}
- O << Name;
+
+ const MCSymbol *NLPSym =
+ OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+
+ MO.getSymbolName()+"$non_lazy_ptr");
+ const MCSymbol *&StubSym =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym);
+ if (StubSym == 0)
+ StubSym = GetExternalSymbolSymbol(MO.getSymbolName());
+
+ O << *NLPSym;
return;
}
case MachineOperand::MO_GlobalAddress: {
// Computing the address of a global symbol, not calling it.
GlobalValue *GV = MO.getGlobal();
- std::string Name;
+ MCSymbol *SymToPrint;
// External or weakly linked global variables need non-lazily-resolved stubs
if (TM.getRelocationModel() != Reloc::Static &&
(GV->isDeclaration() || GV->isWeakForLinker())) {
if (!GV->hasHiddenVisibility()) {
- Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
- GVStubs[Mang->getMangledName(GV)] = Name;
+ SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
+ const MCSymbol *&StubSym =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(SymToPrint);
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
} else if (GV->isDeclaration() || GV->hasCommonLinkage() ||
GV->hasAvailableExternallyLinkage()) {
- Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
- HiddenGVStubs[Mang->getMangledName(GV)] = Name;
+ SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
+
+ const MCSymbol *&StubSym =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>().
+ getHiddenGVStubEntry(SymToPrint);
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
} else {
- Name = Mang->getMangledName(GV);
+ SymToPrint = GetGlobalValueSymbol(GV);
}
} else {
- Name = Mang->getMangledName(GV);
+ SymToPrint = GetGlobalValueSymbol(GV);
}
- O << Name;
+
+ O << *SymToPrint;
printOffset(MO.getOffset());
return;
@@ -641,34 +616,34 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::ExternalLinkage:
- O << "\t.global\t" << CurrentFnName << '\n'
- << "\t.type\t" << CurrentFnName << ", @function\n";
+ O << "\t.global\t" << *CurrentFnSym << '\n' << "\t.type\t";
+ O << *CurrentFnSym << ", @function\n";
break;
case Function::LinkerPrivateLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
- O << "\t.global\t" << CurrentFnName << '\n';
- O << "\t.weak\t" << CurrentFnName << '\n';
+ O << "\t.global\t" << *CurrentFnSym << '\n';
+ O << "\t.weak\t" << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
EmitAlignment(MF.getAlignment(), F);
if (Subtarget.isPPC64()) {
// Emit an official procedure descriptor.
- // FIXME 64-bit SVR4: Use MCSection here?
+ // FIXME 64-bit SVR4: Use MCSection here!
O << "\t.section\t\".opd\",\"aw\"\n";
O << "\t.align 3\n";
- O << CurrentFnName << ":\n";
- O << "\t.quad .L." << CurrentFnName << ",.TOC.@tocbase\n";
+ O << *CurrentFnSym << ":\n";
+ O << "\t.quad .L." << *CurrentFnSym << ",.TOC.@tocbase\n";
O << "\t.previous\n";
- O << ".L." << CurrentFnName << ":\n";
+ O << ".L." << *CurrentFnSym << ":\n";
} else {
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
}
// Emit pre-function debug information.
@@ -688,7 +663,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
}
- O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << '\n';
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
@@ -702,92 +677,6 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
return false;
}
-void PPCLinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- std::string name = Mang->getMangledName(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && /* FIXME: Verify correct */
- !GVar->hasSection() &&
- (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
- GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasExternalLinkage()) {
- O << "\t.global " << name << '\n';
- O << "\t.type " << name << ", @object\n";
- O << name << ":\n";
- O << "\t.zero " << Size << '\n';
- } else if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << ',' << Size;
- } else {
- O << ".comm " << name << ',' << Size;
- }
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'";
- }
- O << '\n';
- return;
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n"
- << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n";
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O << "\t\t\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'";
- }
- O << '\n';
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
const TargetData *TD = TM.getTargetData();
@@ -797,10 +686,11 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
// FIXME 64-bit SVR4: Use MCSection here?
O << "\t.section\t\".toc\",\"aw\"\n";
- for (StringMap<std::string>::iterator I = TOC.begin(), E = TOC.end();
- I != E; ++I) {
- O << I->second << ":\n";
- O << "\t.tc " << I->getKeyData() << "[TC]," << I->getKeyData() << '\n';
+ // FIXME: This is nondeterminstic!
+ for (DenseMap<const MCSymbol*, const MCSymbol*>::iterator I = TOC.begin(),
+ E = TOC.end(); I != E; ++I) {
+ O << *I->second << ":\n";
+ O << "\t.tc " << *I->first << "[TC]," << *I->first << '\n';
}
}
@@ -829,22 +719,22 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
+ O << "\t.globl\t" << *CurrentFnSym << '\n';
break;
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::LinkerPrivateLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
- O << "\t.weak_definition\t" << CurrentFnName << '\n';
+ O << "\t.globl\t" << *CurrentFnSym << '\n';
+ O << "\t.weak_definition\t" << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
EmitAlignment(MF.getAlignment(), F);
- O << CurrentFnName << ":\n";
+ O << *CurrentFnSym << ":\n";
// Emit pre-function debug information.
DW->BeginFunction(&MF);
@@ -926,203 +816,110 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
}
-void PPCDarwinAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar)) {
- if (TM.getRelocationModel() == Reloc::Static) {
- if (GVar->getName() == "llvm.global_ctors")
- O << ".reference .constructors_used\n";
- else if (GVar->getName() == "llvm.global_dtors")
- O << ".reference .destructors_used\n";
- }
- return;
- }
-
- std::string name = Mang->getMangledName(GVar);
- printVisibility(name, GVar->getVisibility());
-
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, Mang, TM);
- OutStreamer.SwitchSection(TheSection);
-
- /// FIXME: Drive this off the section!
- if (C->isNullValue() && /* FIXME: Verify correct */
- !GVar->hasSection() &&
- (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
- GVar->isWeakForLinker()) &&
- // Don't put things that should go in the cstring section into "comm".
- !TheSection->getKind().isMergeableCString()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasExternalLinkage()) {
- O << "\t.globl " << name << '\n';
- O << "\t.zerofill __DATA, __common, " << name << ", "
- << Size << ", " << Align;
- } else if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << ',' << Size << ',' << Align;
- } else if (!GVar->hasCommonLinkage()) {
- O << "\t.globl " << name << '\n'
- << MAI->getWeakDefDirective() << name << '\n';
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O << "\t\t\t\t" << MAI->getCommentString() << " ";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- } else {
- O << ".comm " << name << ',' << Size;
- // Darwin 9 and above support aligned common data.
- if (Subtarget.isDarwin9())
- O << ',' << Align;
- }
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'";
- }
- O << '\n';
- return;
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- O << "\t.globl " << name << '\n'
- << "\t.weak_definition " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << '\n';
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O << "\t\t\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'";
- }
- O << '\n';
-
- EmitGlobalConstant(C);
- O << '\n';
+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());
}
-bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
- const TargetData *TD = TM.getTargetData();
-
- bool isPPC64 = TD->getPointerSizeInBits() == 64;
+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());
+}
- // Darwin/PPC always uses mach-o.
+void PPCDarwinAsmPrinter::
+EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
+ bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64;
+
TargetLoweringObjectFileMachO &TLOFMacho =
static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
-
- const MCSection *LSPSection = 0;
- if (!FnStubs.empty()) // .lazy_symbol_pointer
- LSPSection = TLOFMacho.getLazySymbolPointerSection();
-
+ // .lazy_symbol_pointer
+ const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
// Output stubs for dynamically-linked functions
- if (TM.getRelocationModel() == Reloc::PIC_ && !FnStubs.empty()) {
+ if (TM.getRelocationModel() == Reloc::PIC_) {
const MCSection *StubSection =
- TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1",
- MCSectionMachO::S_SYMBOL_STUBS |
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 32, SectionKind::getText());
- for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(), E = FnStubs.end();
- I != E; ++I) {
+ TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 32, SectionKind::getText());
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
OutStreamer.SwitchSection(StubSection);
EmitAlignment(4);
- const FnStubInfo &Info = I->second;
- Info.Stub->print(O, MAI);
- O << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
+
+ const MCSymbol *Stub = Stubs[i].first;
+ const MCSymbol *RawSym = Stubs[i].second;
+ const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
+ const MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
+
+ O << *Stub << ":\n";
+ O << "\t.indirect_symbol " << *RawSym << '\n';
O << "\tmflr r0\n";
- O << "\tbcl 20,31,";
- Info.AnonSymbol->print(O, MAI);
- O << '\n';
- Info.AnonSymbol->print(O, MAI);
- O << ":\n";
+ O << "\tbcl 20,31," << *AnonSymbol << '\n';
+ O << *AnonSymbol << ":\n";
O << "\tmflr r11\n";
- O << "\taddis r11,r11,ha16(";
- Info.LazyPtr->print(O, MAI);
- O << '-';
- Info.AnonSymbol->print(O, MAI);
- O << ")\n";
+ O << "\taddis r11,r11,ha16(" << *LazyPtr << '-' << *AnonSymbol
+ << ")\n";
O << "\tmtlr r0\n";
- O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(";
- Info.LazyPtr->print(O, MAI);
- O << '-';
- Info.AnonSymbol->print(O, MAI);
- O << ")(r11)\n";
+ O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr
+ << '-' << *AnonSymbol << ")(r11)\n";
O << "\tmtctr r12\n";
O << "\tbctr\n";
OutStreamer.SwitchSection(LSPSection);
- Info.LazyPtr->print(O, MAI);
- O << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
- O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n";
- }
- } else if (!FnStubs.empty()) {
- const MCSection *StubSection =
- TLOFMacho.getMachOSection("__TEXT","__symbol_stub1",
- MCSectionMachO::S_SYMBOL_STUBS |
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 16, SectionKind::getText());
-
- for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(), E = FnStubs.end();
- I != E; ++I) {
- OutStreamer.SwitchSection(StubSection);
- EmitAlignment(4);
- const FnStubInfo &Info = I->second;
- Info.Stub->print(O, MAI);
- O << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
- O << "\tlis r11,ha16(";
- Info.LazyPtr->print(O, MAI);
- O << ")\n";
- O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(";
- Info.LazyPtr->print(O, MAI);
- O << ")(r11)\n";
- O << "\tmtctr r12\n";
- O << "\tbctr\n";
- OutStreamer.SwitchSection(LSPSection);
- Info.LazyPtr->print(O, MAI);
- O << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
+ O << *LazyPtr << ":\n";
+ O << "\t.indirect_symbol " << *RawSym << '\n';
O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n";
}
+ O << '\n';
+ return;
}
-
+
+ const MCSection *StubSection =
+ TLOFMacho.getMachOSection("__TEXT","__symbol_stub1",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 16, SectionKind::getText());
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ const MCSymbol *Stub = Stubs[i].first;
+ const MCSymbol *RawSym = Stubs[i].second;
+ const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
+
+ OutStreamer.SwitchSection(StubSection);
+ EmitAlignment(4);
+ O << *Stub << ":\n";
+ O << "\t.indirect_symbol " << *RawSym << '\n';
+ O << "\tlis r11,ha16(" << *LazyPtr << ")\n";
+ O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr
+ << ")(r11)\n";
+ O << "\tmtctr r12\n";
+ O << "\tbctr\n";
+ OutStreamer.SwitchSection(LSPSection);
+ O << *LazyPtr << ":\n";
+ O << "\t.indirect_symbol " << *RawSym << '\n';
+ O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n";
+ }
+
O << '\n';
+}
+
+
+bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
+ bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64;
+
+ // Darwin/PPC always uses mach-o.
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ MachineModuleInfoMachO &MMIMacho =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>();
+
+ MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList();
+ if (!Stubs.empty())
+ EmitFunctionStubs(Stubs);
if (MAI->doesSupportExceptionHandling() && MMI) {
// Add the (possibly multiple) personalities to the set of global values.
@@ -1130,33 +927,39 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
const std::vector<Function *> &Personalities = MMI->getPersonalities();
for (std::vector<Function *>::const_iterator I = Personalities.begin(),
E = Personalities.end(); I != E; ++I) {
- if (*I)
- GVStubs[Mang->getMangledName(*I)] =
- Mang->getMangledName(*I, "$non_lazy_ptr", true);
+ if (*I) {
+ const MCSymbol *NLPSym =
+ GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr");
+ const MCSymbol *&StubSym = MMIMacho.getGVStubEntry(NLPSym);
+ StubSym = GetGlobalValueSymbol(*I);
+ }
}
}
+ // Output stubs for dynamically-linked functions.
+ Stubs = MMIMacho.GetGVStubList();
+
// Output macho stubs for external and common global variables.
- if (!GVStubs.empty()) {
+ if (!Stubs.empty()) {
// Switch with ".non_lazy_symbol_pointer" directive.
OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
EmitAlignment(isPPC64 ? 3 : 2);
- for (StringMap<std::string>::iterator I = GVStubs.begin(),
- E = GVStubs.end(); I != E; ++I) {
- O << I->second << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ O << *Stubs[i].first << ":\n";
+ O << "\t.indirect_symbol " << *Stubs[i].second << '\n';
O << (isPPC64 ? "\t.quad\t0\n" : "\t.long\t0\n");
}
}
- if (!HiddenGVStubs.empty()) {
+ Stubs = MMIMacho.GetHiddenGVStubList();
+ if (!Stubs.empty()) {
OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
EmitAlignment(isPPC64 ? 3 : 2);
- for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(),
- E = HiddenGVStubs.end(); I != E; ++I) {
- O << I->second << ":\n";
- O << (isPPC64 ? "\t.quad\t" : "\t.long\t") << I->getKeyData() << '\n';
+
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ O << *Stubs[i].first << ":\n";
+ O << (isPPC64 ? "\t.quad\t" : "\t.long\t") << *Stubs[i].second << '\n';
}
}
@@ -1165,7 +968,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never generates
// code that does this, it is always safe to set.
- OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+ OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
return AsmPrinter::doFinalization(M);
}
diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile
index 4015d4a..cd30011 100644
--- a/lib/Target/PowerPC/Makefile
+++ b/lib/Target/PowerPC/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMPowerPCCodeGen
TARGET = PPC
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \
diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/PPCMCAsmInfo.cpp
index ee6deb5..d2ff3b7 100644
--- a/lib/Target/PowerPC/PPCMCAsmInfo.cpp
+++ b/lib/Target/PowerPC/PPCMCAsmInfo.cpp
@@ -29,7 +29,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
CommentString = "#";
GlobalPrefix = "";
PrivateGlobalPrefix = ".L";
- UsedDirective = "\t# .no_dead_strip\t";
WeakRefDirective = "\t.weak\t";
// Uses '.section' before '.bss' directive
@@ -53,7 +52,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
SetDirective = "\t.set";
Data64bitsDirective = is64Bit ? "\t.quad\t" : 0;
AlignmentIsInBytes = false;
- LCOMMDirective = "\t.lcomm\t";
+ HasLCOMMDirective = true;
AssemblerDialect = 0; // Old-Style mnemonics.
}
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index 8079c6e..c7f7882 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -194,4 +194,31 @@ bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
return false;
}
-
+/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte,
+/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA
+/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte
+/// pointer by default. However, some systems may require a different size due
+/// to bugs or other conditions. We will default to a 4-byte encoding unless the
+/// system tells us otherwise.
+///
+/// The issue is when the CIE says their is an LSDA. That mandates that every
+/// FDE have an LSDA slot. But if the function does not need an LSDA. There
+/// needs to be some way to signify there is none. The LSDA is encoded as
+/// pc-rel. But you don't look for some magic value after adding the pc. You
+/// have to look for a zero before adding the pc. The problem is that the size
+/// of the zero to look for depends on the encoding. The unwinder bug in SL is
+/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8
+/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are
+/// non-zero so it goes ahead and then reads the value based on the encoding.
+/// But if you use sdata4 and there is no LSDA, then the test for zero gives a
+/// false negative and the unwinder thinks there is an LSDA.
+///
+/// FIXME: This call-back isn't good! We should be using the correct encoding
+/// regardless of the system. However, there are some systems which have bugs
+/// that prevent this from occuring.
+DwarfLSDAEncoding::Encoding PPCTargetMachine::getLSDAEncoding() const {
+ if (Subtarget.isDarwin() && Subtarget.getDarwinVers() != 10)
+ return DwarfLSDAEncoding::Default;
+
+ return DwarfLSDAEncoding::EightByte;
+}
diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h
index 3399ac8..4afcb23 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/lib/Target/PowerPC/PPCTargetMachine.h
@@ -62,6 +62,18 @@ public:
return &MachOWriterInfo;
}
+ /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are
+ /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that
+ /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded
+ /// as a 4-byte pointer by default. However, some systems may require a
+ /// different size due to bugs or other conditions. We will default to a
+ /// 4-byte encoding unless the system tells us otherwise.
+ ///
+ /// FIXME: This call-back isn't good! We should be using the correct encoding
+ /// regardless of the system. However, there are some systems which have bugs
+ /// that prevent this from occuring.
+ virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const;
+
// Pass Pipeline Configuration
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
diff --git a/lib/Target/PowerPC/TargetInfo/Makefile b/lib/Target/PowerPC/TargetInfo/Makefile
index a101aa4..16d0167 100644
--- a/lib/Target/PowerPC/TargetInfo/Makefile
+++ b/lib/Target/PowerPC/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMPowerPCInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index 69da35f..080ea42 100644
--- a/lib/Target/README.txt
+++ b/lib/Target/README.txt
@@ -1665,3 +1665,54 @@ int foo() {
//===---------------------------------------------------------------------===//
+Missed instcombine transformation:
+define i1 @a(i32 %x) nounwind readnone {
+entry:
+ %cmp = icmp eq i32 %x, 30
+ %sub = add i32 %x, -30
+ %cmp2 = icmp ugt i32 %sub, 9
+ %or = or i1 %cmp, %cmp2
+ ret i1 %or
+}
+This should be optimized to a single compare. Testcase derived from gcc.
+
+//===---------------------------------------------------------------------===//
+
+Missed instcombine transformation:
+void b();
+void a(int x) { if (((1<<x)&8)==0) b(); }
+
+The shift should be optimized out. Testcase derived from gcc.
+
+//===---------------------------------------------------------------------===//
+
+Missed instcombine or reassociate transformation:
+int a(int a, int b) { return (a==12)&(b>47)&(b<58); }
+
+The sgt and slt should be combined into a single comparison. Testcase derived
+from gcc.
+
+//===---------------------------------------------------------------------===//
+
+Missed instcombine transformation:
+define i32 @a(i32 %x) nounwind readnone {
+entry:
+ %shr = lshr i32 %x, 5 ; <i32> [#uses=1]
+ %xor = xor i32 %shr, 67108864 ; <i32> [#uses=1]
+ %sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
+ ret i32 %sub
+}
+
+This function is equivalent to "ashr i32 %x, 5". Testcase derived from gcc.
+
+//===---------------------------------------------------------------------===//
+
+isSafeToLoadUnconditionally should allow a GEP of a global/alloca with constant
+indicies within the bounds of the allocated object. Reduced example:
+
+const int a[] = {3,6};
+int b(int y) { int* x = y ? &a[0] : &a[1]; return *x; }
+
+All the loads should be eliminated. Testcase derived from gcc.
+
+//===---------------------------------------------------------------------===//
diff --git a/lib/Target/Sparc/AsmPrinter/Makefile b/lib/Target/Sparc/AsmPrinter/Makefile
index a856828..404fad1 100644
--- a/lib/Target/Sparc/AsmPrinter/Makefile
+++ b/lib/Target/Sparc/AsmPrinter/Makefile
@@ -8,6 +8,8 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMSparcAsmPrinter
+CXXFLAGS = -fno-rtti
+
# Hack: we need to include 'main' Sparc target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
index cd85dd4..8fc4e5a 100644
--- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
@@ -34,7 +34,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
@@ -61,7 +60,6 @@ namespace {
return "Sparc Assembly Printer";
}
- void PrintGlobalVariable(const GlobalVariable *GVar);
void printOperand(const MachineInstr *MI, int opNum);
void printMemOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
@@ -138,7 +136,7 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
DW->EndFunction(&MF);
// We didn't modify anything.
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
return false;
}
@@ -156,7 +154,7 @@ void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
case Function::DLLExportLinkage:
case Function::ExternalLinkage:
// Function is externally visible
- O << "\t.global\t" << CurrentFnName << '\n';
+ O << "\t.global\t" << *CurrentFnSym << '\n';
break;
case Function::LinkerPrivateLinkage:
case Function::LinkOnceAnyLinkage:
@@ -164,14 +162,14 @@ void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
// Function is weak
- O << "\t.weak\t" << CurrentFnName << '\n' ;
+ O << "\t.weak\t" << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
- O << "\t.type\t" << CurrentFnName << ", #function\n";
- O << CurrentFnName << ":\n";
+ O << "\t.type\t" << *CurrentFnSym << ", #function\n";
+ O << *CurrentFnSym << ":\n";
}
@@ -195,10 +193,10 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
O << (int)MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
@@ -277,85 +275,6 @@ void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}
-void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- O << "\n\n";
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- unsigned Size = TD->getTypeAllocSize(C->getType());
- unsigned Align = TD->getPreferredAlignment(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && !GVar->hasSection()) {
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage())
- O << "\t.local " << name << '\n';
-
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (1 << Align);
-
- O << '\n';
- return;
- }
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage: // FIXME: Verify correct for weak.
- case GlobalValue::WeakODRLinkage: // FIXME: Verify correct for weak.
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << MAI->getGlobalDirective() << name << '\n';
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- case GlobalValue::GhostLinkage:
- llvm_unreachable("Should not have any unmaterialized functions!");
- case GlobalValue::DLLImportLinkage:
- llvm_unreachable("DLLImport linkage is not supported by this target!");
- case GlobalValue::DLLExportLinkage:
- llvm_unreachable("DLLExport linkage is not supported by this target!");
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
-
- if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ",#object\n";
- O << "\t.size " << name << ',' << Size << '\n';
- }
-
- O << name << ":\n";
- EmitGlobalConstant(C);
-}
-
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile
index 6714b4d..d3e2a89 100644
--- a/lib/Target/Sparc/Makefile
+++ b/lib/Target/Sparc/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMSparcCodeGen
TARGET = Sparc
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \
diff --git a/lib/Target/Sparc/TargetInfo/Makefile b/lib/Target/Sparc/TargetInfo/Makefile
index 641ed87..0827fdb 100644
--- a/lib/Target/Sparc/TargetInfo/Makefile
+++ b/lib/Target/Sparc/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMSparcInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/SystemZ/AsmPrinter/Makefile b/lib/Target/SystemZ/AsmPrinter/Makefile
index 9a350df..36cd6f8 100644
--- a/lib/Target/SystemZ/AsmPrinter/Makefile
+++ b/lib/Target/SystemZ/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMSystemZAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' SystemZ target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp
index e97e7ca..5c3fe37 100644
--- a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp
+++ b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp
@@ -35,8 +35,6 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
-
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
@@ -73,7 +71,6 @@ namespace {
void emitFunctionHeader(const MachineFunction &MF);
bool runOnMachineFunction(MachineFunction &F);
- void PrintGlobalVariable(const GlobalVariable* GVar);
void getAnalysisUsage(AnalysisUsage &AU) const {
AsmPrinter::getAnalysisUsage(AU);
@@ -99,20 +96,20 @@ void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
case Function::LinkerPrivateLinkage:
break;
case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
+ O << "\t.globl\t" << *CurrentFnSym << '\n';
break;
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
- O << "\t.weak\t" << CurrentFnName << '\n';
+ O << "\t.weak\t" << *CurrentFnSym << '\n';
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
- O << "\t.type\t" << CurrentFnName << ",@function\n"
- << CurrentFnName << ":\n";
+ O << "\t.type\t" << *CurrentFnSym << ",@function\n";
+ O << *CurrentFnSym << ":\n";
}
bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
@@ -138,7 +135,7 @@ bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
@@ -169,13 +166,11 @@ void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getMangledName(GV);
-
- O << Name;
+ O << *GetGlobalValueSymbol(GV);
// Assemble calls via PLT for externally visible symbols if PIC.
if (TM.getRelocationModel() == Reloc::PIC_ &&
@@ -226,7 +221,7 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
@@ -239,17 +234,11 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
printOffset(MO.getOffset());
break;
- case MachineOperand::MO_GlobalAddress: {
- const GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getMangledName(GV);
-
- O << Name;
+ case MachineOperand::MO_GlobalAddress:
+ O << *GetGlobalValueSymbol(MO.getGlobal());
break;
- }
case MachineOperand::MO_ExternalSymbol: {
- std::string Name(MAI->getGlobalPrefix());
- Name += MO.getSymbolName();
- O << Name;
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
}
default:
@@ -304,87 +293,6 @@ void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
assert(!Index.getReg() && "Should allocate base register first!");
}
-void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- unsigned Size = TD->getTypeAllocSize(C->getType());
- unsigned Align = std::max(1U, TD->getPreferredAlignmentLog(GVar));
-
- printVisibility(name, GVar->getVisibility());
-
- O << "\t.type\t" << name << ",@object\n";
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && !GVar->hasSection() &&
- !GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
-
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
-
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
-
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- return;
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- O << "\t.weak\t" << name << '\n';
- break;
- case GlobalValue::DLLExportLinkage:
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << '\n';
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- // Use 16-bit alignment by default to simplify bunch of stuff
- EmitAlignment(Align, GVar, 1);
- O << name << ":";
- if (VerboseAsm) {
- O << "\t\t\t\t" << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << name << ", " << Size << '\n';
-
- EmitGlobalConstant(C);
-}
-
// Force static initialization.
extern "C" void LLVMInitializeSystemZAsmPrinter() {
RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile
index f1097eb..6d0cbbd 100644
--- a/lib/Target/SystemZ/Makefile
+++ b/lib/Target/SystemZ/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMSystemZCodeGen
TARGET = SystemZ
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \
diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp b/lib/Target/SystemZ/SystemZMCAsmInfo.cpp
index 8ea11c9..ba392bb 100644
--- a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp
+++ b/lib/Target/SystemZ/SystemZMCAsmInfo.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "SystemZMCAsmInfo.h"
+#include "llvm/MC/MCSectionELF.h"
using namespace llvm;
SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) {
@@ -21,6 +22,9 @@ SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) {
WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
PCSymbol = ".";
+}
- NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
+MCSection *SystemZMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const{
+ return MCSectionELF::Create(".note.GNU-stack", MCSectionELF::SHT_PROGBITS,
+ 0, SectionKind::getMetadata(), false, Ctx);
}
diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.h b/lib/Target/SystemZ/SystemZMCAsmInfo.h
index 3bebcb7..00cb99b 100644
--- a/lib/Target/SystemZ/SystemZMCAsmInfo.h
+++ b/lib/Target/SystemZ/SystemZMCAsmInfo.h
@@ -22,8 +22,9 @@ namespace llvm {
struct SystemZMCAsmInfo : public MCAsmInfo {
explicit SystemZMCAsmInfo(const Target &T, const StringRef &TT);
+ virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const;
};
-
+
} // namespace llvm
#endif
diff --git a/lib/Target/SystemZ/TargetInfo/Makefile b/lib/Target/SystemZ/TargetInfo/Makefile
index 0be80eb..9f36b2c 100644
--- a/lib/Target/SystemZ/TargetInfo/Makefile
+++ b/lib/Target/SystemZ/TargetInfo/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMSystemZInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/MC/MCAsmParser.cpp b/lib/Target/TargetAsmLexer.cpp
index 2287e89..0ae6c14 100644
--- a/lib/MC/MCAsmParser.cpp
+++ b/lib/Target/TargetAsmLexer.cpp
@@ -1,4 +1,4 @@
-//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
+//===-- llvm/Target/TargetAsmLexer.cpp - Target Assembly Lexer ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCAsmParser.h"
-
+#include "llvm/Target/TargetAsmLexer.h"
using namespace llvm;
-MCAsmParser::MCAsmParser() {
-}
-
-MCAsmParser::~MCAsmParser() {
-}
+TargetAsmLexer::TargetAsmLexer(const Target &T) : TheTarget(T) {}
+TargetAsmLexer::~TargetAsmLexer() {}
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index 70e8008..a231ebc 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -22,11 +22,11 @@
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -141,9 +141,18 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
return SectionKind::getThreadData();
}
+ // Variables with common linkage always get classified as common.
+ if (GVar->hasCommonLinkage())
+ return SectionKind::getCommon();
+
// Variable can be easily put to BSS section.
- if (isSuitableForBSS(GVar))
+ if (isSuitableForBSS(GVar)) {
+ if (GVar->hasLocalLinkage())
+ return SectionKind::getBSSLocal();
+ else if (GVar->hasExternalLinkage())
+ return SectionKind::getBSSExtern();
return SectionKind::getBSS();
+ }
Constant *C = GVar->getInitializer();
@@ -300,6 +309,7 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
IsIndirect = false;
IsPCRel = false;
+ // FIXME: Use GetGlobalValueSymbol.
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, false);
return MCSymbolRefExpr::Create(Name.str(), getContext());
@@ -464,30 +474,30 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
static SectionKind
-getELFKindForNamedSection(const char *Name, SectionKind K) {
- if (Name[0] != '.') return K;
+getELFKindForNamedSection(StringRef Name, SectionKind K) {
+ if (Name.empty() || Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
- if (strcmp(Name, ".bss") == 0 ||
- strncmp(Name, ".bss.", 5) == 0 ||
- strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
- strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
- strcmp(Name, ".sbss") == 0 ||
- strncmp(Name, ".sbss.", 6) == 0 ||
- strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
+ if (Name == ".bss" ||
+ Name.startswith(".bss.") ||
+ Name.startswith(".gnu.linkonce.b.") ||
+ Name.startswith(".llvm.linkonce.b.") ||
+ Name == ".sbss" ||
+ Name.startswith(".sbss.") ||
+ Name.startswith(".gnu.linkonce.sb.") ||
+ Name.startswith(".llvm.linkonce.sb."))
return SectionKind::getBSS();
- if (strcmp(Name, ".tdata") == 0 ||
- strncmp(Name, ".tdata.", 7) == 0 ||
- strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
+ if (Name == ".tdata" ||
+ Name.startswith(".tdata.") ||
+ Name.startswith(".gnu.linkonce.td.") ||
+ Name.startswith(".llvm.linkonce.td."))
return SectionKind::getThreadData();
- if (strcmp(Name, ".tbss") == 0 ||
- strncmp(Name, ".tbss.", 6) == 0 ||
- strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
+ if (Name == ".tbss" ||
+ Name.startswith(".tbss.") ||
+ Name.startswith(".gnu.linkonce.tb.") ||
+ Name.startswith(".llvm.linkonce.tb."))
return SectionKind::getThreadBSS();
return K;
@@ -543,7 +553,7 @@ getELFSectionFlags(SectionKind K) {
const MCSection *TargetLoweringObjectFileELF::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
- const char *SectionName = GV->getSection().c_str();
+ StringRef SectionName = GV->getSection();
// Infer section flags from the section name if we can.
Kind = getELFKindForNamedSection(SectionName, Kind);
@@ -560,7 +570,6 @@ static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isThreadData()) return ".gnu.linkonce.td.";
if (Kind.isThreadBSS()) return ".gnu.linkonce.tb.";
- if (Kind.isBSS()) return ".gnu.linkonce.b.";
if (Kind.isDataNoRel()) return ".gnu.linkonce.d.";
if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local.";
if (Kind.isDataRel()) return ".gnu.linkonce.d.rel.";
@@ -576,20 +585,13 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
// If this global is linkonce/weak and the target handles this by emitting it
// into a 'uniqued' section name, create and return the section now.
- if (GV->isWeakForLinker()) {
+ if (GV->isWeakForLinker() && !Kind.isCommon() && !Kind.isBSS()) {
const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
- SmallString<128> Name, MangledName;
+ SmallString<128> Name;
Name.append(Prefix, Prefix+strlen(Prefix));
Mang->getNameWithPrefix(Name, GV, false);
-
- raw_svector_ostream OS(MangledName);
- MCSymbol::printMangledName(Name, OS, 0);
- OS.flush();
-
- return getELFSection(MangledName.str(),
- getELFSectionType(MangledName.str(), Kind),
- getELFSectionFlags(Kind),
- Kind);
+ return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind),
+ getELFSectionFlags(Kind), Kind);
}
if (Kind.isText()) return TextSection;
@@ -614,7 +616,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
std::string Name = SizeSpec + utostr(Align);
- return getELFSection(Name.c_str(), MCSectionELF::SHT_PROGBITS,
+ return getELFSection(Name, MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC |
MCSectionELF::SHF_MERGE |
MCSectionELF::SHF_STRINGS,
@@ -636,7 +638,10 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
if (Kind.isThreadData()) return TLSDataSection;
if (Kind.isThreadBSS()) return TLSBSSSection;
- if (Kind.isBSS()) return BSSSection;
+ // Note: we claim that common symbols are put in BSSSection, but they are
+ // really emitted with the magic .comm directive, which creates a symbol table
+ // entry but not a section.
+ if (Kind.isBSS() || Kind.isCommon()) return BSSSection;
if (Kind.isDataNoRel()) return DataSection;
if (Kind.isDataRelLocal()) return DataRelLocalSection;
@@ -762,7 +767,13 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
DataCoalSection
= getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED,
SectionKind::getDataRel());
-
+ DataCommonSection
+ = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL,
+ SectionKind::getBSS());
+ DataBSSSection
+ = getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL,
+ SectionKind::getBSS());
+
LazySymbolPointerSection
= getMachOSection("__DATA", "__la_symbol_ptr",
@@ -921,6 +932,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
+ // Put zero initialized globals with strong external linkage in the
+ // DATA, __common section with the .zerofill directive.
+ if (Kind.isBSSExtern())
+ return DataCommonSection;
+
+ // Put zero initialized globals with local linkage in __DATA,__bss directive
+ // with the .zerofill directive (aka .lcomm).
+ if (Kind.isBSSLocal())
+ return DataBSSSection;
+
// Otherwise, just drop the variable in the normal data section.
return DataSection;
}
@@ -955,7 +976,8 @@ shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const {
// FIXME: ObjC metadata is currently emitted as internal symbols that have
// \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and
// this horrible hack can go away.
- const std::string &Name = Mang->getMangledName(GV);
+ SmallString<64> Name;
+ Mang->getNameWithPrefix(Name, GV, false);
if (Name[0] == 'L' || Name[0] == 'l')
return false;
}
@@ -1064,7 +1086,7 @@ void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
const MCSection *TargetLoweringObjectFileCOFF::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
- return getCOFFSection(GV->getSection().c_str(), false, Kind);
+ return getCOFFSection(GV->getSection(), false, Kind);
}
static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp
index 46bc9a3..fec59b5 100644
--- a/lib/Target/TargetMachine.cpp
+++ b/lib/Target/TargetMachine.cpp
@@ -46,7 +46,6 @@ namespace llvm {
bool DisableJumpTables;
bool StrongPHIElim;
bool AsmVerbosityDefault(false);
- bool DisableScheduling;
}
static cl::opt<bool, true>
@@ -198,11 +197,6 @@ EnableStrongPHIElim(cl::Hidden, "strong-phi-elim",
cl::desc("Use strong PHI elimination."),
cl::location(StrongPHIElim),
cl::init(false));
-static cl::opt<bool, true>
-DisableInstScheduling("disable-scheduling",
- cl::desc("Disable instruction scheduling"),
- cl::location(DisableScheduling),
- cl::init(false));
//---------------------------------------------------------------------------
// TargetMachine Class
diff --git a/lib/Target/X86/AsmParser/CMakeLists.txt b/lib/Target/X86/AsmParser/CMakeLists.txt
index 034d5ab..40dbdd7 100644
--- a/lib/Target/X86/AsmParser/CMakeLists.txt
+++ b/lib/Target/X86/AsmParser/CMakeLists.txt
@@ -1,6 +1,7 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
add_llvm_library(LLVMX86AsmParser
+ X86AsmLexer.cpp
X86AsmParser.cpp
)
add_dependencies(LLVMX86AsmParser X86CodeGenTable_gen)
diff --git a/lib/Target/X86/AsmParser/Makefile b/lib/Target/X86/AsmParser/Makefile
index 25fb0a2..288b985 100644
--- a/lib/Target/X86/AsmParser/Makefile
+++ b/lib/Target/X86/AsmParser/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMX86AsmParser
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' x86 target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/X86/AsmParser/X86AsmLexer.cpp b/lib/Target/X86/AsmParser/X86AsmLexer.cpp
new file mode 100644
index 0000000..1a62044
--- /dev/null
+++ b/lib/Target/X86/AsmParser/X86AsmLexer.cpp
@@ -0,0 +1,43 @@
+//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Target/TargetAsmLexer.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "X86.h"
+
+using namespace llvm;
+
+namespace {
+
+class X86AsmLexer : public TargetAsmLexer {
+ const MCAsmInfo &AsmInfo;
+protected:
+ AsmToken LexToken();
+public:
+ X86AsmLexer(const Target &T, const MCAsmInfo &MAI)
+ : TargetAsmLexer(T), AsmInfo(MAI) {
+ }
+};
+
+}
+
+AsmToken X86AsmLexer::LexToken() {
+ return AsmToken(AsmToken::Error, "", 0);
+}
+
+extern "C" void LLVMInitializeX86AsmLexer() {
+ RegisterAsmLexer<X86AsmLexer> X(TheX86_32Target);
+ RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target);
+}
+
+//#define REGISTERS_ONLY
+//#include "../X86GenAsmMatcher.inc"
+//#undef REGISTERS_ONLY
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index c4ae5d2..7a9218e 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -11,12 +11,12 @@
#include "X86.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAsmLexer.h"
-#include "llvm/MC/MCAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetAsmParser.h"
@@ -37,11 +37,10 @@ private:
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
- bool ParseRegister(X86Operand &Op);
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
- bool ParseOperand(X86Operand &Op);
-
- bool ParseMemOperand(X86Operand &Op);
+ X86Operand *ParseOperand();
+ X86Operand *ParseMemOperand();
bool ParseDirectiveWord(unsigned Size, SMLoc L);
@@ -51,10 +50,6 @@ private:
bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCInst &Inst);
- /// MatchRegisterName - Match the given string to a register name, or 0 if
- /// there is no match.
- unsigned MatchRegisterName(const StringRef &Name);
-
/// }
public:
@@ -69,19 +64,27 @@ public:
} // end anonymous namespace
+/// @name Auto-generated Match Functions
+/// {
+
+static unsigned MatchRegisterName(const StringRef &Name);
+
+/// }
namespace {
/// X86Operand - Instances of this class represent a parsed X86 machine
/// instruction.
struct X86Operand : public MCParsedAsmOperand {
- enum {
+ enum KindTy {
Token,
Register,
Immediate,
Memory
} Kind;
+ SMLoc StartLoc, EndLoc;
+
union {
struct {
const char *Data;
@@ -105,6 +108,14 @@ struct X86Operand : public MCParsedAsmOperand {
} Mem;
};
+ X86Operand(KindTy K, SMLoc Start, SMLoc End)
+ : Kind(K), StartLoc(Start), EndLoc(End) {}
+
+ /// getStartLoc - Get the location of the first token of this operand.
+ SMLoc getStartLoc() const { return StartLoc; }
+ /// getEndLoc - Get the location of the last token of this operand.
+ SMLoc getEndLoc() const { return EndLoc; }
+
StringRef getToken() const {
assert(Kind == Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
@@ -192,44 +203,40 @@ struct X86Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
}
- static X86Operand CreateToken(StringRef Str) {
- X86Operand Res;
- Res.Kind = Token;
- Res.Tok.Data = Str.data();
- Res.Tok.Length = Str.size();
+ static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
+ X86Operand *Res = new X86Operand(Token, Loc, Loc);
+ Res->Tok.Data = Str.data();
+ Res->Tok.Length = Str.size();
return Res;
}
- static X86Operand CreateReg(unsigned RegNo) {
- X86Operand Res;
- Res.Kind = Register;
- Res.Reg.RegNo = RegNo;
+ static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
+ X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
+ Res->Reg.RegNo = RegNo;
return Res;
}
- static X86Operand CreateImm(const MCExpr *Val) {
- X86Operand Res;
- Res.Kind = Immediate;
- Res.Imm.Val = Val;
+ static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
+ X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
+ Res->Imm.Val = Val;
return Res;
}
- static X86Operand CreateMem(unsigned SegReg, const MCExpr *Disp,
- unsigned BaseReg, unsigned IndexReg,
- unsigned Scale) {
+ static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
+ unsigned BaseReg, unsigned IndexReg,
+ unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
// We should never just have a displacement, that would be an immediate.
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
// The scale should always be one of {1,2,4,8}.
assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
"Invalid scale!");
- X86Operand Res;
- Res.Kind = Memory;
- Res.Mem.SegReg = SegReg;
- Res.Mem.Disp = Disp;
- Res.Mem.BaseReg = BaseReg;
- Res.Mem.IndexReg = IndexReg;
- Res.Mem.Scale = Scale;
+ X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
+ Res->Mem.SegReg = SegReg;
+ Res->Mem.Disp = Disp;
+ Res->Mem.BaseReg = BaseReg;
+ Res->Mem.IndexReg = IndexReg;
+ Res->Mem.Scale = Scale;
return Res;
}
};
@@ -237,52 +244,57 @@ struct X86Operand : public MCParsedAsmOperand {
} // end anonymous namespace.
-bool X86ATTAsmParser::ParseRegister(X86Operand &Op) {
- const AsmToken &TokPercent = getLexer().getTok();
- (void)TokPercent; // Avoid warning when assertions are disabled.
+bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
+ SMLoc &StartLoc, SMLoc &EndLoc) {
+ RegNo = 0;
+ const AsmToken &TokPercent = Parser.getTok();
assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
- getLexer().Lex(); // Eat percent token.
+ StartLoc = TokPercent.getLoc();
+ Parser.Lex(); // Eat percent token.
- const AsmToken &Tok = getLexer().getTok();
+ const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return Error(Tok.getLoc(), "invalid register name");
// FIXME: Validate register for the current architecture; we have to do
// validation later, so maybe there is no need for this here.
- unsigned RegNo;
-
RegNo = MatchRegisterName(Tok.getString());
if (RegNo == 0)
return Error(Tok.getLoc(), "invalid register name");
- Op = X86Operand::CreateReg(RegNo);
- getLexer().Lex(); // Eat identifier token.
-
+ EndLoc = Tok.getLoc();
+ Parser.Lex(); // Eat identifier token.
return false;
}
-bool X86ATTAsmParser::ParseOperand(X86Operand &Op) {
+X86Operand *X86ATTAsmParser::ParseOperand() {
switch (getLexer().getKind()) {
default:
- return ParseMemOperand(Op);
- case AsmToken::Percent:
+ return ParseMemOperand();
+ case AsmToken::Percent: {
// FIXME: if a segment register, this could either be just the seg reg, or
// the start of a memory operand.
- return ParseRegister(Op);
+ unsigned RegNo;
+ SMLoc Start, End;
+ if (ParseRegister(RegNo, Start, End)) return 0;
+ return X86Operand::CreateReg(RegNo, Start, End);
+ }
case AsmToken::Dollar: {
// $42 -> immediate.
- getLexer().Lex();
+ SMLoc Start = Parser.getTok().getLoc(), End;
+ Parser.Lex();
const MCExpr *Val;
- if (getParser().ParseExpression(Val))
- return true;
- Op = X86Operand::CreateImm(Val);
- return false;
+ if (getParser().ParseExpression(Val, End))
+ return 0;
+ return X86Operand::CreateImm(Val, Start, End);
}
}
}
/// ParseMemOperand: segment: disp(basereg, indexreg, scale)
-bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
+X86Operand *X86ATTAsmParser::ParseMemOperand() {
+ SMLoc MemStart = Parser.getTok().getLoc();
+
// FIXME: If SegReg ':' (e.g. %gs:), eat and remember.
unsigned SegReg = 0;
@@ -292,47 +304,47 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
// it.
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
if (getLexer().isNot(AsmToken::LParen)) {
- if (getParser().ParseExpression(Disp)) return true;
+ SMLoc ExprEnd;
+ if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
// After parsing the base expression we could either have a parenthesized
// memory address or not. If not, return now. If so, eat the (.
if (getLexer().isNot(AsmToken::LParen)) {
// Unless we have a segment register, treat this as an immediate.
- if (SegReg)
- Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
- else
- Op = X86Operand::CreateImm(Disp);
- return false;
+ if (SegReg == 0)
+ return X86Operand::CreateImm(Disp, MemStart, ExprEnd);
+ return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
}
// Eat the '('.
- getLexer().Lex();
+ Parser.Lex();
} else {
// Okay, we have a '('. We don't know if this is an expression or not, but
// so we have to eat the ( to see beyond it.
- getLexer().Lex(); // Eat the '('.
+ SMLoc LParenLoc = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat the '('.
if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
// Nothing to do here, fall into the code below with the '(' part of the
// memory operand consumed.
} else {
+ SMLoc ExprEnd;
+
// It must be an parenthesized expression, parse it now.
- if (getParser().ParseParenExpression(Disp))
- return true;
+ if (getParser().ParseParenExpression(Disp, ExprEnd))
+ return 0;
// After parsing the base expression we could either have a parenthesized
// memory address or not. If not, return now. If so, eat the (.
if (getLexer().isNot(AsmToken::LParen)) {
// Unless we have a segment register, treat this as an immediate.
- if (SegReg)
- Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
- else
- Op = X86Operand::CreateImm(Disp);
- return false;
+ if (SegReg == 0)
+ return X86Operand::CreateImm(Disp, LParenLoc, ExprEnd);
+ return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
}
// Eat the '('.
- getLexer().Lex();
+ Parser.Lex();
}
}
@@ -341,13 +353,12 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
if (getLexer().is(AsmToken::Percent)) {
- if (ParseRegister(Op))
- return true;
- BaseReg = Op.getReg();
+ SMLoc L;
+ if (ParseRegister(BaseReg, L, L)) return 0;
}
if (getLexer().is(AsmToken::Comma)) {
- getLexer().Lex(); // Eat the comma.
+ Parser.Lex(); // Eat the comma.
// Following the comma we should have either an index register, or a scale
// value. We don't support the later form, but we want to parse it
@@ -356,82 +367,89 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
// Not that even though it would be completely consistent to support syntax
// like "1(%eax,,1)", the assembler doesn't.
if (getLexer().is(AsmToken::Percent)) {
- if (ParseRegister(Op))
- return true;
- IndexReg = Op.getReg();
+ SMLoc L;
+ if (ParseRegister(IndexReg, L, L)) return 0;
if (getLexer().isNot(AsmToken::RParen)) {
// Parse the scale amount:
// ::= ',' [scale-expression]
- if (getLexer().isNot(AsmToken::Comma))
- return true;
- getLexer().Lex(); // Eat the comma.
+ if (getLexer().isNot(AsmToken::Comma)) {
+ Error(Parser.getTok().getLoc(),
+ "expected comma in scale expression");
+ return 0;
+ }
+ Parser.Lex(); // Eat the comma.
if (getLexer().isNot(AsmToken::RParen)) {
- SMLoc Loc = getLexer().getTok().getLoc();
+ SMLoc Loc = Parser.getTok().getLoc();
int64_t ScaleVal;
if (getParser().ParseAbsoluteExpression(ScaleVal))
- return true;
+ return 0;
// Validate the scale amount.
- if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
- return Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
+ if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
+ Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
+ return 0;
+ }
Scale = (unsigned)ScaleVal;
}
}
} else if (getLexer().isNot(AsmToken::RParen)) {
// Otherwise we have the unsupported form of a scale amount without an
// index.
- SMLoc Loc = getLexer().getTok().getLoc();
+ SMLoc Loc = Parser.getTok().getLoc();
int64_t Value;
if (getParser().ParseAbsoluteExpression(Value))
- return true;
+ return 0;
- return Error(Loc, "cannot have scale factor without index register");
+ Error(Loc, "cannot have scale factor without index register");
+ return 0;
}
}
// Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
- if (getLexer().isNot(AsmToken::RParen))
- return Error(getLexer().getTok().getLoc(),
- "unexpected token in memory operand");
- getLexer().Lex(); // Eat the ')'.
+ if (getLexer().isNot(AsmToken::RParen)) {
+ Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
+ return 0;
+ }
+ SMLoc MemEnd = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat the ')'.
- Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale);
- return false;
+ return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
+ MemStart, MemEnd);
}
bool X86ATTAsmParser::
ParseInstruction(const StringRef &Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- Operands.push_back(new X86Operand(X86Operand::CreateToken(Name)));
+ Operands.push_back(X86Operand::CreateToken(Name, NameLoc));
- SMLoc Loc = getLexer().getTok().getLoc();
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Parse '*' modifier.
if (getLexer().is(AsmToken::Star)) {
- getLexer().Lex(); // Eat the star.
- Operands.push_back(new X86Operand(X86Operand::CreateToken("*")));
+ SMLoc Loc = Parser.getTok().getLoc();
+ Operands.push_back(X86Operand::CreateToken("*", Loc));
+ Parser.Lex(); // Eat the star.
}
// Read the first operand.
- X86Operand Op;
- if (ParseOperand(Op))
+ if (X86Operand *Op = ParseOperand())
+ Operands.push_back(Op);
+ else
return true;
-
- Operands.push_back(new X86Operand(Op));
-
+
while (getLexer().is(AsmToken::Comma)) {
- getLexer().Lex(); // Eat the comma.
+ Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
- if (ParseOperand(Op))
+ if (X86Operand *Op = ParseOperand())
+ Operands.push_back(Op);
+ else
return true;
- Operands.push_back(new X86Operand(Op));
}
}
@@ -454,7 +472,7 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
if (getParser().ParseExpression(Value))
return true;
- getParser().getStreamer().EmitValue(Value, Size);
+ getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -462,18 +480,21 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
// FIXME: Improve diagnostic.
if (getLexer().isNot(AsmToken::Comma))
return Error(L, "unexpected token in directive");
- getLexer().Lex();
+ Parser.Lex();
}
}
- getLexer().Lex();
+ Parser.Lex();
return false;
}
+extern "C" void LLVMInitializeX86AsmLexer();
+
// Force static initialization.
extern "C" void LLVMInitializeX86AsmParser() {
RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target);
RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
+ LLVMInitializeX86AsmLexer();
}
#include "X86GenAsmMatcher.inc"
diff --git a/lib/Target/X86/AsmPrinter/Makefile b/lib/Target/X86/AsmPrinter/Makefile
index 2368761..326a22f 100644
--- a/lib/Target/X86/AsmPrinter/Makefile
+++ b/lib/Target/X86/AsmPrinter/Makefile
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMX86AsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' x86 target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
index c74b97a..804dbb9 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
@@ -55,7 +55,7 @@ void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
O << (int)Op.getImm();
else {
assert(Op.isExpr() && "unknown pcrel immediate operand");
- Op.getExpr()->print(O, &MAI);
+ O << *Op.getExpr();
}
}
@@ -68,8 +68,7 @@ void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) {
O << '$' << Op.getImm();
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
- O << '$';
- Op.getExpr()->print(O, &MAI);
+ O << '$' << *Op.getExpr();
}
}
@@ -84,7 +83,7 @@ void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
O << DispVal;
} else {
assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
- DispSpec.getExpr()->print(O, &MAI);
+ O << *DispSpec.getExpr();
}
if (IndexReg.getReg() || BaseReg.getReg()) {
diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
index 70c6dd0..2ffa18f 100644
--- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
@@ -36,7 +36,6 @@
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
@@ -61,7 +60,7 @@ void X86AsmPrinter::printMCInst(const MCInst *MI) {
void X86AsmPrinter::PrintPICBaseSymbol() const {
// FIXME: Gross const cast hack.
X86AsmPrinter *AP = const_cast<X86AsmPrinter*>(this);
- X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol()->print(O, MAI);
+ O << *X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol();
}
void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
@@ -71,7 +70,8 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
if (Subtarget->isTargetCygMing()) {
X86COFFMachineModuleInfo &COFFMMI =
MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
- COFFMMI.DecorateCygMingName(CurrentFnName, F, *TM.getTargetData());
+ COFFMMI.DecorateCygMingName(CurrentFnSym, OutContext, F,
+ *TM.getTargetData());
}
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
@@ -84,7 +84,7 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
break;
case Function::DLLExportLinkage:
case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
+ OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global);
break;
case Function::LinkerPrivateLinkage:
case Function::LinkOnceAnyLinkage:
@@ -92,30 +92,30 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
if (Subtarget->isTargetDarwin()) {
- O << "\t.globl\t" << CurrentFnName << '\n';
- O << MAI->getWeakDefDirective() << CurrentFnName << '\n';
+ OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global);
+ O << MAI->getWeakDefDirective() << *CurrentFnSym << '\n';
} else if (Subtarget->isTargetCygMing()) {
- O << "\t.globl\t" << CurrentFnName << "\n"
- "\t.linkonce discard\n";
+ OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global);
+ O << "\t.linkonce discard\n";
} else {
- O << "\t.weak\t" << CurrentFnName << '\n';
+ O << "\t.weak\t" << *CurrentFnSym << '\n';
}
break;
}
- printVisibility(CurrentFnName, F->getVisibility());
+ printVisibility(CurrentFnSym, F->getVisibility());
- if (Subtarget->isTargetELF())
- O << "\t.type\t" << CurrentFnName << ",@function\n";
- else if (Subtarget->isTargetCygMing()) {
- O << "\t.def\t " << CurrentFnName
- << ";\t.scl\t" <<
+ if (Subtarget->isTargetELF()) {
+ O << "\t.type\t" << *CurrentFnSym << ",@function\n";
+ } else if (Subtarget->isTargetCygMing()) {
+ O << "\t.def\t " << *CurrentFnSym;
+ O << ";\t.scl\t" <<
(F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT)
<< ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
<< ";\t.endef\n";
}
- O << CurrentFnName << ':';
+ O << *CurrentFnSym << ':';
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
@@ -126,7 +126,7 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
// Add some workaround for linkonce linkage on Cygwin\MinGW
if (Subtarget->isTargetCygMing() &&
(F->hasLinkOnceLinkage() || F->hasWeakLinkage()))
- O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n";
+ O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n";
}
/// runOnMachineFunction - This uses the printMachineInstruction()
@@ -184,7 +184,7 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
// Emit post-function debug information.
if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling())
@@ -201,93 +201,78 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
/// jump tables, constant pools, global address and external symbols, all of
/// which print to a label with various suffixes for relocation types etc.
void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) {
- SmallString<128> TempNameStr;
switch (MO.getType()) {
default: llvm_unreachable("unknown symbol type!");
case MachineOperand::MO_JumpTableIndex:
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
- << MO.getIndex();
+ O << *GetJTISymbol(MO.getIndex());
break;
case MachineOperand::MO_ConstantPoolIndex:
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
- << MO.getIndex();
+ O << *GetCPISymbol(MO.getIndex());
printOffset(MO.getOffset());
break;
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
- const char *Suffix = "";
+ MCSymbol *GVSym;
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
- Suffix = "$stub";
+ GVSym = GetSymbolWithGlobalValueBase(GV, "$stub");
else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
- Suffix = "$non_lazy_ptr";
-
- std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
+ GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
+ else
+ GVSym = GetGlobalValueSymbol(GV);
+
if (Subtarget->isTargetCygMing()) {
X86COFFMachineModuleInfo &COFFMMI =
MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
- COFFMMI.DecorateCygMingName(Name, GV, *TM.getTargetData());
+ COFFMMI.DecorateCygMingName(GVSym, OutContext, GV, *TM.getTargetData());
}
// Handle dllimport linkage.
if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
- Name = "__imp_" + Name;
+ GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName());
if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) {
- Mang->getNameWithPrefix(TempNameStr, GV, true);
- TempNameStr += "$non_lazy_ptr";
- MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
const MCSymbol *&StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);
- if (StubSym == 0) {
- TempNameStr.clear();
- Mang->getNameWithPrefix(TempNameStr, GV, false);
- StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str());
- }
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
+
} else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){
- Mang->getNameWithPrefix(TempNameStr, GV, true);
- TempNameStr += "$non_lazy_ptr";
- MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
const MCSymbol *&StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym);
- if (StubSym == 0) {
- TempNameStr.clear();
- Mang->getNameWithPrefix(TempNameStr, GV, false);
- StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str());
- }
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
} else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
- Mang->getNameWithPrefix(TempNameStr, GV, true);
- TempNameStr += "$stub";
- MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub");
const MCSymbol *&StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
- if (StubSym == 0) {
- TempNameStr.clear();
- Mang->getNameWithPrefix(TempNameStr, GV, false);
- StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str());
- }
+ if (StubSym == 0)
+ StubSym = GetGlobalValueSymbol(GV);
}
// If the name begins with a dollar-sign, enclose it in parens. We do this
// to avoid having it look like an integer immediate to the assembler.
- if (Name[0] == '$')
- O << '(' << Name << ')';
+ if (GVSym->getName()[0] != '$')
+ O << *GVSym;
else
- O << Name;
-
+ O << '(' << *GVSym << ')';
printOffset(MO.getOffset());
break;
}
case MachineOperand::MO_ExternalSymbol: {
const MCSymbol *SymToPrint;
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
- Mang->getNameWithPrefix(TempNameStr,
- StringRef(MO.getSymbolName())+"$stub");
- const MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ SmallString<128> TempNameStr;
+ TempNameStr += StringRef(MO.getSymbolName());
+ TempNameStr += StringRef("$stub");
+
+ const MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str());
const MCSymbol *&StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
if (StubSym == 0) {
@@ -296,19 +281,15 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) {
}
SymToPrint = StubSym;
} else {
- Mang->getNameWithPrefix(TempNameStr, MO.getSymbolName());
- SymToPrint = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName());
}
// If the name begins with a dollar-sign, enclose it in parens. We do this
// to avoid having it look like an integer immediate to the assembler.
if (SymToPrint->getName()[0] != '$')
- SymToPrint->print(O, MAI);
- else {
- O << '(';
- SymToPrint->print(O, MAI);
- O << '(';
- }
+ O << *SymToPrint;
+ else
+ O << '(' << *SymToPrint << '(';
break;
}
}
@@ -357,7 +338,7 @@ void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
return;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
@@ -368,7 +349,7 @@ void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier) {
+ const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: llvm_unreachable("unknown operand type!");
@@ -482,11 +463,10 @@ void X86AsmPrinter::printPICJumpTableSetLabel(unsigned uid,
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MBB->getNumber());
if (Subtarget->isPICStyleRIPRel())
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << uid << '\n';
+ O << '-' << *GetJTISymbol(uid) << '\n';
else {
O << '-';
PrintPICBaseSymbol();
@@ -513,11 +493,10 @@ void X86AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStubPIC()) {
O << MAI->getPrivateGlobalPrefix() << getFunctionNumber()
<< '_' << uid << "_set_" << MBB->getNumber();
- } else if (Subtarget->isPICStyleGOT()) {
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
- O << "@GOTOFF";
- } else
- GetMBBSymbol(MBB->getNumber())->print(O, MAI);
+ } else if (Subtarget->isPICStyleGOT())
+ O << *GetMBBSymbol(MBB->getNumber()) << "@GOTOFF";
+ else
+ O << *GetMBBSymbol(MBB->getNumber());
}
bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) {
@@ -664,147 +643,6 @@ void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
processDebugLoc(MI, false);
}
-void X86AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar)) {
- if (Subtarget->isTargetDarwin() &&
- TM.getRelocationModel() == Reloc::Static) {
- if (GVar->getName() == "llvm.global_ctors")
- O << ".reference .constructors_used\n";
- else if (GVar->getName() == "llvm.global_dtors")
- O << ".reference .destructors_used\n";
- }
- return;
- }
-
- const TargetData *TD = TM.getTargetData();
-
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- if (Subtarget->isTargetELF())
- O << "\t.type\t" << name << ",@object\n";
-
-
- SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
- const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
- OutStreamer.SwitchSection(TheSection);
-
- // FIXME: get this stuff from section kind flags.
- if (C->isNullValue() && !GVar->hasSection() &&
- // Don't put things that should go in the cstring section into "comm".
- !TheSection->getKind().isMergeableCString()) {
- if (GVar->hasExternalLinkage()) {
- if (const char *Directive = MAI->getZeroFillDirective()) {
- O << "\t.globl " << name << '\n';
- O << Directive << "__DATA, __common, " << name << ", "
- << Size << ", " << Align << '\n';
- return;
- }
- }
-
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (MAI->getLCOMMDirective() != NULL) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << name << ',' << Size;
- if (Subtarget->isTargetDarwin())
- O << ',' << Align;
- } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) {
- O << "\t.globl " << name << '\n'
- << MAI->getWeakDefDirective() << name << '\n';
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- } else {
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- } else {
- if (!Subtarget->isTargetCygMing()) {
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
- }
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- return;
- }
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- if (Subtarget->isTargetDarwin()) {
- O << "\t.globl " << name << '\n'
- << MAI->getWeakDefDirective() << name << '\n';
- } else if (Subtarget->isTargetCygMing()) {
- O << "\t.globl\t" << name << "\n"
- "\t.linkonce same_size\n";
- } else {
- O << "\t.weak\t" << name << '\n';
- }
- break;
- case GlobalValue::DLLExportLinkage:
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << '\n';
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm){
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
-
- EmitGlobalConstant(C);
-
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << name << ", " << Size << '\n';
-}
-
void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetDarwin()) {
// All darwin targets use mach-o.
@@ -828,10 +666,9 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
OutStreamer.SwitchSection(TheSection);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- Stubs[i].first->print(O, MAI);
- O << ":\n" << "\t.indirect_symbol ";
+ O << *Stubs[i].first << ":\n";
// Get the MCSymbol without the $stub suffix.
- Stubs[i].second->print(O, MAI);
+ O << "\t.indirect_symbol " << *Stubs[i].second;
O << "\n\thlt ; hlt ; hlt ; hlt ; hlt\n";
}
O << '\n';
@@ -849,9 +686,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
OutStreamer.SwitchSection(TheSection);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- Stubs[i].first->print(O, MAI);
- O << ":\n\t.indirect_symbol ";
- Stubs[i].second->print(O, MAI);
+ O << *Stubs[i].first << ":\n\t.indirect_symbol " << *Stubs[i].second;
O << "\n\t.long\t0\n";
}
Stubs.clear();
@@ -863,10 +698,8 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
EmitAlignment(2);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- Stubs[i].first->print(O, MAI);
- O << ":\n" << MAI->getData32bitsDirective();
- Stubs[i].second->print(O, MAI);
- O << '\n';
+ O << *Stubs[i].first << ":\n" << MAI->getData32bitsDirective();
+ O << *Stubs[i].second << '\n';
}
Stubs.clear();
}
@@ -876,7 +709,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
- OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+ OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
}
if (Subtarget->isTargetCOFF()) {
@@ -894,25 +727,22 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetCygMing()) {
// Necessary for dllexport support
- std::vector<std::string> DLLExportedFns, DLLExportedGlobals;
+ std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals;
TargetLoweringObjectFileCOFF &TLOFCOFF =
static_cast<TargetLoweringObjectFileCOFF&>(getObjFileLowering());
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
if (I->hasDLLExportLinkage()) {
- std::string Name = Mang->getMangledName(I);
- COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData());
- DLLExportedFns.push_back(Name);
+ MCSymbol *Sym = GetGlobalValueSymbol(I);
+ COFFMMI.DecorateCygMingName(Sym, OutContext, I, *TM.getTargetData());
+ DLLExportedFns.push_back(Sym);
}
for (Module::const_global_iterator I = M.global_begin(),
E = M.global_end(); I != E; ++I)
- if (I->hasDLLExportLinkage()) {
- std::string Name = Mang->getMangledName(I);
- COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData());
- DLLExportedGlobals.push_back(Mang->getMangledName(I));
- }
+ if (I->hasDLLExportLinkage())
+ DLLExportedGlobals.push_back(GetGlobalValueSymbol(I));
// Output linker support code for dllexported globals on windows.
if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) {
@@ -920,10 +750,10 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
true,
SectionKind::getMetadata()));
for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i)
- O << "\t.ascii \" -export:" << DLLExportedGlobals[i] << ",data\"\n";
+ O << "\t.ascii \" -export:" << *DLLExportedGlobals[i] << ",data\"\n";
for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i)
- O << "\t.ascii \" -export:" << DLLExportedFns[i] << "\"\n";
+ O << "\t.ascii \" -export:" << *DLLExportedFns[i] << "\"\n";
}
}
}
diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h
index 0351829..6a9262d 100644
--- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h
+++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h
@@ -135,7 +135,6 @@ class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter {
unsigned uid) const;
void printPICLabel(const MachineInstr *MI, unsigned Op);
- void PrintGlobalVariable(const GlobalVariable* GVar);
void PrintPICBaseSymbol() const;
diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp
index fde5902..4efb529 100644
--- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp
@@ -52,7 +52,7 @@ void X86IntelInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
O << Op.getImm();
else {
assert(Op.isExpr() && "unknown pcrel immediate operand");
- Op.getExpr()->print(O, &MAI);
+ O << *Op.getExpr();
}
}
@@ -72,7 +72,7 @@ void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << Op.getImm();
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
- Op.getExpr()->print(O, &MAI);
+ O << *Op.getExpr();
}
}
@@ -102,7 +102,7 @@ void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
if (!DispSpec.isImm()) {
if (NeedPlus) O << " + ";
assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
- DispSpec.getExpr()->print(O, &MAI);
+ O << *DispSpec.getExpr();
} else {
int64_t DispVal = DispSpec.getImm();
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {
diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
index 9ee118c..b970d46 100644
--- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
+++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp
@@ -16,16 +16,15 @@
#include "X86AsmPrinter.h"
#include "X86MCAsmInfo.h"
#include "X86COFFMachineModuleInfo.h"
+#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Analysis/DebugInfo.h"
using namespace llvm;
@@ -83,33 +82,24 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const {
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
const MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym);
- if (StubSym == 0) {
- Name.clear();
- Mang->getNameWithPrefix(Name, GV, false);
- StubSym = Ctx.GetOrCreateSymbol(Name.str());
- }
+ if (StubSym == 0)
+ StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
return Sym;
}
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
Name += "$non_lazy_ptr";
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
const MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym);
- if (StubSym == 0) {
- Name.clear();
- Mang->getNameWithPrefix(Name, GV, false);
- StubSym = Ctx.GetOrCreateSymbol(Name.str());
- }
+ if (StubSym == 0)
+ StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
return Sym;
}
case X86II::MO_DARWIN_STUB: {
Name += "$stub";
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
- if (StubSym == 0) {
- Name.clear();
- Mang->getNameWithPrefix(Name, GV, false);
- StubSym = Ctx.GetOrCreateSymbol(Name.str());
- }
+ if (StubSym == 0)
+ StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
return Sym;
}
// FIXME: These probably should be a modifier on the symbol or something??
@@ -173,6 +163,8 @@ GetExternalSymbolSymbol(const MachineOperand &MO) const {
MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
SmallString<256> Name;
+ // FIXME: Use AsmPrinter.GetJTISymbol. @TLSGD shouldn't be part of the symbol
+ // name!
raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "JTI"
<< AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
@@ -204,6 +196,8 @@ MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
MCSymbol *X86MCInstLower::
GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
SmallString<256> Name;
+ // FIXME: USe AsmPrinter.GetCPISymbol. @TLSGD shouldn't be part of the symbol
+ // name!
raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "CPI"
<< AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
@@ -422,22 +416,28 @@ void X86AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
printLabel(MI);
return;
case TargetInstrInfo::DEBUG_VALUE: {
+ // FIXME: if this is implemented for another target before it goes
+ // away completely, the common part should be moved into AsmPrinter.
if (!VerboseAsm)
return;
O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
- // cast away const; DIetc do not take const operands for some reason
- DIVariable V((MDNode*)(MI->getOperand(2).getMetadata()));
+ unsigned NOps = MI->getNumOperands();
+ // cast away const; DIetc do not take const operands for some reason.
+ DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata()));
O << V.getName();
O << " <- ";
- if (MI->getOperand(0).getType()==MachineOperand::MO_Register)
+ if (NOps==3) {
+ // Variable is in register
+ assert(MI->getOperand(0).getType()==MachineOperand::MO_Register);
printOperand(MI, 0);
- else {
- assert(MI->getOperand(0).getType()==MachineOperand::MO_Immediate);
- int64_t imm = MI->getOperand(0).getImm();
- O << '[' << ((imm<0) ? "EBP" : "ESP+") << imm << ']';
+ } else {
+ // Frame address. Currently handles register +- offset only.
+ assert(MI->getOperand(0).getType()==MachineOperand::MO_Register);
+ assert(MI->getOperand(3).getType()==MachineOperand::MO_Immediate);
+ O << '['; printOperand(MI, 0); O << '+'; printOperand(MI, 3); O << ']';
}
O << "+";
- printOperand(MI, 1);
+ printOperand(MI, NOps-2);
return;
}
case TargetInstrInfo::INLINEASM:
diff --git a/lib/Target/X86/Disassembler/Makefile b/lib/Target/X86/Disassembler/Makefile
index b289647..6c26853 100644
--- a/lib/Target/X86/Disassembler/Makefile
+++ b/lib/Target/X86/Disassembler/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMX86Disassembler
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' x86 target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile
index 6098dbf..5e625dc 100644
--- a/lib/Target/X86/Makefile
+++ b/lib/Target/X86/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMX86CodeGen
TARGET = X86
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \
diff --git a/lib/Target/X86/TargetInfo/Makefile b/lib/Target/X86/TargetInfo/Makefile
index 6677d4b..211607f 100644
--- a/lib/Target/X86/TargetInfo/Makefile
+++ b/lib/Target/X86/TargetInfo/Makefile
@@ -6,8 +6,10 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../../..
LIBRARYNAME = LLVMX86Info
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.cpp b/lib/Target/X86/X86COFFMachineModuleInfo.cpp
index 01c4fcf..ea52795 100644
--- a/lib/Target/X86/X86COFFMachineModuleInfo.cpp
+++ b/lib/Target/X86/X86COFFMachineModuleInfo.cpp
@@ -15,6 +15,8 @@
#include "X86MachineFunctionInfo.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -23,7 +25,6 @@ using namespace llvm;
X86COFFMachineModuleInfo::X86COFFMachineModuleInfo(const MachineModuleInfo &) {
}
X86COFFMachineModuleInfo::~X86COFFMachineModuleInfo() {
-
}
void X86COFFMachineModuleInfo::AddFunctionInfo(const Function *F,
@@ -114,10 +115,12 @@ void X86COFFMachineModuleInfo::DecorateCygMingName(SmallVectorImpl<char> &Name,
/// DecorateCygMingName - Query FunctionInfoMap and use this information for
/// various name decorations for Cygwin and MingW.
-void X86COFFMachineModuleInfo::DecorateCygMingName(std::string &Name,
+void X86COFFMachineModuleInfo::DecorateCygMingName(MCSymbol *&Name,
+ MCContext &Ctx,
const GlobalValue *GV,
const TargetData &TD) {
- SmallString<128> NameStr(Name.begin(), Name.end());
+ SmallString<128> NameStr(Name->getName().begin(), Name->getName().end());
DecorateCygMingName(NameStr, GV, TD);
- Name.assign(NameStr.begin(), NameStr.end());
+
+ Name = Ctx.GetOrCreateSymbol(NameStr.str());
}
diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.h b/lib/Target/X86/X86COFFMachineModuleInfo.h
index 5017af2..0e2009e 100644
--- a/lib/Target/X86/X86COFFMachineModuleInfo.h
+++ b/lib/Target/X86/X86COFFMachineModuleInfo.h
@@ -46,8 +46,8 @@ public:
~X86COFFMachineModuleInfo();
- void DecorateCygMingName(std::string &Name, const GlobalValue *GV,
- const TargetData &TD);
+ void DecorateCygMingName(MCSymbol* &Name, MCContext &Ctx,
+ const GlobalValue *GV, const TargetData &TD);
void DecorateCygMingName(SmallVectorImpl<char> &Name, const GlobalValue *GV,
const TargetData &TD);
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 7e02d59..d5ad61b 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -1153,6 +1153,10 @@ bool X86FastISel::X86VisitIntrinsicCall(IntrinsicInst &I) {
// FIXME: Handle more intrinsics.
switch (I.getIntrinsicID()) {
default: return false;
+ case Intrinsic::trap: {
+ BuildMI(MBB, DL, TII.get(X86::TRAP));
+ return true;
+ }
case Intrinsic::sadd_with_overflow:
case Intrinsic::uadd_with_overflow: {
// Replace "add with overflow" intrinsics with an "add" instruction followed
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index e2a53d1..91e0483 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -384,8 +384,11 @@ static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
///
static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
SDValue &Load) {
- if (N.getOpcode() == ISD::BIT_CONVERT)
+ if (N.getOpcode() == ISD::BIT_CONVERT) {
+ if (!N.hasOneUse())
+ return false;
N = N.getOperand(0);
+ }
LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
if (!LD || LD->isVolatile())
@@ -595,6 +598,7 @@ void X86DAGToDAGISel::PreprocessForRMW() {
if (RModW) {
MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain);
++NumLoadMoved;
+ checkForCycles(I);
}
}
}
@@ -940,7 +944,7 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
// Okay, we know that we have a scale by now. However, if the scaled
// value is an add of something and a constant, we can fold the
// constant into the disp field here.
- if (ShVal.getNode()->getOpcode() == ISD::ADD && ShVal.hasOneUse() &&
+ if (ShVal.getNode()->getOpcode() == ISD::ADD &&
isa<ConstantSDNode>(ShVal.getNode()->getOperand(1))) {
AM.IndexReg = ShVal.getNode()->getOperand(0);
ConstantSDNode *AddVal =
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 228ec9f..11e07df 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -3390,17 +3390,10 @@ X86TargetLowering::LowerAsSplatVectorLoad(SDValue SrcOp, EVT VT, DebugLoc dl,
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
if (DAG.InferPtrAlignment(Ptr) < 16) {
if (MFI->isFixedObjectIndex(FI)) {
- // Can't change the alignment. Reference stack + offset explicitly
- // if stack pointer is at least 16-byte aligned.
- unsigned StackAlign = Subtarget->getStackAlignment();
- if (StackAlign < 16)
- return SDValue();
- Offset = MFI->getObjectOffset(FI) + Offset;
- SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr,
- getPointerTy());
- Ptr = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr,
- DAG.getConstant(Offset & ~15, getPointerTy()));
- Offset %= 16;
+ // Can't change the alignment. FIXME: It's possible to compute
+ // the exact stack offset and reference FI + adjust offset instead.
+ // If someone *really* cares about this. That's the way to implement it.
+ return SDValue();
} else {
MFI->setObjectAlignment(FI, 16);
}
@@ -7579,7 +7572,7 @@ bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
bool X86TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const {
// x86-64 implicitly zero-extends 32-bit results in 64-bit registers.
- return Ty1->isInteger(64) && Ty2->isInteger(64) && Subtarget->is64Bit();
+ return Ty1->isInteger(32) && Ty2->isInteger(64) && Subtarget->is64Bit();
}
bool X86TargetLowering::isZExtFree(EVT VT1, EVT VT2) const {
diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td
index 08e1dd1..9037ba6 100644
--- a/lib/Target/X86/X86Instr64bit.td
+++ b/lib/Target/X86/X86Instr64bit.td
@@ -207,7 +207,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
// EH Pseudo Instructions
//
let isTerminator = 1, isReturn = 1, isBarrier = 1,
- hasCtrlDep = 1 in {
+ hasCtrlDep = 1, isCodeGenOnly = 1 in {
def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
"ret\t#eh_return, addr: $addr",
[(X86ehret GR64:$addr)]>;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 7b39fb3..3ae352c 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -402,7 +402,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
{ X86::MOVSX64rr32, X86::MOVSX64rm32, 0 },
{ X86::MOVSX64rr8, X86::MOVSX64rm8, 0 },
{ X86::MOVUPDrr, X86::MOVUPDrm, 16 },
- { X86::MOVUPSrr, X86::MOVUPSrm, 16 },
+ { X86::MOVUPSrr, X86::MOVUPSrm, 0 },
{ X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 },
{ X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 },
{ X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, 16 },
@@ -2077,8 +2077,7 @@ void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
unsigned SrcReg, bool isKill, int FrameIdx,
const TargetRegisterClass *RC) const {
const MachineFunction &MF = *MBB.getParent();
- bool isAligned = (RI.getStackAlignment() >= 16) ||
- RI.needsStackRealignment(MF);
+ bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF);
unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM);
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
@@ -2172,8 +2171,7 @@ void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC) const{
const MachineFunction &MF = *MBB.getParent();
- bool isAligned = (RI.getStackAlignment() >= 16) ||
- RI.needsStackRealignment(MF);
+ bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF);
unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM);
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
@@ -2202,8 +2200,7 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
if (CSI.empty())
return false;
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
+ DebugLoc DL = MBB.findDebugLoc(MI);
bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
bool isWin64 = TM.getSubtarget<X86Subtarget>().isTargetWin64();
@@ -2241,8 +2238,7 @@ bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
if (CSI.empty())
return false;
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
+ DebugLoc DL = MBB.findDebugLoc(MI);
MachineFunction &MF = *MBB.getParent();
unsigned FPReg = RI.getFrameRegister(MF);
@@ -2872,6 +2868,138 @@ unsigned X86InstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc,
return I->second.first;
}
+bool
+X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
+ int64_t &Offset1, int64_t &Offset2) const {
+ if (!Load1->isMachineOpcode() || !Load2->isMachineOpcode())
+ return false;
+ unsigned Opc1 = Load1->getMachineOpcode();
+ unsigned Opc2 = Load2->getMachineOpcode();
+ switch (Opc1) {
+ default: return false;
+ case X86::MOV8rm:
+ case X86::MOV16rm:
+ case X86::MOV32rm:
+ case X86::MOV64rm:
+ case X86::LD_Fp32m:
+ case X86::LD_Fp64m:
+ case X86::LD_Fp80m:
+ case X86::MOVSSrm:
+ case X86::MOVSDrm:
+ case X86::MMX_MOVD64rm:
+ case X86::MMX_MOVQ64rm:
+ case X86::FsMOVAPSrm:
+ case X86::FsMOVAPDrm:
+ case X86::MOVAPSrm:
+ case X86::MOVUPSrm:
+ case X86::MOVUPSrm_Int:
+ case X86::MOVAPDrm:
+ case X86::MOVDQArm:
+ case X86::MOVDQUrm:
+ case X86::MOVDQUrm_Int:
+ break;
+ }
+ switch (Opc2) {
+ default: return false;
+ case X86::MOV8rm:
+ case X86::MOV16rm:
+ case X86::MOV32rm:
+ case X86::MOV64rm:
+ case X86::LD_Fp32m:
+ case X86::LD_Fp64m:
+ case X86::LD_Fp80m:
+ case X86::MOVSSrm:
+ case X86::MOVSDrm:
+ case X86::MMX_MOVD64rm:
+ case X86::MMX_MOVQ64rm:
+ case X86::FsMOVAPSrm:
+ case X86::FsMOVAPDrm:
+ case X86::MOVAPSrm:
+ case X86::MOVUPSrm:
+ case X86::MOVUPSrm_Int:
+ case X86::MOVAPDrm:
+ case X86::MOVDQArm:
+ case X86::MOVDQUrm:
+ case X86::MOVDQUrm_Int:
+ break;
+ }
+
+ // Check if chain operands and base addresses match.
+ if (Load1->getOperand(0) != Load2->getOperand(0) ||
+ Load1->getOperand(5) != Load2->getOperand(5))
+ return false;
+ // Segment operands should match as well.
+ if (Load1->getOperand(4) != Load2->getOperand(4))
+ return false;
+ // Scale should be 1, Index should be Reg0.
+ if (Load1->getOperand(1) == Load2->getOperand(1) &&
+ Load1->getOperand(2) == Load2->getOperand(2)) {
+ if (cast<ConstantSDNode>(Load1->getOperand(1))->getZExtValue() != 1)
+ return false;
+ SDValue Op2 = Load1->getOperand(2);
+ if (!isa<RegisterSDNode>(Op2) ||
+ cast<RegisterSDNode>(Op2)->getReg() != 0)
+ return 0;
+
+ // Now let's examine the displacements.
+ if (isa<ConstantSDNode>(Load1->getOperand(3)) &&
+ isa<ConstantSDNode>(Load2->getOperand(3))) {
+ Offset1 = cast<ConstantSDNode>(Load1->getOperand(3))->getSExtValue();
+ Offset2 = cast<ConstantSDNode>(Load2->getOperand(3))->getSExtValue();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool X86InstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,
+ int64_t Offset1, int64_t Offset2,
+ unsigned NumLoads) const {
+ assert(Offset2 > Offset1);
+ if ((Offset2 - Offset1) / 8 > 64)
+ return false;
+
+ unsigned Opc1 = Load1->getMachineOpcode();
+ unsigned Opc2 = Load2->getMachineOpcode();
+ if (Opc1 != Opc2)
+ return false; // FIXME: overly conservative?
+
+ switch (Opc1) {
+ default: break;
+ case X86::LD_Fp32m:
+ case X86::LD_Fp64m:
+ case X86::LD_Fp80m:
+ case X86::MMX_MOVD64rm:
+ case X86::MMX_MOVQ64rm:
+ return false;
+ }
+
+ EVT VT = Load1->getValueType(0);
+ switch (VT.getSimpleVT().SimpleTy) {
+ default: {
+ // XMM registers. In 64-bit mode we can be a bit more aggressive since we
+ // have 16 of them to play with.
+ if (TM.getSubtargetImpl()->is64Bit()) {
+ if (NumLoads >= 3)
+ return false;
+ } else if (NumLoads)
+ return false;
+ break;
+ }
+ case MVT::i8:
+ case MVT::i16:
+ case MVT::i32:
+ case MVT::i64:
+ case MVT::f32:
+ case MVT::f64:
+ if (NumLoads)
+ return false;
+ }
+
+ return true;
+}
+
+
bool X86InstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
assert(Cond.size() == 1 && "Invalid X86 branch condition!");
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index 0ab85f4..4f35d0d 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -610,6 +610,26 @@ public:
bool UnfoldLoad, bool UnfoldStore,
unsigned *LoadRegIndex = 0) const;
+ /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler
+ /// to determine if two loads are loading from the same base address. It
+ /// should only return true if the base pointers are the same and the
+ /// only differences between the two addresses are the offset. It also returns
+ /// the offsets by reference.
+ virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
+ int64_t &Offset1, int64_t &Offset2) const;
+
+ /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to
+ /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should
+ /// be scheduled togther. On some targets if two loads are loading from
+ /// addresses in the same cache line, it's better if they are scheduled
+ /// together. This function takes two integers that represent the load offsets
+ /// from the common base address. It returns true if it decides it's desirable
+ /// to schedule the two loads together. "NumLoads" is the number of loads that
+ /// have already been scheduled after Load1.
+ virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,
+ int64_t Offset1, int64_t Offset2,
+ unsigned NumLoads) const;
+
virtual
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp
index 9d7e66d..1738d49 100644
--- a/lib/Target/X86/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/X86MCAsmInfo.cpp
@@ -14,6 +14,7 @@
#include "X86MCAsmInfo.h"
#include "X86TargetMachine.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
@@ -87,10 +88,11 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) {
// Exceptions handling
ExceptionsType = ExceptionHandling::Dwarf;
AbsoluteEHSectionOffsets = false;
+}
- // On Linux we must declare when we can use a non-executable stack.
- if (Triple.getOS() == Triple::Linux)
- NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
+MCSection *X86ELFMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const {
+ return MCSectionELF::Create(".note.GNU-stack", MCSectionELF::SHT_PROGBITS,
+ 0, SectionKind::getMetadata(), false, Ctx);
}
X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) {
@@ -109,7 +111,6 @@ X86WinMCAsmInfo::X86WinMCAsmInfo(const Triple &Triple) {
PrivateGlobalPrefix = "$";
AlignDirective = "\tALIGN\t";
ZeroDirective = "\tdb\t";
- ZeroDirectiveSuffix = " dup(0)";
AsciiDirective = "\tdb\t";
AscizDirective = 0;
Data8bitsDirective = "\tdb\t";
diff --git a/lib/Target/X86/X86MCAsmInfo.h b/lib/Target/X86/X86MCAsmInfo.h
index 18e2bdb..ca227b7 100644
--- a/lib/Target/X86/X86MCAsmInfo.h
+++ b/lib/Target/X86/X86MCAsmInfo.h
@@ -27,6 +27,7 @@ namespace llvm {
struct X86ELFMCAsmInfo : public MCAsmInfo {
explicit X86ELFMCAsmInfo(const Triple &Triple);
+ virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const;
};
struct X86MCAsmInfoCOFF : public MCAsmInfoCOFF {
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index 9bd96af..f959a2d 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -438,6 +438,12 @@ bool X86RegisterInfo::hasFP(const MachineFunction &MF) const {
(MMI && MMI->callsUnwindInit()));
}
+bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ return (RealignStack &&
+ !MFI->hasVarSizedObjects());
+}
+
bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
bool requiresRealignment =
@@ -591,15 +597,6 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int FrameIndex = MI.getOperand(i).getIndex();
unsigned BasePtr;
- // DEBUG_VALUE has a special representation, and is only robust enough to
- // represent SP(or BP) +- offset addressing modes. We rewrite the
- // FrameIndex to be a constant; implicitly positive constants are relative
- // to ESP and negative ones to EBP.
- if (MI.getOpcode()==TargetInstrInfo::DEBUG_VALUE) {
- MI.getOperand(i).ChangeToImmediate(getFrameIndexOffset(MF, FrameIndex));
- return 0;
- }
-
if (needsStackRealignment(MF))
BasePtr = (FrameIndex < 0 ? FramePtr : StackPtr);
else
@@ -685,8 +682,7 @@ void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
(Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) :
(Is64Bit ? X86::ADD64ri32 : X86::ADD32ri));
uint64_t Chunk = (1LL << 31) - 1;
- DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
- DebugLoc::getUnknownLoc());
+ DebugLoc DL = MBB.findDebugLoc(MBBI);
while (Offset) {
uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
@@ -1035,8 +1031,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
}
}
- if (MBBI != MBB.end())
- DL = MBBI->getDebugLoc();
+ DL = MBB.findDebugLoc(MBBI);
// Adjust stack pointer: ESP -= numbytes.
if (NumBytes >= 4096 && Subtarget->isTargetCygMing()) {
diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h
index f281a3c..dec3fba 100644
--- a/lib/Target/X86/X86RegisterInfo.h
+++ b/lib/Target/X86/X86RegisterInfo.h
@@ -128,6 +128,8 @@ public:
bool hasFP(const MachineFunction &MF) const;
+ bool canRealignStack(const MachineFunction &MF) const;
+
bool needsStackRealignment(const MachineFunction &MF) const;
bool hasReservedCallFrame(MachineFunction &MF) const;
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 962f0f7..731c3ab 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -157,9 +157,6 @@ bool X86TargetMachine::addInstSelector(PassManagerBase &PM,
bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
- // Calculate and set max stack object alignment early, so we can decide
- // whether we will need stack realignment (and thus FP).
- PM.add(createMaxStackAlignmentCalculatorPass());
return false; // -print-machineinstr shouldn't print after this.
}
@@ -249,3 +246,32 @@ void X86TargetMachine::setCodeModelForJIT() {
else
setCodeModel(CodeModel::Small);
}
+
+/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte,
+/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA
+/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte
+/// pointer by default. However, some systems may require a different size due
+/// to bugs or other conditions. We will default to a 4-byte encoding unless the
+/// system tells us otherwise.
+///
+/// The issue is when the CIE says their is an LSDA. That mandates that every
+/// FDE have an LSDA slot. But if the function does not need an LSDA. There
+/// needs to be some way to signify there is none. The LSDA is encoded as
+/// pc-rel. But you don't look for some magic value after adding the pc. You
+/// have to look for a zero before adding the pc. The problem is that the size
+/// of the zero to look for depends on the encoding. The unwinder bug in SL is
+/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8
+/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are
+/// non-zero so it goes ahead and then reads the value based on the encoding.
+/// But if you use sdata4 and there is no LSDA, then the test for zero gives a
+/// false negative and the unwinder thinks there is an LSDA.
+///
+/// FIXME: This call-back isn't good! We should be using the correct encoding
+/// regardless of the system. However, there are some systems which have bugs
+/// that prevent this from occuring.
+DwarfLSDAEncoding::Encoding X86TargetMachine::getLSDAEncoding() const {
+ if (Subtarget.isTargetDarwin() && Subtarget.getDarwinVers() != 10)
+ return DwarfLSDAEncoding::Default;
+
+ return DwarfLSDAEncoding::EightByte;
+}
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index 6183e91..d05bebd 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -62,6 +62,18 @@ public:
return Subtarget.isTargetELF() ? &ELFWriterInfo : 0;
}
+ /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are
+ /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that
+ /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded
+ /// as a 4-byte pointer by default. However, some systems may require a
+ /// different size due to bugs or other conditions. We will default to a
+ /// 4-byte encoding unless the system tells us otherwise.
+ ///
+ /// FIXME: This call-back isn't good! We should be using the correct encoding
+ /// regardless of the system. However, there are some systems which have bugs
+ /// that prevent this from occuring.
+ virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const;
+
// Set up the pass pipeline.
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp
index d39b3c4..41ad153 100644
--- a/lib/Target/X86/X86TargetObjectFile.cpp
+++ b/lib/Target/X86/X86TargetObjectFile.cpp
@@ -8,11 +8,11 @@
//===----------------------------------------------------------------------===//
#include "X86TargetObjectFile.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Mangler.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/CodeGen/MachineModuleInfoImpls.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/ADT/SmallString.h"
using namespace llvm;
const MCExpr *X8632_MachoTargetObjectFile::
@@ -27,6 +27,7 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfoMachO &MachOMMI =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
+ // FIXME: Use GetSymbolWithGlobalValueBase.
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, true);
Name += "$non_lazy_ptr";
diff --git a/lib/Target/XCore/AsmPrinter/Makefile b/lib/Target/XCore/AsmPrinter/Makefile
index 82dc1df..f0e883e 100644
--- a/lib/Target/XCore/AsmPrinter/Makefile
+++ b/lib/Target/XCore/AsmPrinter/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMXCoreAsmPrinter
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' XCore target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp
index 2a561c6..40d7160 100644
--- a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp
+++ b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp
@@ -37,7 +37,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cctype>
@@ -69,11 +68,10 @@ namespace {
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
- void emitGlobalDirective(const std::string &name);
- void emitExternDirective(const std::string &name);
+ void emitGlobalDirective(const MCSymbol *Sym);
- void emitArrayBound(const std::string &name, const GlobalVariable *GV);
- virtual void PrintGlobalVariable(const GlobalVariable *GV);
+ void emitArrayBound(const MCSymbol *Sym, const GlobalVariable *GV);
+ virtual void EmitGlobalVariable(const GlobalVariable *GV);
void emitFunctionStart(MachineFunction &MF);
void emitFunctionEnd(MachineFunction &MF);
@@ -95,55 +93,44 @@ namespace {
#include "XCoreGenAsmWriter.inc"
-void XCoreAsmPrinter::
-emitGlobalDirective(const std::string &name)
-{
- O << MAI->getGlobalDirective() << name;
- O << "\n";
-}
-
-void XCoreAsmPrinter::
-emitExternDirective(const std::string &name)
-{
- O << "\t.extern\t" << name;
- O << '\n';
+void XCoreAsmPrinter::emitGlobalDirective(const MCSymbol *Sym) {
+ O << MAI->getGlobalDirective() << *Sym << "\n";
}
-void XCoreAsmPrinter::
-emitArrayBound(const std::string &name, const GlobalVariable *GV)
-{
+void XCoreAsmPrinter::emitArrayBound(const MCSymbol *Sym,
+ const GlobalVariable *GV) {
assert(((GV->hasExternalLinkage() ||
GV->hasWeakLinkage()) ||
GV->hasLinkOnceLinkage()) && "Unexpected linkage");
if (const ArrayType *ATy = dyn_cast<ArrayType>(
- cast<PointerType>(GV->getType())->getElementType()))
- {
- O << MAI->getGlobalDirective() << name << ".globound" << "\n";
- O << MAI->getSetDirective() << name << ".globound" << ","
- << ATy->getNumElements() << "\n";
+ cast<PointerType>(GV->getType())->getElementType())) {
+ O << MAI->getGlobalDirective() << *Sym;
+ O << ".globound" << "\n";
+ O << MAI->getSetDirective() << *Sym;
+ O << ".globound" << "," << ATy->getNumElements() << "\n";
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
// TODO Use COMDAT groups for LinkOnceLinkage
- O << MAI->getWeakDefDirective() << name << ".globound" << "\n";
+ O << MAI->getWeakDefDirective() << *Sym << ".globound" << "\n";
}
}
}
-void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
+void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Check to see if this is a special global used by LLVM, if so, emit it.
if (!GV->hasInitializer() ||
EmitSpecialLLVMGlobal(GV))
return;
const TargetData *TD = TM.getTargetData();
-
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
+
- std::string name = Mang->getMangledName(GV);
+ MCSymbol *GVSym = GetGlobalValueSymbol(GV);
Constant *C = GV->getInitializer();
unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
// Mark the start of the global
- O << "\t.cc_top " << name << ".data," << name << "\n";
+ O << "\t.cc_top " << *GVSym << ".data," << *GVSym << "\n";
switch (GV->getLinkage()) {
case GlobalValue::AppendingLinkage:
@@ -153,12 +140,11 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::ExternalLinkage:
- emitArrayBound(name, GV);
- emitGlobalDirective(name);
+ emitArrayBound(GVSym, GV);
+ emitGlobalDirective(GVSym);
// TODO Use COMDAT groups for LinkOnceLinkage
- if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
- O << MAI->getWeakDefDirective() << name << "\n";
- }
+ if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
+ O << MAI->getWeakDefDirective() << *GVSym << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
@@ -181,25 +167,23 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
Size *= MaxThreads;
}
if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << "," << Size << "\n";
+ O << "\t.type " << *GVSym << ",@object\n";
+ O << "\t.size " << *GVSym << "," << Size << "\n";
}
- O << name << ":\n";
+ O << *GVSym << ":\n";
EmitGlobalConstant(C);
if (GV->isThreadLocal()) {
- for (unsigned i = 1; i < MaxThreads; ++i) {
+ for (unsigned i = 1; i < MaxThreads; ++i)
EmitGlobalConstant(C);
- }
- }
- if (Size < 4) {
- // The ABI requires that unsigned scalar types smaller than 32 bits
- // are are padded to 32 bits.
- EmitZeros(4 - Size);
}
+ // The ABI requires that unsigned scalar types smaller than 32 bits
+ // are padded to 32 bits.
+ if (Size < 4)
+ OutStreamer.EmitZeros(4 - Size, 0);
// Mark the end of the global
- O << "\t.cc_bottom " << name << ".data\n";
+ O << "\t.cc_bottom " << *GVSym << ".data\n";
}
/// Emit the directives on the start of functions
@@ -210,7 +194,7 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) {
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
// Mark the start of the function
- O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";
+ O << "\t.cc_top " << *CurrentFnSym << ".function," << *CurrentFnSym << "\n";
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
@@ -219,31 +203,29 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) {
case Function::LinkerPrivateLinkage:
break;
case Function::ExternalLinkage:
- emitGlobalDirective(CurrentFnName);
+ emitGlobalDirective(CurrentFnSym);
break;
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
// TODO Use COMDAT groups for LinkOnceLinkage
- O << MAI->getGlobalDirective() << CurrentFnName << "\n";
- O << MAI->getWeakDefDirective() << CurrentFnName << "\n";
+ O << MAI->getGlobalDirective() << *CurrentFnSym << "\n";
+ O << MAI->getWeakDefDirective() << *CurrentFnSym << "\n";
break;
}
// (1 << 1) byte aligned
EmitAlignment(MF.getAlignment(), F, 1);
- if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << CurrentFnName << ",@function\n";
- }
- O << CurrentFnName << ":\n";
+ if (MAI->hasDotTypeDotSizeDirective())
+ O << "\t.type " << *CurrentFnSym << ",@function\n";
+
+ O << *CurrentFnSym << ":\n";
}
/// Emit the directives on the end of functions
-void XCoreAsmPrinter::
-emitFunctionEnd(MachineFunction &MF)
-{
+void XCoreAsmPrinter::emitFunctionEnd(MachineFunction &MF) {
// Mark the end of the function
- O << "\t.cc_bottom " << CurrentFnName << ".function\n";
+ O << "\t.cc_bottom " << *CurrentFnSym << ".function\n";
}
/// runOnMachineFunction - This uses the printMachineInstruction()
@@ -318,10 +300,10 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
+ O << *GetMBBSymbol(MO.getMBB()->getNumber());
break;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
@@ -333,8 +315,9 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
+ break;
case MachineOperand::MO_BlockAddress:
- GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
+ O << *GetBlockAddressSymbol(MO.getBlockAddress());
break;
default:
llvm_unreachable("not implemented");
diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile
index bd3b52a..3bb127f 100644
--- a/lib/Target/XCore/Makefile
+++ b/lib/Target/XCore/Makefile
@@ -6,9 +6,11 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../..
LIBRARYNAME = LLVMXCoreCodeGen
TARGET = XCore
+CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \
diff --git a/lib/Target/XCore/TargetInfo/Makefile b/lib/Target/XCore/TargetInfo/Makefile
index 07473d2..83bba13 100644
--- a/lib/Target/XCore/TargetInfo/Makefile
+++ b/lib/Target/XCore/TargetInfo/Makefile
@@ -6,8 +6,10 @@
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
+
LEVEL = ../../../..
LIBRARYNAME = LLVMXCoreInfo
+CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
diff --git a/lib/Transforms/Hello/Makefile b/lib/Transforms/Hello/Makefile
index c5e75d4..46f8098 100644
--- a/lib/Transforms/Hello/Makefile
+++ b/lib/Transforms/Hello/Makefile
@@ -11,6 +11,7 @@ LEVEL = ../../..
LIBRARYNAME = LLVMHello
LOADABLE_MODULE = 1
USEDLIBS =
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 5725db1..0990278 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -171,7 +171,16 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
return true;
}
-
+
+unsigned Inliner::getInlineThreshold(Function* Caller) const {
+ if (Caller && !Caller->isDeclaration() &&
+ Caller->hasFnAttr(Attribute::OptimizeForSize) &&
+ InlineLimit.getNumOccurrences() == 0)
+ return 50;
+ else
+ return InlineThreshold;
+}
+
/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
@@ -190,14 +199,8 @@ bool Inliner::shouldInline(CallSite CS) {
}
int Cost = IC.getValue();
- int CurrentThreshold = InlineThreshold;
Function *Caller = CS.getCaller();
- if (Caller && !Caller->isDeclaration() &&
- Caller->hasFnAttr(Attribute::OptimizeForSize) &&
- InlineLimit.getNumOccurrences() == 0 &&
- InlineThreshold != 50)
- CurrentThreshold = 50;
-
+ int CurrentThreshold = getInlineThreshold(Caller);
float FudgeFactor = getInlineFudgeFactor(CS);
if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
DEBUG(dbgs() << " NOT Inlining: cost=" << Cost
@@ -233,13 +236,8 @@ bool Inliner::shouldInline(CallSite CS) {
outerCallsFound = true;
int Cost2 = IC2.getValue();
- int CurrentThreshold2 = InlineThreshold;
Function *Caller2 = CS2.getCaller();
- if (Caller2 && !Caller2->isDeclaration() &&
- Caller2->hasFnAttr(Attribute::OptimizeForSize) &&
- InlineThreshold != 50)
- CurrentThreshold2 = 50;
-
+ int CurrentThreshold2 = getInlineThreshold(Caller2);
float FudgeFactor2 = getInlineFudgeFactor(CS2);
if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2))
diff --git a/lib/Transforms/IPO/Makefile b/lib/Transforms/IPO/Makefile
index 5c42374..fd018c4 100644
--- a/lib/Transforms/IPO/Makefile
+++ b/lib/Transforms/IPO/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMipo
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp
index ae88d9e..0e0d83a 100644
--- a/lib/Transforms/IPO/StripSymbols.cpp
+++ b/lib/Transforms/IPO/StripSymbols.cpp
@@ -147,7 +147,7 @@ static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
- if (PreserveDbgInfo && strncmp(TI->first.c_str(), "llvm.dbg", 8) == 0)
+ if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
++TI;
else
ST.remove(TI++);
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index af300fc..fa7bb12 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1751,6 +1751,11 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return BinaryOperator::CreateOr(NotX, NotY);
return BinaryOperator::CreateAnd(NotX, NotY);
}
+
+ } else if (Op0I->getOpcode() == Instruction::AShr) {
+ // ~(~X >>s Y) --> (X >>s Y)
+ if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0)))
+ return BinaryOperator::CreateAShr(Op0NotVal, Op0I->getOperand(1));
}
}
}
diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp
index e018b35..f25dd35 100644
--- a/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -955,6 +955,19 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
ShAmt);
}
+ // If this input is a trunc from our destination, then turn sext(trunc(x))
+ // into shifts.
+ if (TruncInst *TI = dyn_cast<TruncInst>(Src))
+ if (TI->hasOneUse() && TI->getOperand(0)->getType() == DestTy) {
+ uint32_t SrcBitSize = SrcTy->getScalarSizeInBits();
+ uint32_t DestBitSize = DestTy->getScalarSizeInBits();
+
+ // We need to emit a shl + ashr to do the sign extend.
+ Value *ShAmt = ConstantInt::get(DestTy, DestBitSize-SrcBitSize);
+ Value *Res = Builder->CreateShl(TI->getOperand(0), ShAmt, "sext");
+ return BinaryOperator::CreateAShr(Res, ShAmt);
+ }
+
// If the input is a shl/ashr pair of a same constant, then this is a sign
// extension from a smaller value. If we could trust arbitrary bitwidth
// integers, we could turn this into a truncate to the smaller bit and then
diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 6c0ecc9..ae728dd 100644
--- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -366,7 +366,7 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
// alloca dead.
// If the RHS is an alloca with a two uses, the other one being a
// llvm.dbg.declare, zapify the store and the declare, making the
- // alloca dead. We must do this to prevent declare's from affecting
+ // alloca dead. We must do this to prevent declares from affecting
// codegen.
if (!SI.isVolatile()) {
if (Ptr->hasOneUse()) {
@@ -408,8 +408,6 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
--BBI;
// Don't count debug info directives, lest they affect codegen,
// and we skip pointer-to-pointer bitcasts, which are NOPs.
- // It is necessary for correctness to skip those that feed into a
- // llvm.dbg.declare, as these are not present when debugging is off.
if (isa<DbgInfoIntrinsic>(BBI) ||
(isa<BitCastInst>(BBI) && isa<PointerType>(BBI->getType()))) {
ScanInsts++;
@@ -475,9 +473,8 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
// If this store is the last instruction in the basic block (possibly
- // excepting debug info instructions and the pointer bitcasts that feed
- // into them), and if the block ends with an unconditional branch, try
- // to move it to the successor block.
+ // excepting debug info instructions), and if the block ends with an
+ // unconditional branch, try to move it to the successor block.
BBI = &SI;
do {
++BBI;
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 6afc0cd..2e26a75 100644
--- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -407,7 +407,7 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
return Common;
if (ConstantInt *C = dyn_cast<ConstantInt>(Op1)) {
- // X udiv C^2 -> X >> C
+ // X udiv 2^C -> X >> C
// Check to see if this is an unsigned division with an exact power of 2,
// if so, convert to a right shift.
if (C->getValue().isPowerOf2()) // 0 not included in isPowerOf2
diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp
index fe91da1..321c91d 100644
--- a/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -404,12 +404,26 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
// If the input is a SHL by the same constant (ashr (shl X, C), C), then we
- // have a sign-extend idiom. If the input value is known to already be sign
- // extended enough, delete the extension.
+ // have a sign-extend idiom.
Value *X;
- if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
- ComputeNumSignBits(X) > Op1C->getZExtValue())
- return ReplaceInstUsesWith(I, X);
+ if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1)))) {
+ // If the input value is known to already be sign extended enough, delete
+ // the extension.
+ if (ComputeNumSignBits(X) > Op1C->getZExtValue())
+ return ReplaceInstUsesWith(I, X);
+
+ // If the input is an extension from the shifted amount value, e.g.
+ // %x = zext i8 %A to i32
+ // %y = shl i32 %x, 24
+ // %z = ashr %y, 24
+ // then turn this into "z = sext i8 A to i32".
+ if (ZExtInst *ZI = dyn_cast<ZExtInst>(X)) {
+ uint32_t SrcBits = ZI->getOperand(0)->getType()->getScalarSizeInBits();
+ uint32_t DestBits = ZI->getType()->getScalarSizeInBits();
+ if (Op1C->getZExtValue() == DestBits-SrcBits)
+ return new SExtInst(ZI->getOperand(0), ZI->getType());
+ }
+ }
}
// See if we can turn a signed shr into an unsigned shr.
diff --git a/lib/Transforms/InstCombine/Makefile b/lib/Transforms/InstCombine/Makefile
index 0c488e78..f9de42a 100644
--- a/lib/Transforms/InstCombine/Makefile
+++ b/lib/Transforms/InstCombine/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMInstCombine
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/Instrumentation/Makefile b/lib/Transforms/Instrumentation/Makefile
index 6cbc7a9..1238896 100644
--- a/lib/Transforms/Instrumentation/Makefile
+++ b/lib/Transforms/Instrumentation/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMInstrumentation
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
index 94b0671..5650150 100644
--- a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
+++ b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
@@ -130,7 +130,7 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) {
// actual MST is returned but the edges _not_ in the MST.
ProfileInfo::EdgeWeights ECs =
- getAnalysisID<ProfileInfo>(ProfileEstimatorPassID, *F).getEdgeWeights(F);
+ getAnalysis<ProfileInfo>(*F).getEdgeWeights(F);
std::vector<ProfileInfo::EdgeWeight> EdgeVector(ECs.begin(), ECs.end());
MaximumSpanningTree<BasicBlock> MST (EdgeVector);
std::stable_sort(MST.begin(),MST.end());
diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp
index 9c1b440..c3139a5 100644
--- a/lib/Transforms/Scalar/CodeGenPrepare.cpp
+++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp
@@ -617,7 +617,23 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
TLI->getTargetData()->getIntPtrType(AccessTy->getContext());
Value *Result = 0;
- // Start with the scale value.
+
+ // Start with the base register. Do this first so that subsequent address
+ // matching finds it last, which will prevent it from trying to match it
+ // as the scaled value in case it happens to be a mul. That would be
+ // problematic if we've sunk a different mul for the scale, because then
+ // we'd end up sinking both muls.
+ if (AddrMode.BaseReg) {
+ Value *V = AddrMode.BaseReg;
+ if (isa<PointerType>(V->getType()))
+ V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt);
+ if (V->getType() != IntPtrTy)
+ V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true,
+ "sunkaddr", InsertPt);
+ Result = V;
+ }
+
+ // Add the scale value.
if (AddrMode.Scale) {
Value *V = AddrMode.ScaledReg;
if (V->getType() == IntPtrTy) {
@@ -634,17 +650,6 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
V = BinaryOperator::CreateMul(V, ConstantInt::get(IntPtrTy,
AddrMode.Scale),
"sunkaddr", InsertPt);
- Result = V;
- }
-
- // Add in the base register.
- if (AddrMode.BaseReg) {
- Value *V = AddrMode.BaseReg;
- if (isa<PointerType>(V->getType()))
- V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt);
- if (V->getType() != IntPtrTy)
- V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true,
- "sunkaddr", InsertPt);
if (Result)
Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt);
else
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index ac0d850..b29fe74 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -70,18 +70,44 @@ static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
/// two values.
namespace {
struct Expression {
- enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
- UDIV, SDIV, FDIV, UREM, SREM,
- FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
- ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
- ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
- FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE,
- FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE,
- FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT,
- SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI,
- FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT,
- PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT,
- INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE };
+ enum ExpressionOpcode {
+ ADD = Instruction::Add,
+ FADD = Instruction::FAdd,
+ SUB = Instruction::Sub,
+ FSUB = Instruction::FSub,
+ MUL = Instruction::Mul,
+ FMUL = Instruction::FMul,
+ UDIV = Instruction::UDiv,
+ SDIV = Instruction::SDiv,
+ FDIV = Instruction::FDiv,
+ UREM = Instruction::URem,
+ SREM = Instruction::SRem,
+ FREM = Instruction::FRem,
+ SHL = Instruction::Shl,
+ LSHR = Instruction::LShr,
+ ASHR = Instruction::AShr,
+ AND = Instruction::And,
+ OR = Instruction::Or,
+ XOR = Instruction::Xor,
+ TRUNC = Instruction::Trunc,
+ ZEXT = Instruction::ZExt,
+ SEXT = Instruction::SExt,
+ FPTOUI = Instruction::FPToUI,
+ FPTOSI = Instruction::FPToSI,
+ UITOFP = Instruction::UIToFP,
+ SITOFP = Instruction::SIToFP,
+ FPTRUNC = Instruction::FPTrunc,
+ FPEXT = Instruction::FPExt,
+ PTRTOINT = Instruction::PtrToInt,
+ INTTOPTR = Instruction::IntToPtr,
+ BITCAST = Instruction::BitCast,
+ ICMPEQ, ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
+ ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
+ FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE,
+ FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE,
+ FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT,
+ SHUFFLE, SELECT, GEP, CALL, CONSTANT,
+ INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE };
ExpressionOpcode opcode;
const Type* type;
@@ -127,9 +153,7 @@ namespace {
uint32_t nextValueNumber;
- Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
Expression::ExpressionOpcode getOpcode(CmpInst* C);
- Expression::ExpressionOpcode getOpcode(CastInst* C);
Expression create_expression(BinaryOperator* BO);
Expression create_expression(CmpInst* C);
Expression create_expression(ShuffleVectorInst* V);
@@ -200,30 +224,6 @@ struct isPodLike<Expression> { static const bool value = true; };
//===----------------------------------------------------------------------===//
// ValueTable Internal Functions
//===----------------------------------------------------------------------===//
-Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) {
- switch(BO->getOpcode()) {
- default: // THIS SHOULD NEVER HAPPEN
- llvm_unreachable("Binary operator with unknown opcode?");
- case Instruction::Add: return Expression::ADD;
- case Instruction::FAdd: return Expression::FADD;
- case Instruction::Sub: return Expression::SUB;
- case Instruction::FSub: return Expression::FSUB;
- case Instruction::Mul: return Expression::MUL;
- case Instruction::FMul: return Expression::FMUL;
- case Instruction::UDiv: return Expression::UDIV;
- case Instruction::SDiv: return Expression::SDIV;
- case Instruction::FDiv: return Expression::FDIV;
- case Instruction::URem: return Expression::UREM;
- case Instruction::SRem: return Expression::SREM;
- case Instruction::FRem: return Expression::FREM;
- case Instruction::Shl: return Expression::SHL;
- case Instruction::LShr: return Expression::LSHR;
- case Instruction::AShr: return Expression::ASHR;
- case Instruction::And: return Expression::AND;
- case Instruction::Or: return Expression::OR;
- case Instruction::Xor: return Expression::XOR;
- }
-}
Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) {
if (isa<ICmpInst>(C)) {
@@ -263,25 +263,6 @@ Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) {
}
}
-Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) {
- switch(C->getOpcode()) {
- default: // THIS SHOULD NEVER HAPPEN
- llvm_unreachable("Cast operator with unknown opcode?");
- case Instruction::Trunc: return Expression::TRUNC;
- case Instruction::ZExt: return Expression::ZEXT;
- case Instruction::SExt: return Expression::SEXT;
- case Instruction::FPToUI: return Expression::FPTOUI;
- case Instruction::FPToSI: return Expression::FPTOSI;
- case Instruction::UIToFP: return Expression::UITOFP;
- case Instruction::SIToFP: return Expression::SITOFP;
- case Instruction::FPTrunc: return Expression::FPTRUNC;
- case Instruction::FPExt: return Expression::FPEXT;
- case Instruction::PtrToInt: return Expression::PTRTOINT;
- case Instruction::IntToPtr: return Expression::INTTOPTR;
- case Instruction::BitCast: return Expression::BITCAST;
- }
-}
-
Expression ValueTable::create_expression(CallInst* C) {
Expression e;
@@ -302,7 +283,7 @@ Expression ValueTable::create_expression(BinaryOperator* BO) {
e.varargs.push_back(lookup_or_add(BO->getOperand(1)));
e.function = 0;
e.type = BO->getType();
- e.opcode = getOpcode(BO);
+ e.opcode = static_cast<Expression::ExpressionOpcode>(BO->getOpcode());
return e;
}
@@ -325,7 +306,7 @@ Expression ValueTable::create_expression(CastInst* C) {
e.varargs.push_back(lookup_or_add(C->getOperand(0)));
e.function = 0;
e.type = C->getType();
- e.opcode = getOpcode(C);
+ e.opcode = static_cast<Expression::ExpressionOpcode>(C->getOpcode());
return e;
}
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
index ce1307c..17f7d98 100644
--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -471,6 +471,13 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
// Compute the final addrec to expand into code.
const SCEV *AR = IU->getReplacementExpr(*UI);
+ // Evaluate the expression out of the loop, if possible.
+ if (!L->contains(UI->getUser())) {
+ const SCEV *ExitVal = SE->getSCEVAtScope(AR, L->getParentLoop());
+ if (ExitVal->isLoopInvariant(L))
+ AR = ExitVal;
+ }
+
// FIXME: It is an extremely bad idea to indvar substitute anything more
// complex than affine induction variables. Doing so will put expensive
// polynomial evaluations inside of the loop, and the str reduction pass
@@ -522,11 +529,10 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
Rewriter.clear();
// Now that we're done iterating through lists, clean up any instructions
// which are now dead.
- while (!DeadInsts.empty()) {
- Instruction *Inst = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val());
- if (Inst)
+ while (!DeadInsts.empty())
+ if (Instruction *Inst =
+ dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val()))
RecursivelyDeleteTriviallyDeadInstructions(Inst);
- }
}
/// If there's a single exit block, sink any loop-invariant values that
diff --git a/lib/Transforms/Scalar/Makefile b/lib/Transforms/Scalar/Makefile
index cc42fd0..e18f30f 100644
--- a/lib/Transforms/Scalar/Makefile
+++ b/lib/Transforms/Scalar/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMScalarOpts
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
index 9e1e79a..f473480 100644
--- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp
+++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
@@ -85,10 +85,6 @@ namespace {
/// isUnsafe - This is set to true if the alloca cannot be SROA'd.
bool isUnsafe : 1;
- /// needsCleanup - This is set to true if there is some use of the alloca
- /// that requires cleanup.
- bool needsCleanup : 1;
-
/// isMemCpySrc - This is true if this aggregate is memcpy'd from.
bool isMemCpySrc : 1;
@@ -96,15 +92,14 @@ namespace {
bool isMemCpyDst : 1;
AllocaInfo()
- : isUnsafe(false), needsCleanup(false),
- isMemCpySrc(false), isMemCpyDst(false) {}
+ : isUnsafe(false), isMemCpySrc(false), isMemCpyDst(false) {}
};
unsigned SRThreshold;
void MarkUnsafe(AllocaInfo &I) { I.isUnsafe = true; }
- int isSafeAllocaToScalarRepl(AllocaInst *AI);
+ bool isSafeAllocaToScalarRepl(AllocaInst *AI);
void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
AllocaInfo &Info);
@@ -119,7 +114,6 @@ namespace {
void DoScalarReplacement(AllocaInst *AI,
std::vector<AllocaInst*> &WorkList);
void DeleteDeadInstructions();
- void CleanupAllocaUsers(Value *V);
AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base);
void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
@@ -281,14 +275,7 @@ bool SROA::performScalarRepl(Function &F) {
getNumSAElements(AI->getAllocatedType()) <= SRThreshold/4) {
// Check that all of the users of the allocation are capable of being
// transformed.
- switch (isSafeAllocaToScalarRepl(AI)) {
- default: llvm_unreachable("Unexpected value!");
- case 0: // Not safe to scalar replace.
- break;
- case 1: // Safe, but requires cleanup/canonicalizations first
- CleanupAllocaUsers(AI);
- // FALL THROUGH.
- case 3: // Safe to scalar replace.
+ if (isSafeAllocaToScalarRepl(AI)) {
DoScalarReplacement(AI, WorkList);
Changed = true;
continue;
@@ -437,14 +424,6 @@ void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
SIType, true, Info);
} else
MarkUnsafe(Info);
- } else if (isa<DbgInfoIntrinsic>(UI)) {
- // If one user is DbgInfoIntrinsic then check if all users are
- // DbgInfoIntrinsics.
- if (OnlyUsedByDbgInfoIntrinsics(I)) {
- Info.needsCleanup = true;
- return;
- }
- MarkUnsafe(Info);
} else {
DEBUG(errs() << " Transformation preventing inst: " << *User << '\n');
MarkUnsafe(Info);
@@ -752,9 +731,16 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
}
break;
}
- // If OtherPtr has already been rewritten, this intrinsic will be dead.
- if (OtherPtr == NewElts[0])
+ // Copying the alloca to itself is a no-op: just delete it.
+ if (OtherPtr == AI || OtherPtr == NewElts[0]) {
+ // This code will run twice for a no-op memcpy -- once for each operand.
+ // Put only one reference to MI on the DeadInsts list.
+ for (SmallVector<Value*, 32>::const_iterator I = DeadInsts.begin(),
+ E = DeadInsts.end(); I != E; ++I)
+ if (*I == MI) return;
+ DeadInsts.push_back(MI);
return;
+ }
if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr))
if (BCE->getOpcode() == Instruction::BitCast)
@@ -779,10 +765,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
Value *OtherElt = 0;
unsigned OtherEltAlign = MemAlignment;
- if (OtherPtr == AI) {
- OtherElt = NewElts[i];
- OtherEltAlign = 0;
- } else if (OtherPtr) {
+ if (OtherPtr) {
Value *Idx[2] = { Zero,
ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) };
OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2,
@@ -1146,7 +1129,7 @@ static bool HasPadding(const Type *Ty, const TargetData &TD) {
/// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of
/// an aggregate can be broken down into elements. Return 0 if not, 3 if safe,
/// or 1 if safe after canonicalization has been performed.
-int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) {
+bool SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) {
// Loop over the use list of the alloca. We can only transform it if all of
// the users are safe to transform.
AllocaInfo Info;
@@ -1154,7 +1137,7 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) {
isSafeForScalarRepl(AI, AI, 0, Info);
if (Info.isUnsafe) {
DEBUG(dbgs() << "Cannot transform: " << *AI << '\n');
- return 0;
+ return false;
}
// Okay, we know all the users are promotable. If the aggregate is a memcpy
@@ -1164,29 +1147,9 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) {
// struct.
if (Info.isMemCpySrc && Info.isMemCpyDst &&
HasPadding(AI->getAllocatedType(), *TD))
- return 0;
-
- // If we require cleanup, return 1, otherwise return 3.
- return Info.needsCleanup ? 1 : 3;
-}
+ return false;
-/// CleanupAllocaUsers - If SROA reported that it can promote the specified
-/// allocation, but only if cleaned up, perform the cleanups required.
-void SROA::CleanupAllocaUsers(Value *V) {
- for (Value::use_iterator UI = V->use_begin(), E = V->use_end();
- UI != E; ) {
- User *U = *UI++;
- Instruction *I = cast<Instruction>(U);
- SmallVector<DbgInfoIntrinsic *, 2> DbgInUses;
- if (!isa<StoreInst>(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) {
- // Safe to remove debug info uses.
- while (!DbgInUses.empty()) {
- DbgInfoIntrinsic *DI = DbgInUses.pop_back_val();
- DI->eraseFromParent();
- }
- I->eraseFromParent();
- }
- }
+ return true;
}
/// MergeInType - Add the 'In' type to the accumulated type (Accum) so far at
@@ -1321,10 +1284,6 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy,
}
}
- // Ignore dbg intrinsic.
- if (isa<DbgInfoIntrinsic>(User))
- continue;
-
// Otherwise, we cannot handle this!
return false;
}
@@ -1449,18 +1408,11 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
} else {
// Noop transfer. Src == Dst
}
-
MTI->eraseFromParent();
continue;
}
- // If user is a dbg info intrinsic then it is safe to remove it.
- if (isa<DbgInfoIntrinsic>(User)) {
- User->eraseFromParent();
- continue;
- }
-
llvm_unreachable("Unsupported operation!");
}
}
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index 9183f3a..a49da9c 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -81,6 +81,10 @@ public:
/// and the return value has 'i8*' type.
Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B);
+ /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+ /// specified pointer arguments.
+ Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B);
+
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This
/// always expects that the size has type 'intptr_t' and Dst/Src are pointers.
Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,
@@ -176,6 +180,22 @@ Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) {
return CI;
}
+/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+/// specified pointer arguments.
+Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) {
+ Module *M = Caller->getParent();
+ AttributeWithIndex AWI[2];
+ AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
+ AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
+ const Type *I8Ptr = Type::getInt8PtrTy(*Context);
+ Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2),
+ I8Ptr, I8Ptr, I8Ptr, NULL);
+ CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
+ "strcpy");
+ if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts()))
+ CI->setCallingConv(F->getCallingConv());
+ return CI;
+}
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always
/// expects that the size has type 'intptr_t' and Dst/Src are pointers.
@@ -1181,6 +1201,31 @@ struct MemMoveChkOpt : public LibCallOptimization {
}
};
+struct StrCpyChkOpt : 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() != 3 || FT->getReturnType() != FT->getParamType(0) ||
+ !isa<PointerType>(FT->getParamType(0)) ||
+ !isa<PointerType>(FT->getParamType(1)) ||
+ !isa<IntegerType>(FT->getParamType(2)))
+ return 0;
+
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeCI)
+ return 0;
+
+ // We don't have any length information, just lower to a plain strcpy.
+ if (SizeCI->isAllOnesValue())
+ return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B);
+
+ return 0;
+ }
+};
+
+
//===----------------------------------------------------------------------===//
// Math Library Optimizations
//===----------------------------------------------------------------------===//
@@ -1725,6 +1770,7 @@ namespace {
// Object Size Checking
MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk;
+ StrCpyChkOpt StrCpyChk;
bool Modified; // This is only used by doInitialization.
public:
@@ -1836,6 +1882,7 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["__memcpy_chk"] = &MemCpyChk;
Optimizations["__memset_chk"] = &MemSetChk;
Optimizations["__memmove_chk"] = &MemMoveChk;
+ Optimizations["__strcpy_chk"] = &StrCpyChk;
}
diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp
index e902688..7bc4fcd 100644
--- a/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -615,11 +615,6 @@ Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
Instruction *Inst = --ScanFrom;
if (isa<DbgInfoIntrinsic>(Inst))
continue;
- // We skip pointer-to-pointer bitcasts, which are NOPs.
- // It is necessary for correctness to skip those that feed into a
- // llvm.dbg.declare, as these are not present when debugging is off.
- if (isa<BitCastInst>(Inst) && isa<PointerType>(Inst->getType()))
- continue;
// Restore ScanFrom to expected value in case next test succeeds
ScanFrom++;
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 90e929e..92bdf2d 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -609,30 +609,6 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) {
return true;
}
-
-
-/// OnlyUsedByDbgIntrinsics - Return true if the instruction I is only used
-/// by DbgIntrinsics. If DbgInUses is specified then the vector is filled
-/// with the DbgInfoIntrinsic that use the instruction I.
-bool llvm::OnlyUsedByDbgInfoIntrinsics(Instruction *I,
- SmallVectorImpl<DbgInfoIntrinsic *> *DbgInUses) {
- if (DbgInUses)
- DbgInUses->clear();
-
- for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE;
- ++UI) {
- if (DbgInfoIntrinsic *DI = dyn_cast<DbgInfoIntrinsic>(*UI)) {
- if (DbgInUses)
- DbgInUses->push_back(DI);
- } else {
- if (DbgInUses)
- DbgInUses->clear();
- return false;
- }
- }
- return true;
-}
-
/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI
/// nodes in this block. This doesn't try to be clever about PHI nodes
/// which differ only in the order of the incoming values, but instcombine
diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp
index 7fcc5f7..e81b779 100644
--- a/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/lib/Transforms/Utils/LoopSimplify.cpp
@@ -232,7 +232,7 @@ ReprocessLoop:
PN->eraseFromParent();
}
- // If this loop has muliple exits and the exits all go to the same
+ // If this loop has multiple exits and the exits all go to the same
// block, attempt to merge the exits. This helps several passes, such
// as LoopRotation, which do not support loops with multiple exits.
// SimplifyCFG also does this (and this code uses the same utility
diff --git a/lib/Transforms/Utils/Makefile b/lib/Transforms/Utils/Makefile
index d1e9336..b9761df 100644
--- a/lib/Transforms/Utils/Makefile
+++ b/lib/Transforms/Utils/Makefile
@@ -10,6 +10,7 @@
LEVEL = ../../..
LIBRARYNAME = LLVMTransformUtils
BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index baaa130..d9261ac 100644
--- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -23,6 +23,7 @@
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/ADT/DenseMap.h"
@@ -76,16 +77,6 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
return false; // Don't allow a store OF the AI, only INTO the AI.
if (SI->isVolatile())
return false;
- } else if (const BitCastInst *BC = dyn_cast<BitCastInst>(*UI)) {
- // A bitcast that does not feed into debug info inhibits promotion.
- if (!BC->hasOneUse() || !isa<DbgInfoIntrinsic>(*BC->use_begin()))
- return false;
- // If the only use is by debug info, this alloca will not exist in
- // non-debug code, so don't try to promote; this ensures the same
- // codegen with debug info. Otherwise, debug info should not
- // inhibit promotion (but we must examine other uses).
- if (AI->hasOneUse())
- return false;
} else {
return false;
}
@@ -173,6 +164,7 @@ namespace {
std::vector<AllocaInst*> Allocas;
DominatorTree &DT;
DominanceFrontier &DF;
+ DIFactory *DIF;
/// AST - An AliasSetTracker object to update. If null, don't update it.
///
@@ -209,7 +201,7 @@ namespace {
public:
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
DominanceFrontier &df, AliasSetTracker *ast)
- : Allocas(A), DT(dt), DF(df), AST(ast) {}
+ : Allocas(A), DT(dt), DF(df), DIF(0), AST(ast) {}
void run();
@@ -251,8 +243,9 @@ namespace {
LargeBlockInfo &LBI);
void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI);
-
-
+ void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst* SI,
+ uint64_t Offset);
+
void RenamePass(BasicBlock *BB, BasicBlock *Pred,
RenamePassData::ValVector &IncVals,
std::vector<RenamePassData> &Worklist);
@@ -290,15 +283,7 @@ namespace {
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
UI != E;) {
Instruction *User = cast<Instruction>(*UI++);
- if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) {
- // Remove any uses of this alloca in DbgInfoInstrinsics.
- assert(BC->hasOneUse() && "Unexpected alloca uses!");
- DbgInfoIntrinsic *DI = cast<DbgInfoIntrinsic>(*BC->use_begin());
- DI->eraseFromParent();
- BC->eraseFromParent();
- continue;
- }
-
+
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Remember the basic blocks which define new values for the alloca
DefiningBlocks.push_back(SI->getParent());
@@ -324,6 +309,19 @@ namespace {
} // end of anonymous namespace
+/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca if any.
+static DbgDeclareInst *findDbgDeclare(AllocaInst *AI) {
+ Function *F = AI->getParent()->getParent();
+ for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
+ for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end();
+ BI != BE; ++BI)
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
+ if (DDI->getAddress() == AI)
+ return DDI;
+
+ return 0;
+}
+
void PromoteMem2Reg::run() {
Function &F = *DF.getRoot()->getParent();
@@ -362,6 +360,8 @@ void PromoteMem2Reg::run() {
// Finally, after the scan, check to see if the store is all that is left.
if (Info.UsingBlocks.empty()) {
+ // Record debuginfo for the store before removing it.
+ ConvertDebugDeclareToDebugValue(findDbgDeclare(AI), Info.OnlyStore, 0);
// Remove the (now dead) store and alloca.
Info.OnlyStore->eraseFromParent();
LBI.deleteValue(Info.OnlyStore);
@@ -388,8 +388,11 @@ void PromoteMem2Reg::run() {
if (Info.UsingBlocks.empty()) {
// Remove the (now dead) stores and alloca.
+ DbgDeclareInst *DDI = findDbgDeclare(AI);
while (!AI->use_empty()) {
StoreInst *SI = cast<StoreInst>(AI->use_back());
+ // Record debuginfo for the store before removing it.
+ ConvertDebugDeclareToDebugValue(DDI, SI, 0);
SI->eraseFromParent();
LBI.deleteValue(SI);
}
@@ -851,6 +854,18 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
}
}
+// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value
+// that has an associated llvm.dbg.decl intrinsic.
+void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
+ StoreInst* SI,
+ uint64_t Offset) {
+ if (!DDI) return;
+
+ if (!DIF)
+ DIF = new DIFactory(*SI->getParent()->getParent()->getParent());
+ DIF->InsertDbgValueIntrinsic(SI->getOperand(0), Offset,
+ DIVariable(DDI->getVariable()), SI);
+}
// QueuePhiNode - queues a phi-node to be added to a basic-block for a specific
// Alloca returns true if there wasn't already a phi-node for that variable
@@ -964,6 +979,8 @@ NextIteration:
// what value were we writing?
IncomingVals[ai->second] = SI->getOperand(0);
+ // Record debuginfo for the store before removing it.
+ ConvertDebugDeclareToDebugValue(findDbgDeclare(Dest), SI, 0);
BB->getInstList().erase(SI);
}
}
diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp
index 39331d7..a6e6701 100644
--- a/lib/Transforms/Utils/ValueMapper.cpp
+++ b/lib/Transforms/Utils/ValueMapper.cpp
@@ -13,12 +13,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ValueMapper.h"
-#include "llvm/DerivedTypes.h" // For getNullValue(Type::Int32Ty)
+#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Metadata.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
Value *llvm::MapValue(const Value *V, ValueMapTy &VM) {
@@ -28,11 +27,19 @@ Value *llvm::MapValue(const Value *V, ValueMapTy &VM) {
// NOTE: VMSlot can be invalidated by any reference to VM, which can grow the
// DenseMap. This includes any recursive calls to MapValue.
- // Global values and metadata do not need to be seeded into the ValueMap if
- // they are using the identity mapping.
- if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MetadataBase>(V))
+ // Global values and non-function-local metadata do not need to be seeded into
+ // the ValueMap if they are using the identity mapping.
+ if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MDString>(V) ||
+ (isa<MDNode>(V) && !cast<MDNode>(V)->isFunctionLocal()))
return VMSlot = const_cast<Value*>(V);
+ if (const MDNode *MD = dyn_cast<MDNode>(V)) {
+ SmallVector<Value*, 4> Elts;
+ for (unsigned i = 0; i != MD->getNumOperands(); i++)
+ Elts.push_back(MD->getOperand(i) ? MapValue(MD->getOperand(i), VM) : 0);
+ return VM[V] = MDNode::get(V->getContext(), Elts.data(), Elts.size());
+ }
+
Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V));
if (C == 0) return 0;
@@ -111,14 +118,10 @@ Value *llvm::MapValue(const Value *V, ValueMapTy &VM) {
return VM[V] = C;
}
- if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
- Function *F = cast<Function>(MapValue(BA->getFunction(), VM));
- BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM));
- return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
- }
-
- llvm_unreachable("Unknown type of constant!");
- return 0;
+ BlockAddress *BA = cast<BlockAddress>(C);
+ Function *F = cast<Function>(MapValue(BA->getFunction(), VM));
+ BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM));
+ return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
}
/// RemapInstruction - Convert the instruction operands from referencing the
@@ -131,3 +134,4 @@ void llvm::RemapInstruction(Instruction *I, ValueMapTy &ValueMap) {
*op = V;
}
}
+
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index eff2c77..c9f3849 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -2062,9 +2062,9 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
else
W.printAlias(cast<GlobalAlias>(GV));
} else if (const MDNode *N = dyn_cast<MDNode>(this)) {
- Function *F = N->getFunction();
+ const Function *F = N->getFunction();
SlotTracker SlotTable(F);
- AssemblyWriter W(OS, SlotTable, getModuleFromVal(F), AAW);
+ AssemblyWriter W(OS, SlotTable, F ? getModuleFromVal(F) : 0, AAW);
W.printMDNodeBody(N);
} else if (const NamedMDNode *N = dyn_cast<NamedMDNode>(this)) {
SlotTracker SlotTable(N->getParent());
diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp
index a371c6f..65155f1 100644
--- a/lib/VMCore/Attributes.cpp
+++ b/lib/VMCore/Attributes.cpp
@@ -56,8 +56,6 @@ std::string Attribute::getAsString(Attributes Attrs) {
Result += "optsize ";
if (Attrs & Attribute::NoInline)
Result += "noinline ";
- if (Attrs & Attribute::InlineHint)
- Result += "inlinehint ";
if (Attrs & Attribute::AlwaysInline)
Result += "alwaysinline ";
if (Attrs & Attribute::StackProtect)
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp
index 2161841..5e4c9fb 100644
--- a/lib/VMCore/AutoUpgrade.cpp
+++ b/lib/VMCore/AutoUpgrade.cpp
@@ -521,7 +521,7 @@ void llvm::CheckDebugInfoIntrinsics(Module *M) {
if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
if (!Declare->use_empty()) {
DbgDeclareInst *DDI = cast<DbgDeclareInst>(Declare->use_back());
- if (!isa<MDNode>(DDI->getOperand(2))) {
+ if (!isa<MDNode>(DDI->getOperand(1)) ||!isa<MDNode>(DDI->getOperand(2))) {
while (!Declare->use_empty()) {
CallInst *CI = cast<CallInst>(Declare->use_back());
CI->eraseFromParent();
diff --git a/lib/VMCore/CMakeLists.txt b/lib/VMCore/CMakeLists.txt
index 61d01ee..5ecedf1 100644
--- a/lib/VMCore/CMakeLists.txt
+++ b/lib/VMCore/CMakeLists.txt
@@ -16,7 +16,6 @@ add_llvm_library(LLVMCore
IRBuilder.cpp
LLVMContext.cpp
LeakDetector.cpp
- Mangler.cpp
Metadata.cpp
Module.cpp
ModuleProvider.cpp
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 3a24389..ddd5587 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -1673,14 +1673,15 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context,
SmallVector<Constant*, 16> C1Elts, C2Elts;
C1->getVectorElements(Context, C1Elts);
C2->getVectorElements(Context, C2Elts);
+ if (C1Elts.empty() || C2Elts.empty())
+ return 0;
// If we can constant fold the comparison of each element, constant fold
// the whole vector comparison.
SmallVector<Constant*, 4> ResElts;
for (unsigned i = 0, e = C1Elts.size(); i != e; ++i) {
// Compare the elements, producing an i1 result or constant expr.
- ResElts.push_back(
- ConstantExpr::getCompare(pred, C1Elts[i], C2Elts[i]));
+ ResElts.push_back(ConstantExpr::getCompare(pred, C1Elts[i], C2Elts[i]));
}
return ConstantVector::get(&ResElts[0], ResElts.size());
}
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index cc8961f..916aac6 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -1630,7 +1630,7 @@ Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C,
}
Constant *
-ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
assert(LHS->getType() == RHS->getType());
assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE &&
pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate");
@@ -1646,13 +1646,16 @@ ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) {
// Get the key type with both the opcode and predicate
const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
+ const Type *ResultTy = Type::getInt1Ty(LHS->getContext());
+ if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
+ ResultTy = VectorType::get(ResultTy, VT->getNumElements());
+
LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl;
- return
- pImpl->ExprConstants.getOrCreate(Type::getInt1Ty(LHS->getContext()), Key);
+ return pImpl->ExprConstants.getOrCreate(ResultTy, Key);
}
Constant *
-ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) {
assert(LHS->getType() == RHS->getType());
assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate");
@@ -1666,10 +1669,13 @@ ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) {
ArgVec.push_back(RHS);
// Get the key type with both the opcode and predicate
const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
-
+
+ const Type *ResultTy = Type::getInt1Ty(LHS->getContext());
+ if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
+ ResultTy = VectorType::get(ResultTy, VT->getNumElements());
+
LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl;
- return
- pImpl->ExprConstants.getOrCreate(Type::getInt1Ty(LHS->getContext()), Key);
+ return pImpl->ExprConstants.getOrCreate(ResultTy, Key);
}
Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 2619047..e2b920e 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -2079,25 +2079,26 @@ unsigned CastInst::isEliminableCastPair(
return secondOp;
case 3:
// no-op cast in second op implies firstOp as long as the DestTy
- // is integer
- if (DstTy->isInteger())
+ // is integer and we are not converting between a vector and a
+ // non vector type.
+ if (!isa<VectorType>(SrcTy) && DstTy->isInteger())
return firstOp;
return 0;
case 4:
// no-op cast in second op implies firstOp as long as the DestTy
- // is floating point
+ // is floating point.
if (DstTy->isFloatingPoint())
return firstOp;
return 0;
case 5:
// no-op cast in first op implies secondOp as long as the SrcTy
- // is an integer
+ // is an integer.
if (SrcTy->isInteger())
return secondOp;
return 0;
case 6:
// no-op cast in first op implies secondOp as long as the SrcTy
- // is a floating point
+ // is a floating point.
if (SrcTy->isFloatingPoint())
return secondOp;
return 0;
@@ -2714,6 +2715,8 @@ BitCastInst::BitCastInst(
// CmpInst Classes
//===----------------------------------------------------------------------===//
+void CmpInst::Anchor() const {}
+
CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
Value *LHS, Value *RHS, const Twine &Name,
Instruction *InsertBefore)
diff --git a/lib/VMCore/IntrinsicInst.cpp b/lib/VMCore/IntrinsicInst.cpp
index cb9252e..d8f015a 100644
--- a/lib/VMCore/IntrinsicInst.cpp
+++ b/lib/VMCore/IntrinsicInst.cpp
@@ -51,6 +51,17 @@ Value *DbgInfoIntrinsic::StripCast(Value *C) {
}
//===----------------------------------------------------------------------===//
+/// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
+///
+
+Value *DbgDeclareInst::getAddress() const {
+ if (MDNode* MD = cast_or_null<MDNode>(getOperand(1)))
+ return MD->getOperand(0);
+ else
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
/// DbgValueInst - This represents the llvm.dbg.value instruction.
///
diff --git a/lib/VMCore/Makefile b/lib/VMCore/Makefile
index e9d3dc8..ecadaee 100644
--- a/lib/VMCore/Makefile
+++ b/lib/VMCore/Makefile
@@ -9,6 +9,7 @@
LEVEL = ../..
LIBRARYNAME = LLVMCore
BUILD_ARCHIVE = 1
+#CXXFLAGS = -fno-rtti
BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/Intrinsics.gen
diff --git a/lib/VMCore/Mangler.cpp b/lib/VMCore/Mangler.cpp
deleted file mode 100644
index 7d9f330..0000000
--- a/lib/VMCore/Mangler.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Unified name mangler for CWriter and assembly backends.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mangler.h"
-#include "llvm/Function.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-static char HexDigit(int V) {
- return V < 10 ? V+'0' : V+'A'-10;
-}
-
-static void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) {
- OutName.push_back('_');
- OutName.push_back(HexDigit(C >> 4));
- OutName.push_back(HexDigit(C & 15));
- OutName.push_back('_');
-}
-
-/// makeNameProper - We don't want identifier names non-C-identifier characters
-/// in them, so mangle them as appropriate.
-///
-/// FIXME: This is deprecated, new code should use getNameWithPrefix and use
-/// MCSymbol printing to handle quotes or not etc.
-///
-void Mangler::makeNameProper(SmallVectorImpl<char> &OutName,
- const Twine &TheName,
- ManglerPrefixTy PrefixTy) {
- SmallString<256> TmpData;
- StringRef X = TheName.toStringRef(TmpData);
- assert(!X.empty() && "Cannot mangle empty strings");
-
- if (!UseQuotes) {
- // If X does not start with (char)1, add the prefix.
- StringRef::iterator I = X.begin();
- if (*I == 1) {
- ++I; // Skip over the no-prefix marker.
- } else {
- if (PrefixTy == Mangler::Private)
- OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix));
- else if (PrefixTy == Mangler::LinkerPrivate)
- OutName.append(LinkerPrivatePrefix,
- LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));
- OutName.append(Prefix, Prefix+strlen(Prefix));
- }
-
- // Mangle the first letter specially, don't allow numbers unless the target
- // explicitly allows them.
- if (!SymbolsCanStartWithDigit && *I >= '0' && *I <= '9')
- MangleLetter(OutName, *I++);
-
- for (StringRef::iterator E = X.end(); I != E; ++I) {
- if (!isCharAcceptable(*I))
- MangleLetter(OutName, *I);
- else
- OutName.push_back(*I);
- }
- return;
- }
-
- bool NeedPrefix = true;
- bool NeedQuotes = false;
- StringRef::iterator I = X.begin();
- if (*I == 1) {
- NeedPrefix = false;
- ++I; // Skip over the marker.
- }
-
- // If the first character is a number, we need quotes.
- if (*I >= '0' && *I <= '9')
- NeedQuotes = true;
-
- // Do an initial scan of the string, checking to see if we need quotes or
- // to escape a '"' or not.
- if (!NeedQuotes)
- for (StringRef::iterator E = X.end(); I != E; ++I)
- if (!isCharAcceptable(*I)) {
- NeedQuotes = true;
- break;
- }
-
- // In the common case, we don't need quotes. Handle this quickly.
- if (!NeedQuotes) {
- if (!NeedPrefix) {
- OutName.append(X.begin()+1, X.end()); // Strip off the \001.
- return;
- }
-
- if (PrefixTy == Mangler::Private)
- OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix));
- else if (PrefixTy == Mangler::LinkerPrivate)
- OutName.append(LinkerPrivatePrefix,
- LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));
-
- if (Prefix[0] == 0)
- ; // Common noop, no prefix.
- else if (Prefix[1] == 0)
- OutName.push_back(Prefix[0]); // Common, one character prefix.
- else
- OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary prefix.
- OutName.append(X.begin(), X.end());
- return;
- }
-
- // Add leading quote.
- OutName.push_back('"');
-
- // Add prefixes unless disabled.
- if (NeedPrefix) {
- if (PrefixTy == Mangler::Private)
- OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix));
- else if (PrefixTy == Mangler::LinkerPrivate)
- OutName.append(LinkerPrivatePrefix,
- LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));
- OutName.append(Prefix, Prefix+strlen(Prefix));
- }
-
- // Add the piece that we already scanned through.
- OutName.append(X.begin()+!NeedPrefix, I);
-
- // Otherwise, construct the string the expensive way.
- for (StringRef::iterator E = X.end(); I != E; ++I) {
- if (*I == '"') {
- const char *Quote = "_QQ_";
- OutName.append(Quote, Quote+4);
- } else if (*I == '\n') {
- const char *Newline = "_NL_";
- OutName.append(Newline, Newline+4);
- } else
- OutName.push_back(*I);
- }
-
- // Add trailing quote.
- OutName.push_back('"');
-}
-
-/// getMangledName - Returns the mangled name of V, an LLVM Value,
-/// in the current module. If 'Suffix' is specified, the name ends with the
-/// specified suffix. If 'ForcePrivate' is specified, the label is specified
-/// to have a private label prefix.
-///
-/// FIXME: This is deprecated, new code should use getNameWithPrefix and use
-/// MCSymbol printing to handle quotes or not etc.
-///
-std::string Mangler::getMangledName(const GlobalValue *GV, const char *Suffix,
- bool ForcePrivate) {
- assert((!isa<Function>(GV) || !cast<Function>(GV)->isIntrinsic()) &&
- "Intrinsic functions cannot be mangled by Mangler");
-
- ManglerPrefixTy PrefixTy =
- (GV->hasPrivateLinkage() || ForcePrivate) ? Mangler::Private :
- GV->hasLinkerPrivateLinkage() ? Mangler::LinkerPrivate : Mangler::Default;
-
- SmallString<128> Result;
- if (GV->hasName()) {
- makeNameProper(Result, GV->getNameStr() + Suffix, PrefixTy);
- return Result.str().str();
- }
-
- // Get the ID for the global, assigning a new one if we haven't got one
- // already.
- unsigned &ID = AnonGlobalIDs[GV];
- if (ID == 0) ID = NextAnonGlobalID++;
-
- // Must mangle the global into a unique ID.
- makeNameProper(Result, "__unnamed_" + utostr(ID) + Suffix, PrefixTy);
- return Result.str().str();
-}
-
-/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
-/// and the specified name as the global variable name. GVName must not be
-/// empty.
-void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
- const Twine &GVName, ManglerPrefixTy PrefixTy) {
- SmallString<256> TmpData;
- StringRef Name = GVName.toStringRef(TmpData);
- assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
-
- // If the global name is not led with \1, add the appropriate prefixes.
- if (Name[0] != '\1') {
- if (PrefixTy == Mangler::Private)
- OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix));
- else if (PrefixTy == Mangler::LinkerPrivate)
- OutName.append(LinkerPrivatePrefix,
- LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));
-
- if (Prefix[0] == 0)
- ; // Common noop, no prefix.
- else if (Prefix[1] == 0)
- OutName.push_back(Prefix[0]); // Common, one character prefix.
- else
- OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary prefix.
- } else {
- Name = Name.substr(1);
- }
-
- OutName.append(Name.begin(), Name.end());
-}
-
-
-/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
-/// and the specified global variable's name. If the global variable doesn't
-/// have a name, this fills in a unique name for the global.
-void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
- const GlobalValue *GV,
- bool isImplicitlyPrivate) {
- // If this global has a name, handle it simply.
- if (GV->hasName()) {
- ManglerPrefixTy PrefixTy = Mangler::Default;
- if (GV->hasPrivateLinkage() || isImplicitlyPrivate)
- PrefixTy = Mangler::Private;
- else if (GV->hasLinkerPrivateLinkage())
- PrefixTy = Mangler::LinkerPrivate;
-
- return getNameWithPrefix(OutName, GV->getName(), PrefixTy);
- }
-
- // If the global variable doesn't have a name, return a unique name for the
- // global based on a numbering.
-
- // Anonymous names always get prefixes.
- if (GV->hasPrivateLinkage() || isImplicitlyPrivate)
- OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix));
- else if (GV->hasLinkerPrivateLinkage())
- OutName.append(LinkerPrivatePrefix,
- LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));;
- OutName.append(Prefix, Prefix+strlen(Prefix));
-
- // Get the ID for the global, assigning a new one if we haven't got one
- // already.
- unsigned &ID = AnonGlobalIDs[GV];
- if (ID == 0) ID = NextAnonGlobalID++;
-
- // Must mangle the global into a unique ID.
- raw_svector_ostream(OutName) << "__unnamed_" << ID;
-}
-
-
-Mangler::Mangler(Module &M, const char *prefix, const char *privatePrefix,
- const char *linkerPrivatePrefix)
- : Prefix(prefix), PrivatePrefix(privatePrefix),
- LinkerPrivatePrefix(linkerPrivatePrefix), UseQuotes(false),
- SymbolsCanStartWithDigit(false), NextAnonGlobalID(1) {
- std::fill(AcceptableChars, array_endof(AcceptableChars), 0);
-
- // Letters and numbers are acceptable.
- for (unsigned char X = 'a'; X <= 'z'; ++X)
- markCharAcceptable(X);
- for (unsigned char X = 'A'; X <= 'Z'; ++X)
- markCharAcceptable(X);
- for (unsigned char X = '0'; X <= '9'; ++X)
- markCharAcceptable(X);
-
- // These chars are acceptable.
- markCharAcceptable('_');
- markCharAcceptable('$');
- markCharAcceptable('.');
- markCharAcceptable('@');
-}
diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp
index 7988b44..ee8e713 100644
--- a/lib/VMCore/Metadata.cpp
+++ b/lib/VMCore/Metadata.cpp
@@ -28,7 +28,7 @@ using namespace llvm;
//
MDString::MDString(LLVMContext &C, StringRef S)
- : MetadataBase(Type::getMetadataTy(C), Value::MDStringVal), Str(S) {}
+ : Value(Type::getMetadataTy(C), Value::MDStringVal), Str(S) {}
MDString *MDString::get(LLVMContext &Context, StringRef Str) {
LLVMContextImpl *pImpl = Context.pImpl;
@@ -93,7 +93,7 @@ static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) {
MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals,
bool isFunctionLocal)
-: MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) {
+: Value(Type::getMetadataTy(C), Value::MDNodeVal) {
NumOperands = NumVals;
if (isFunctionLocal)
@@ -121,67 +121,60 @@ MDNode::~MDNode() {
Op->~MDNodeOperand();
}
-#ifndef NDEBUG
-static Function *assertLocalFunction(const MDNode *N,
- SmallPtrSet<const MDNode *, 32> &Visited) {
- Function *F = NULL;
- // Only visit each MDNode once.
- if (!Visited.insert(N)) return F;
-
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- Value *V = N->getOperand(i);
- Function *NewF = NULL;
- if (!V) continue;
- if (Instruction *I = dyn_cast<Instruction>(V))
- NewF = I->getParent()->getParent();
- else if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
- NewF = BB->getParent();
- else if (Argument *A = dyn_cast<Argument>(V))
- NewF = A->getParent();
- else if (MDNode *MD = dyn_cast<MDNode>(V))
- if (MD->isFunctionLocal())
- NewF = assertLocalFunction(MD, Visited);
- if (F && NewF) assert(F == NewF && "inconsistent function-local metadata");
- if (!F) F = NewF;
- }
- return F;
+static const Function *getFunctionForValue(Value *V) {
+ assert(!isa<MDNode>(V) && "does not iterate over metadata operands");
+ if (!V) return NULL;
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ return I->getParent()->getParent();
+ if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
+ return BB->getParent();
+ if (Argument *A = dyn_cast<Argument>(V))
+ return A->getParent();
+ return NULL;
}
-#endif
-static Function *getFunctionHelper(const MDNode *N,
- SmallPtrSet<const MDNode *, 32> &Visited) {
- assert(N->isFunctionLocal() && "Should only be called on function-local MD");
#ifndef NDEBUG
- return assertLocalFunction(N, Visited);
-#endif
- Function *F = NULL;
- // Only visit each MDNode once.
- if (!Visited.insert(N)) return F;
-
+static const Function *assertLocalFunction(const MDNode *N) {
+ if (!N->isFunctionLocal()) return 0;
+
+ const Function *F = 0, *NewF = 0;
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- Value *V = N->getOperand(i);
- if (!V) continue;
- if (Instruction *I = dyn_cast<Instruction>(V))
- F = I->getParent()->getParent();
- else if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
- F = BB->getParent();
- else if (Argument *A = dyn_cast<Argument>(V))
- F = A->getParent();
- else if (MDNode *MD = dyn_cast<MDNode>(V))
- if (MD->isFunctionLocal())
- F = getFunctionHelper(MD, Visited);
- if (F) break;
+ if (Value *V = N->getOperand(i)) {
+ if (MDNode *MD = dyn_cast<MDNode>(V))
+ NewF = assertLocalFunction(MD);
+ else
+ NewF = getFunctionForValue(V);
+ }
+ if (F == 0)
+ F = NewF;
+ else
+ assert((NewF == 0 || F == NewF) &&"inconsistent function-local metadata");
}
return F;
}
+#endif
// getFunction - If this metadata is function-local and recursively has a
// function-local operand, return the first such operand's parent function.
-// Otherwise, return null.
-Function *MDNode::getFunction() const {
+// Otherwise, return null. getFunction() should not be used for performance-
+// critical code because it recursively visits all the MDNode's operands.
+const Function *MDNode::getFunction() const {
+#ifndef NDEBUG
+ return assertLocalFunction(this);
+#endif
if (!isFunctionLocal()) return NULL;
- SmallPtrSet<const MDNode *, 32> Visited;
- return getFunctionHelper(this, Visited);
+
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+ if (Value *V = getOperand(i)) {
+ if (MDNode *MD = dyn_cast<MDNode>(V)) {
+ if (const Function *F = MD->getFunction())
+ return F;
+ } else {
+ return getFunctionForValue(V);
+ }
+ }
+ }
+ return NULL;
}
// destroy - Delete this node. Only when there are no uses.
diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp
index 39da8fb..45000f2 100644
--- a/lib/VMCore/Pass.cpp
+++ b/lib/VMCore/Pass.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Atomic.h"
#include "llvm/System/Mutex.h"
@@ -394,6 +395,8 @@ void PassRegistrationListener::enumeratePasses() {
getPassRegistrar()->EnumerateWith(this);
}
+PassNameParser::~PassNameParser() {}
+
//===----------------------------------------------------------------------===//
// AnalysisUsage Class Implementation
//
diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp
index b37b2ae..0c0d64e 100644
--- a/lib/VMCore/PassManager.cpp
+++ b/lib/VMCore/PassManager.cpp
@@ -127,6 +127,9 @@ public:
bool doFinalization(Module &M);
bool doFinalization(Function &F);
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
virtual const char *getPassName() const {
return "BasicBlock Pass Manager";
}
@@ -169,7 +172,7 @@ private:
public:
static char ID;
explicit FunctionPassManagerImpl(int Depth) :
- Pass(&ID), PMDataManager(Depth),
+ Pass(PT_PassManager, &ID), PMDataManager(Depth),
PMTopLevelManager(TLM_Function), wasRun(false) { }
/// add - Add a pass to the queue of passes to run. This passes ownership of
@@ -196,15 +199,17 @@ public:
///
bool doFinalization(Module &M);
+
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
/// Pass Manager itself does not invalidate any analysis info.
void getAnalysisUsage(AnalysisUsage &Info) const {
Info.setPreservesAll();
}
inline void addTopLevelPass(Pass *P) {
-
- if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (P)) {
-
+ if (ImmutablePass *IP = P->getAsImmutablePass()) {
// P is a immutable pass and it will be managed by this
// top level manager. Set up analysis resolver to connect them.
AnalysisResolver *AR = new AnalysisResolver(*this);
@@ -236,7 +241,7 @@ class MPPassManager : public Pass, public PMDataManager {
public:
static char ID;
explicit MPPassManager(int Depth) :
- Pass(&ID), PMDataManager(Depth) { }
+ Pass(PT_PassManager, &ID), PMDataManager(Depth) { }
// Delete on the fly managers.
virtual ~MPPassManager() {
@@ -271,6 +276,9 @@ public:
return "Module Pass Manager";
}
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
// Print passes managed by this manager
void dumpPassStructure(unsigned Offset) {
llvm::dbgs() << std::string(Offset*2, ' ') << "ModulePass Manager\n";
@@ -313,7 +321,8 @@ class PassManagerImpl : public Pass,
public:
static char ID;
explicit PassManagerImpl(int Depth) :
- Pass(&ID), PMDataManager(Depth), PMTopLevelManager(TLM_Pass) { }
+ Pass(PT_PassManager, &ID), PMDataManager(Depth),
+ PMTopLevelManager(TLM_Pass) { }
/// add - Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
@@ -333,8 +342,7 @@ public:
}
inline void addTopLevelPass(Pass *P) {
- if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (P)) {
-
+ if (ImmutablePass *IP = P->getAsImmutablePass()) {
// P is a immutable pass and it will be managed by this
// top level manager. Set up analysis resolver to connect them.
AnalysisResolver *AR = new AnalysisResolver(*this);
@@ -347,6 +355,9 @@ public:
}
}
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
MPPassManager *getContainedManager(unsigned N) {
assert(N < PassManagers.size() && "Pass number out of range!");
MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]);
@@ -390,7 +401,7 @@ public:
/// passStarted - This method creates a timer for the given pass if it doesn't
/// already have one, and starts the timer.
Timer *passStarted(Pass *P) {
- if (dynamic_cast<PMDataManager *>(P))
+ if (P->getAsPMDataManager())
return 0;
sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
@@ -584,11 +595,11 @@ void PMTopLevelManager::dumpPasses() const {
// Every class that derives from PMDataManager also derives from Pass
// (sometimes indirectly), but there's no inheritance relationship
- // between PMDataManager and Pass, so we have to dynamic_cast to get
+ // between PMDataManager and Pass, so we have to getAsPass to get
// from a PMDataManager* to a Pass*.
for (SmallVector<PMDataManager *, 8>::const_iterator I = PassManagers.begin(),
E = PassManagers.end(); I != E; ++I)
- dynamic_cast<Pass *>(*I)->dumpPassStructure(1);
+ (*I)->getAsPass()->dumpPassStructure(1);
}
void PMTopLevelManager::dumpArguments() const {
@@ -670,7 +681,7 @@ bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) {
for (SmallVector<Pass *, 8>::iterator I = HigherLevelAnalysis.begin(),
E = HigherLevelAnalysis.end(); I != E; ++I) {
Pass *P1 = *I;
- if (!dynamic_cast<ImmutablePass*>(P1) &&
+ if (P1->getAsImmutablePass() == 0 &&
std::find(PreservedSet.begin(), PreservedSet.end(),
P1->getPassInfo()) ==
PreservedSet.end())
@@ -713,8 +724,8 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
for (std::map<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
E = AvailableAnalysis.end(); I != E; ) {
std::map<AnalysisID, Pass*>::iterator Info = I++;
- if (!dynamic_cast<ImmutablePass*>(Info->second)
- && std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
+ if (Info->second->getAsImmutablePass() == 0 &&
+ std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
PreservedSet.end()) {
// Remove this analysis
if (PassDebugging >= Details) {
@@ -737,7 +748,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
I = InheritedAnalysis[Index]->begin(),
E = InheritedAnalysis[Index]->end(); I != E; ) {
std::map<AnalysisID, Pass *>::iterator Info = I++;
- if (!dynamic_cast<ImmutablePass*>(Info->second) &&
+ if (Info->second->getAsImmutablePass() == 0 &&
std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
PreservedSet.end()) {
// Remove this analysis
@@ -854,12 +865,12 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) {
// Set P as P's last user until someone starts using P.
// However, if P is a Pass Manager then it does not need
// to record its last user.
- if (!dynamic_cast<PMDataManager *>(P))
+ if (P->getAsPMDataManager() == 0)
LastUses.push_back(P);
TPM->setLastUser(LastUses, P);
if (!TransferLastUses.empty()) {
- Pass *My_PM = dynamic_cast<Pass *>(this);
+ Pass *My_PM = getAsPass();
TPM->setLastUser(TransferLastUses, My_PM);
TransferLastUses.clear();
}
@@ -968,7 +979,7 @@ void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{
void PMDataManager::dumpPassArguments() const {
for (SmallVector<Pass *, 8>::const_iterator I = PassVector.begin(),
E = PassVector.end(); I != E; ++I) {
- if (PMDataManager *PMD = dynamic_cast<PMDataManager *>(*I))
+ if (PMDataManager *PMD = (*I)->getAsPMDataManager())
PMD->dumpPassArguments();
else
if (const PassInfo *PI = (*I)->getPassInfo())
@@ -1469,7 +1480,7 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, const PassInfo *PI, Function &F){
FPP->releaseMemoryOnTheFly();
FPP->run(F);
- return (dynamic_cast<PMTopLevelManager *>(FPP))->findAnalysisPass(PI);
+ return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI);
}
@@ -1586,7 +1597,7 @@ void PMStack::push(PMDataManager *PM) {
void PMStack::dump() {
for (std::deque<PMDataManager *>::iterator I = S.begin(),
E = S.end(); I != E; ++I)
- printf("%s ", dynamic_cast<Pass *>(*I)->getPassName());
+ printf("%s ", (*I)->getAsPass()->getPassName());
if (!S.empty())
printf("\n");
@@ -1616,16 +1627,18 @@ void FunctionPass::assignPassManager(PMStack &PMS,
PassManagerType PreferredType) {
// Find Module Pass Manager
- while(!PMS.empty()) {
+ while (!PMS.empty()) {
if (PMS.top()->getPassManagerType() > PMT_FunctionPassManager)
PMS.pop();
else
break;
}
- FPPassManager *FPP = dynamic_cast<FPPassManager *>(PMS.top());
- // Create new Function Pass Manager
- if (!FPP) {
+ // Create new Function Pass Manager if needed.
+ FPPassManager *FPP;
+ if (PMS.top()->getPassManagerType() == PMT_FunctionPassManager) {
+ FPP = (FPPassManager *)PMS.top();
+ } else {
assert(!PMS.empty() && "Unable to create Function Pass Manager");
PMDataManager *PMD = PMS.top();
@@ -1653,17 +1666,16 @@ void FunctionPass::assignPassManager(PMStack &PMS,
/// in the PM Stack and add self into that manager.
void BasicBlockPass::assignPassManager(PMStack &PMS,
PassManagerType PreferredType) {
- BBPassManager *BBP = NULL;
+ BBPassManager *BBP;
// Basic Pass Manager is a leaf pass manager. It does not handle
// any other pass manager.
- if (!PMS.empty())
- BBP = dynamic_cast<BBPassManager *>(PMS.top());
-
- // If leaf manager is not Basic Block Pass manager then create new
- // basic Block Pass manager.
-
- if (!BBP) {
+ if (!PMS.empty() &&
+ PMS.top()->getPassManagerType() == PMT_BasicBlockPassManager) {
+ BBP = (BBPassManager *)PMS.top();
+ } else {
+ // If leaf manager is not Basic Block Pass manager then create new
+ // basic Block Pass manager.
assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager");
PMDataManager *PMD = PMS.top();
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index ec475e4..76d9d43 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1301,6 +1301,8 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
&AI);
Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type",
&AI);
+ Assert1(AI.getArraySize()->getType()->isInteger(32),
+ "Alloca array size must be i32", &AI);
visitInstruction(AI);
}
@@ -1579,7 +1581,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
// If the intrinsic takes MDNode arguments, verify that they are either global
// or are local to *this* function.
- for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)
+ for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
if (MDNode *MD = dyn_cast<MDNode>(CI.getOperand(i))) {
if (!MD->isFunctionLocal()) continue;
SmallPtrSet<MDNode *, 32> Visited;
@@ -1589,12 +1591,17 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
switch (ID) {
default:
break;
- case Intrinsic::dbg_declare: // llvm.dbg.declare
- if (MDNode *MD = dyn_cast<MDNode>(CI.getOperand(1)))
+ case Intrinsic::dbg_declare: { // llvm.dbg.declare
+ Assert1(CI.getOperand(1) && isa<MDNode>(CI.getOperand(1)),
+ "invalid llvm.dbg.declare intrinsic call 1", &CI);
+ MDNode *MD = cast<MDNode>(CI.getOperand(1));
+ Assert1(MD->getNumOperands() == 1,
+ "invalid llvm.dbg.declare intrinsic call 2", &CI);
+ if (MD->getOperand(0))
if (Constant *C = dyn_cast<Constant>(MD->getOperand(0)))
Assert1(C && !isa<ConstantPointerNull>(C),
- "invalid llvm.dbg.declare intrinsic call", &CI);
- break;
+ "invalid llvm.dbg.declare intrinsic call 3", &CI);
+ } break;
case Intrinsic::memcpy:
case Intrinsic::memmove:
case Intrinsic::memset:
OpenPOWER on IntegriCloud