1 // The LLVM Compiler Infrastructure
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file contains a printer that converts from our internal representation
9 // of machine-dependent LLVM code to GAS-format ARM assembly language.
11 //===----------------------------------------------------------------------===//
13 #define DEBUG_TYPE "asm-printer"
15 #include "ARMBuildAttrs.h"
16 #include "ARMTargetMachine.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMConstantPoolValue.h"
19 #include "ARMMachineFunctionInfo.h"
20 #include "llvm/Constants.h"
21 #include "llvm/Module.h"
22 #include "llvm/Assembly/Writer.h"
23 #include "llvm/CodeGen/AsmPrinter.h"
24 #include "llvm/CodeGen/DwarfWriter.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineJumpTableInfo.h"
28 #include "llvm/MC/MCSectionMachO.h"
29 #include "llvm/MC/MCStreamer.h"
30 #include "llvm/MC/MCAsmInfo.h"
31 #include "llvm/MC/MCSymbol.h"
32 #include "llvm/Target/TargetData.h"
33 #include "llvm/Target/TargetLoweringObjectFile.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Target/TargetOptions.h"
36 #include "llvm/Target/TargetRegistry.h"
37 #include "llvm/ADT/SmallPtrSet.h"
38 #include "llvm/ADT/SmallString.h"
39 #include "llvm/ADT/Statistic.h"
40 #include "llvm/ADT/StringSet.h"
41 #include "llvm/Support/Compiler.h"
42 #include "llvm/Support/ErrorHandling.h"
43 #include "llvm/Support/Mangler.h"
44 #include "llvm/Support/MathExtras.h"
45 #include "llvm/Support/FormattedStream.h"
49 STATISTIC(EmittedInsts
, "Number of machine instrs printed");
52 class VISIBILITY_HIDDEN ARMAsmPrinter
: public AsmPrinter
{
55 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
56 /// make the right decision when printing asm code for different targets.
57 const ARMSubtarget
*Subtarget
;
59 /// AFI - Keep a pointer to ARMFunctionInfo for the current
63 /// MCP - Keep a pointer to constantpool entries of the current
65 const MachineConstantPool
*MCP
;
67 /// We name each basic block in a Function with a unique number, so
68 /// that we can consistently refer to them later. This is cleared
69 /// at the beginning of each call to runOnMachineFunction().
71 typedef std::map
<const Value
*, unsigned> ValueMapTy
;
72 ValueMapTy NumberForBB
;
74 /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
75 /// non-lazy-pointers for indirect access.
76 StringMap
<std::string
> GVNonLazyPtrs
;
78 /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden
79 /// visibility that require non-lazy-pointers for indirect access.
80 StringMap
<std::string
> HiddenGVNonLazyPtrs
;
82 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
85 explicit ARMAsmPrinter(formatted_raw_ostream
&O
, TargetMachine
&TM
,
86 const MCAsmInfo
*T
, bool V
)
87 : AsmPrinter(O
, TM
, T
, V
), DW(0), AFI(NULL
), MCP(NULL
),
89 Subtarget
= &TM
.getSubtarget
<ARMSubtarget
>();
92 virtual const char *getPassName() const {
93 return "ARM Assembly Printer";
96 void printOperand(const MachineInstr
*MI
, int OpNum
,
97 const char *Modifier
= 0);
98 void printSOImmOperand(const MachineInstr
*MI
, int OpNum
);
99 void printSOImm2PartOperand(const MachineInstr
*MI
, int OpNum
);
100 void printSORegOperand(const MachineInstr
*MI
, int OpNum
);
101 void printAddrMode2Operand(const MachineInstr
*MI
, int OpNum
);
102 void printAddrMode2OffsetOperand(const MachineInstr
*MI
, int OpNum
);
103 void printAddrMode3Operand(const MachineInstr
*MI
, int OpNum
);
104 void printAddrMode3OffsetOperand(const MachineInstr
*MI
, int OpNum
);
105 void printAddrMode4Operand(const MachineInstr
*MI
, int OpNum
,
106 const char *Modifier
= 0);
107 void printAddrMode5Operand(const MachineInstr
*MI
, int OpNum
,
108 const char *Modifier
= 0);
109 void printAddrMode6Operand(const MachineInstr
*MI
, int OpNum
);
110 void printAddrModePCOperand(const MachineInstr
*MI
, int OpNum
,
111 const char *Modifier
= 0);
112 void printBitfieldInvMaskImmOperand (const MachineInstr
*MI
, int OpNum
);
114 void printThumbITMask(const MachineInstr
*MI
, int OpNum
);
115 void printThumbAddrModeRROperand(const MachineInstr
*MI
, int OpNum
);
116 void printThumbAddrModeRI5Operand(const MachineInstr
*MI
, int OpNum
,
118 void printThumbAddrModeS1Operand(const MachineInstr
*MI
, int OpNum
);
119 void printThumbAddrModeS2Operand(const MachineInstr
*MI
, int OpNum
);
120 void printThumbAddrModeS4Operand(const MachineInstr
*MI
, int OpNum
);
121 void printThumbAddrModeSPOperand(const MachineInstr
*MI
, int OpNum
);
123 void printT2SOOperand(const MachineInstr
*MI
, int OpNum
);
124 void printT2AddrModeImm12Operand(const MachineInstr
*MI
, int OpNum
);
125 void printT2AddrModeImm8Operand(const MachineInstr
*MI
, int OpNum
);
126 void printT2AddrModeImm8s4Operand(const MachineInstr
*MI
, int OpNum
);
127 void printT2AddrModeImm8OffsetOperand(const MachineInstr
*MI
, int OpNum
);
128 void printT2AddrModeSoRegOperand(const MachineInstr
*MI
, int OpNum
);
130 void printPredicateOperand(const MachineInstr
*MI
, int OpNum
);
131 void printSBitModifierOperand(const MachineInstr
*MI
, int OpNum
);
132 void printPCLabel(const MachineInstr
*MI
, int OpNum
);
133 void printRegisterList(const MachineInstr
*MI
, int OpNum
);
134 void printCPInstOperand(const MachineInstr
*MI
, int OpNum
,
135 const char *Modifier
);
136 void printJTBlockOperand(const MachineInstr
*MI
, int OpNum
);
137 void printJT2BlockOperand(const MachineInstr
*MI
, int OpNum
);
138 void printTBAddrMode(const MachineInstr
*MI
, int OpNum
);
139 void printNoHashImmediate(const MachineInstr
*MI
, int OpNum
);
141 virtual bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNum
,
142 unsigned AsmVariant
, const char *ExtraCode
);
143 virtual bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNum
,
145 const char *ExtraCode
);
147 void PrintGlobalVariable(const GlobalVariable
* GVar
);
148 void printInstruction(const MachineInstr
*MI
); // autogenerated.
149 const char *getRegisterName(unsigned RegNo
) const;
151 void printMachineInstruction(const MachineInstr
*MI
);
152 bool runOnMachineFunction(MachineFunction
&F
);
153 bool doInitialization(Module
&M
);
154 bool doFinalization(Module
&M
);
156 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
158 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue
*MCPV
) {
159 printDataDirective(MCPV
->getType());
161 ARMConstantPoolValue
*ACPV
= static_cast<ARMConstantPoolValue
*>(MCPV
);
162 GlobalValue
*GV
= ACPV
->getGV();
165 if (ACPV
->isLSDA()) {
166 SmallString
<16> LSDAName
;
167 raw_svector_ostream(LSDAName
) << MAI
->getPrivateGlobalPrefix() <<
168 "_LSDA_" << getFunctionNumber();
169 Name
= LSDAName
.str();
171 bool isIndirect
= Subtarget
->isTargetDarwin() &&
172 Subtarget
->GVIsIndirectSymbol(GV
, TM
.getRelocationModel());
174 Name
= Mang
->getMangledName(GV
);
176 // FIXME: Remove this when Darwin transition to @GOT like syntax.
177 std::string SymName
= Mang
->getMangledName(GV
);
178 Name
= Mang
->getMangledName(GV
, "$non_lazy_ptr", true);
179 if (GV
->hasHiddenVisibility())
180 HiddenGVNonLazyPtrs
[SymName
] = Name
;
182 GVNonLazyPtrs
[SymName
] = Name
;
185 Name
= Mang
->makeNameProper(ACPV
->getSymbol());
188 if (ACPV
->hasModifier()) O
<< "(" << ACPV
->getModifier() << ")";
189 if (ACPV
->getPCAdjustment() != 0) {
190 O
<< "-(" << MAI
->getPrivateGlobalPrefix() << "PC"
191 << ACPV
->getLabelId()
192 << "+" << (unsigned)ACPV
->getPCAdjustment();
193 if (ACPV
->mustAddCurrentAddress())
200 void getAnalysisUsage(AnalysisUsage
&AU
) const {
201 AsmPrinter::getAnalysisUsage(AU
);
202 AU
.setPreservesAll();
203 AU
.addRequired
<MachineModuleInfo
>();
204 AU
.addRequired
<DwarfWriter
>();
207 } // end of anonymous namespace
209 #include "ARMGenAsmWriter.inc"
211 /// runOnMachineFunction - This uses the printInstruction()
212 /// method to print assembly for each instruction.
214 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
217 AFI
= MF
.getInfo
<ARMFunctionInfo
>();
218 MCP
= MF
.getConstantPool();
220 SetupMachineFunction(MF
);
223 // NOTE: we don't print out constant pools here, they are handled as
228 // Print out labels for the function.
229 const Function
*F
= MF
.getFunction();
230 OutStreamer
.SwitchSection(getObjFileLowering().SectionForGlobal(F
, Mang
, TM
));
232 switch (F
->getLinkage()) {
233 default: llvm_unreachable("Unknown linkage type!");
234 case Function::PrivateLinkage
:
235 case Function::InternalLinkage
:
237 case Function::ExternalLinkage
:
238 O
<< "\t.globl\t" << CurrentFnName
<< "\n";
240 case Function::LinkerPrivateLinkage
:
241 case Function::WeakAnyLinkage
:
242 case Function::WeakODRLinkage
:
243 case Function::LinkOnceAnyLinkage
:
244 case Function::LinkOnceODRLinkage
:
245 if (Subtarget
->isTargetDarwin()) {
246 O
<< "\t.globl\t" << CurrentFnName
<< "\n";
247 O
<< "\t.weak_definition\t" << CurrentFnName
<< "\n";
249 O
<< MAI
->getWeakRefDirective() << CurrentFnName
<< "\n";
254 printVisibility(CurrentFnName
, F
->getVisibility());
256 if (AFI
->isThumbFunction()) {
257 EmitAlignment(MF
.getAlignment(), F
, AFI
->getAlign());
258 O
<< "\t.code\t16\n";
259 O
<< "\t.thumb_func";
260 if (Subtarget
->isTargetDarwin())
261 O
<< "\t" << CurrentFnName
;
265 EmitAlignment(MF
.getAlignment(), F
);
268 O
<< CurrentFnName
<< ":\n";
269 // Emit pre-function debug information.
270 DW
->BeginFunction(&MF
);
272 if (Subtarget
->isTargetDarwin()) {
273 // If the function is empty, then we need to emit *something*. Otherwise,
274 // the function's label might be associated with something that it wasn't
275 // meant to be associated with. We emit a noop in this situation.
276 MachineFunction::iterator I
= MF
.begin();
278 if (++I
== MF
.end() && MF
.front().empty())
282 // Print out code for the function.
283 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
285 // Print a label for the basic block.
286 if (I
!= MF
.begin()) {
287 EmitBasicBlockStart(I
);
290 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
292 // Print the assembly for the instruction.
293 printMachineInstruction(II
);
297 if (MAI
->hasDotTypeDotSizeDirective())
298 O
<< "\t.size " << CurrentFnName
<< ", .-" << CurrentFnName
<< "\n";
300 // Emit post-function debug information.
301 DW
->EndFunction(&MF
);
306 void ARMAsmPrinter::printOperand(const MachineInstr
*MI
, int OpNum
,
307 const char *Modifier
) {
308 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
309 switch (MO
.getType()) {
310 case MachineOperand::MO_Register
: {
311 unsigned Reg
= MO
.getReg();
312 if (TargetRegisterInfo::isPhysicalRegister(Reg
)) {
313 if (Modifier
&& strcmp(Modifier
, "dregpair") == 0) {
314 unsigned DRegLo
= TRI
->getSubReg(Reg
, 5); // arm_dsubreg_0
315 unsigned DRegHi
= TRI
->getSubReg(Reg
, 6); // arm_dsubreg_1
317 << TRI
->getAsmName(DRegLo
) << ',' << TRI
->getAsmName(DRegHi
)
319 } else if (Modifier
&& strcmp(Modifier
, "lane") == 0) {
320 unsigned RegNum
= ARMRegisterInfo::getRegisterNumbering(Reg
);
321 unsigned DReg
= TRI
->getMatchingSuperReg(Reg
, RegNum
& 1 ? 0 : 1,
323 O
<< TRI
->getAsmName(DReg
) << '[' << (RegNum
& 1) << ']';
325 O
<< TRI
->getAsmName(Reg
);
328 llvm_unreachable("not implemented");
331 case MachineOperand::MO_Immediate
: {
332 O
<< '#' << MO
.getImm();
335 case MachineOperand::MO_MachineBasicBlock
:
336 GetMBBSymbol(MO
.getMBB()->getNumber())->print(O
, MAI
);
338 case MachineOperand::MO_GlobalAddress
: {
339 bool isCallOp
= Modifier
&& !strcmp(Modifier
, "call");
340 GlobalValue
*GV
= MO
.getGlobal();
341 O
<< Mang
->getMangledName(GV
);
343 printOffset(MO
.getOffset());
345 if (isCallOp
&& Subtarget
->isTargetELF() &&
346 TM
.getRelocationModel() == Reloc::PIC_
)
350 case MachineOperand::MO_ExternalSymbol
: {
351 bool isCallOp
= Modifier
&& !strcmp(Modifier
, "call");
352 std::string Name
= Mang
->makeNameProper(MO
.getSymbolName());
355 if (isCallOp
&& Subtarget
->isTargetELF() &&
356 TM
.getRelocationModel() == Reloc::PIC_
)
360 case MachineOperand::MO_ConstantPoolIndex
:
361 O
<< MAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
362 << '_' << MO
.getIndex();
364 case MachineOperand::MO_JumpTableIndex
:
365 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
366 << '_' << MO
.getIndex();
369 O
<< "<unknown operand type>"; abort (); break;
373 static void printSOImm(formatted_raw_ostream
&O
, int64_t V
, bool VerboseAsm
,
374 const MCAsmInfo
*MAI
) {
375 // Break it up into two parts that make up a shifter immediate.
376 V
= ARM_AM::getSOImmVal(V
);
377 assert(V
!= -1 && "Not a valid so_imm value!");
379 unsigned Imm
= ARM_AM::getSOImmValImm(V
);
380 unsigned Rot
= ARM_AM::getSOImmValRot(V
);
382 // Print low-level immediate formation info, per
383 // A5.1.3: "Data-processing operands - Immediate".
385 O
<< "#" << Imm
<< ", " << Rot
;
386 // Pretty printed version.
388 O
<< ' ' << MAI
->getCommentString()
389 << ' ' << (int)ARM_AM::rotr32(Imm
, Rot
);
395 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
396 /// immediate in bits 0-7.
397 void ARMAsmPrinter::printSOImmOperand(const MachineInstr
*MI
, int OpNum
) {
398 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
399 assert(MO
.isImm() && "Not a valid so_imm value!");
400 printSOImm(O
, MO
.getImm(), VerboseAsm
, MAI
);
403 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
404 /// followed by an 'orr' to materialize.
405 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr
*MI
, int OpNum
) {
406 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
407 assert(MO
.isImm() && "Not a valid so_imm value!");
408 unsigned V1
= ARM_AM::getSOImmTwoPartFirst(MO
.getImm());
409 unsigned V2
= ARM_AM::getSOImmTwoPartSecond(MO
.getImm());
410 printSOImm(O
, V1
, VerboseAsm
, MAI
);
412 printPredicateOperand(MI
, 2);
418 printSOImm(O
, V2
, VerboseAsm
, MAI
);
421 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
422 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
424 // REG REG 0,SH_OPC - e.g. R5, ROR R3
425 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
426 void ARMAsmPrinter::printSORegOperand(const MachineInstr
*MI
, int Op
) {
427 const MachineOperand
&MO1
= MI
->getOperand(Op
);
428 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
429 const MachineOperand
&MO3
= MI
->getOperand(Op
+2);
431 assert(TargetRegisterInfo::isPhysicalRegister(MO1
.getReg()));
432 O
<< TRI
->getAsmName(MO1
.getReg());
434 // Print the shift opc.
436 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3
.getImm()))
440 assert(TargetRegisterInfo::isPhysicalRegister(MO2
.getReg()));
441 O
<< TRI
->getAsmName(MO2
.getReg());
442 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
444 O
<< "#" << ARM_AM::getSORegOffset(MO3
.getImm());
448 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr
*MI
, int Op
) {
449 const MachineOperand
&MO1
= MI
->getOperand(Op
);
450 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
451 const MachineOperand
&MO3
= MI
->getOperand(Op
+2);
453 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
454 printOperand(MI
, Op
);
458 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
461 if (ARM_AM::getAM2Offset(MO3
.getImm())) // Don't print +0.
463 << (char)ARM_AM::getAM2Op(MO3
.getImm())
464 << ARM_AM::getAM2Offset(MO3
.getImm());
470 << (char)ARM_AM::getAM2Op(MO3
.getImm())
471 << TRI
->getAsmName(MO2
.getReg());
473 if (unsigned ShImm
= ARM_AM::getAM2Offset(MO3
.getImm()))
475 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3
.getImm()))
480 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr
*MI
, int Op
){
481 const MachineOperand
&MO1
= MI
->getOperand(Op
);
482 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
485 unsigned ImmOffs
= ARM_AM::getAM2Offset(MO2
.getImm());
486 assert(ImmOffs
&& "Malformed indexed load / store!");
488 << (char)ARM_AM::getAM2Op(MO2
.getImm())
493 O
<< (char)ARM_AM::getAM2Op(MO2
.getImm())
494 << TRI
->getAsmName(MO1
.getReg());
496 if (unsigned ShImm
= ARM_AM::getAM2Offset(MO2
.getImm()))
498 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2
.getImm()))
502 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr
*MI
, int Op
) {
503 const MachineOperand
&MO1
= MI
->getOperand(Op
);
504 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
505 const MachineOperand
&MO3
= MI
->getOperand(Op
+2);
507 assert(TargetRegisterInfo::isPhysicalRegister(MO1
.getReg()));
508 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
512 << (char)ARM_AM::getAM3Op(MO3
.getImm())
513 << TRI
->getAsmName(MO2
.getReg())
518 if (unsigned ImmOffs
= ARM_AM::getAM3Offset(MO3
.getImm()))
520 << (char)ARM_AM::getAM3Op(MO3
.getImm())
525 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr
*MI
, int Op
){
526 const MachineOperand
&MO1
= MI
->getOperand(Op
);
527 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
530 O
<< (char)ARM_AM::getAM3Op(MO2
.getImm())
531 << TRI
->getAsmName(MO1
.getReg());
535 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO2
.getImm());
536 assert(ImmOffs
&& "Malformed indexed load / store!");
538 << (char)ARM_AM::getAM3Op(MO2
.getImm())
542 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr
*MI
, int Op
,
543 const char *Modifier
) {
544 const MachineOperand
&MO1
= MI
->getOperand(Op
);
545 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
546 ARM_AM::AMSubMode Mode
= ARM_AM::getAM4SubMode(MO2
.getImm());
547 if (Modifier
&& strcmp(Modifier
, "submode") == 0) {
548 if (MO1
.getReg() == ARM::SP
) {
550 bool isLDM
= (MI
->getOpcode() == ARM::LDM
||
551 MI
->getOpcode() == ARM::LDM_RET
||
552 MI
->getOpcode() == ARM::t2LDM
||
553 MI
->getOpcode() == ARM::t2LDM_RET
);
554 O
<< ARM_AM::getAMSubModeAltStr(Mode
, isLDM
);
556 O
<< ARM_AM::getAMSubModeStr(Mode
);
557 } else if (Modifier
&& strcmp(Modifier
, "wide") == 0) {
558 ARM_AM::AMSubMode Mode
= ARM_AM::getAM4SubMode(MO2
.getImm());
559 if (Mode
== ARM_AM::ia
)
562 printOperand(MI
, Op
);
563 if (ARM_AM::getAM4WBFlag(MO2
.getImm()))
568 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr
*MI
, int Op
,
569 const char *Modifier
) {
570 const MachineOperand
&MO1
= MI
->getOperand(Op
);
571 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
573 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
574 printOperand(MI
, Op
);
578 assert(TargetRegisterInfo::isPhysicalRegister(MO1
.getReg()));
580 if (Modifier
&& strcmp(Modifier
, "submode") == 0) {
581 ARM_AM::AMSubMode Mode
= ARM_AM::getAM5SubMode(MO2
.getImm());
582 if (MO1
.getReg() == ARM::SP
) {
583 bool isFLDM
= (MI
->getOpcode() == ARM::FLDMD
||
584 MI
->getOpcode() == ARM::FLDMS
);
585 O
<< ARM_AM::getAMSubModeAltStr(Mode
, isFLDM
);
587 O
<< ARM_AM::getAMSubModeStr(Mode
);
589 } else if (Modifier
&& strcmp(Modifier
, "base") == 0) {
590 // Used for FSTM{D|S} and LSTM{D|S} operations.
591 O
<< TRI
->getAsmName(MO1
.getReg());
592 if (ARM_AM::getAM5WBFlag(MO2
.getImm()))
597 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
599 if (unsigned ImmOffs
= ARM_AM::getAM5Offset(MO2
.getImm())) {
601 << (char)ARM_AM::getAM5Op(MO2
.getImm())
607 void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr
*MI
, int Op
) {
608 const MachineOperand
&MO1
= MI
->getOperand(Op
);
609 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
610 const MachineOperand
&MO3
= MI
->getOperand(Op
+2);
612 // FIXME: No support yet for specifying alignment.
613 O
<< "[" << TRI
->getAsmName(MO1
.getReg()) << "]";
615 if (ARM_AM::getAM6WBFlag(MO3
.getImm())) {
616 if (MO2
.getReg() == 0)
619 O
<< ", " << TRI
->getAsmName(MO2
.getReg());
623 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr
*MI
, int Op
,
624 const char *Modifier
) {
625 if (Modifier
&& strcmp(Modifier
, "label") == 0) {
626 printPCLabel(MI
, Op
+1);
630 const MachineOperand
&MO1
= MI
->getOperand(Op
);
631 assert(TargetRegisterInfo::isPhysicalRegister(MO1
.getReg()));
632 O
<< "[pc, +" << TRI
->getAsmName(MO1
.getReg()) << "]";
636 ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr
*MI
, int Op
) {
637 const MachineOperand
&MO
= MI
->getOperand(Op
);
638 uint32_t v
= ~MO
.getImm();
639 int32_t lsb
= CountTrailingZeros_32(v
);
640 int32_t width
= (32 - CountLeadingZeros_32 (v
)) - lsb
;
641 assert(MO
.isImm() && "Not a valid bf_inv_mask_imm value!");
642 O
<< "#" << lsb
<< ", #" << width
;
645 //===--------------------------------------------------------------------===//
648 ARMAsmPrinter::printThumbITMask(const MachineInstr
*MI
, int Op
) {
649 // (3 - the number of trailing zeros) is the number of then / else.
650 unsigned Mask
= MI
->getOperand(Op
).getImm();
651 unsigned NumTZ
= CountTrailingZeros_32(Mask
);
652 assert(NumTZ
<= 3 && "Invalid IT mask!");
653 for (unsigned Pos
= 3, e
= NumTZ
; Pos
> e
; --Pos
) {
654 bool T
= (Mask
& (1 << Pos
)) == 0;
663 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr
*MI
, int Op
) {
664 const MachineOperand
&MO1
= MI
->getOperand(Op
);
665 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
666 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
667 O
<< ", " << TRI
->getAsmName(MO2
.getReg()) << "]";
671 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr
*MI
, int Op
,
673 const MachineOperand
&MO1
= MI
->getOperand(Op
);
674 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
675 const MachineOperand
&MO3
= MI
->getOperand(Op
+2);
677 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
678 printOperand(MI
, Op
);
682 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
684 O
<< ", " << TRI
->getAsmName(MO3
.getReg());
685 else if (unsigned ImmOffs
= MO2
.getImm()) {
686 O
<< ", #" << ImmOffs
;
694 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr
*MI
, int Op
) {
695 printThumbAddrModeRI5Operand(MI
, Op
, 1);
698 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr
*MI
, int Op
) {
699 printThumbAddrModeRI5Operand(MI
, Op
, 2);
702 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr
*MI
, int Op
) {
703 printThumbAddrModeRI5Operand(MI
, Op
, 4);
706 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr
*MI
,int Op
) {
707 const MachineOperand
&MO1
= MI
->getOperand(Op
);
708 const MachineOperand
&MO2
= MI
->getOperand(Op
+1);
709 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
710 if (unsigned ImmOffs
= MO2
.getImm())
711 O
<< ", #" << ImmOffs
<< " * 4";
715 //===--------------------------------------------------------------------===//
717 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
718 // register with shift forms.
720 // REG IMM, SH_OPC - e.g. R5, LSL #3
721 void ARMAsmPrinter::printT2SOOperand(const MachineInstr
*MI
, int OpNum
) {
722 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
723 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1);
725 unsigned Reg
= MO1
.getReg();
726 assert(TargetRegisterInfo::isPhysicalRegister(Reg
));
727 O
<< TRI
->getAsmName(Reg
);
729 // Print the shift opc.
731 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2
.getImm()))
734 assert(MO2
.isImm() && "Not a valid t2_so_reg value!");
735 O
<< "#" << ARM_AM::getSORegOffset(MO2
.getImm());
738 void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr
*MI
,
740 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
741 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1);
743 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
745 unsigned OffImm
= MO2
.getImm();
746 if (OffImm
) // Don't print +0.
747 O
<< ", #+" << OffImm
;
751 void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr
*MI
,
753 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
754 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1);
756 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
758 int32_t OffImm
= (int32_t)MO2
.getImm();
761 O
<< ", #-" << -OffImm
;
763 O
<< ", #+" << OffImm
;
767 void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr
*MI
,
769 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
770 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1);
772 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
774 int32_t OffImm
= (int32_t)MO2
.getImm() / 4;
777 O
<< ", #-" << -OffImm
<< " * 4";
779 O
<< ", #+" << OffImm
<< " * 4";
783 void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr
*MI
,
785 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
786 int32_t OffImm
= (int32_t)MO1
.getImm();
789 O
<< "#-" << -OffImm
;
794 void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr
*MI
,
796 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
797 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1);
798 const MachineOperand
&MO3
= MI
->getOperand(OpNum
+2);
800 O
<< "[" << TRI
->getAsmName(MO1
.getReg());
802 assert(MO2
.getReg() && "Invalid so_reg load / store address!");
803 O
<< ", " << TRI
->getAsmName(MO2
.getReg());
805 unsigned ShAmt
= MO3
.getImm();
807 assert(ShAmt
<= 3 && "Not a valid Thumb2 addressing mode!");
808 O
<< ", lsl #" << ShAmt
;
814 //===--------------------------------------------------------------------===//
816 void ARMAsmPrinter::printPredicateOperand(const MachineInstr
*MI
, int OpNum
) {
817 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
819 O
<< ARMCondCodeToString(CC
);
822 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr
*MI
, int OpNum
){
823 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
825 assert(Reg
== ARM::CPSR
&& "Expect ARM CPSR register!");
830 void ARMAsmPrinter::printPCLabel(const MachineInstr
*MI
, int OpNum
) {
831 int Id
= (int)MI
->getOperand(OpNum
).getImm();
832 O
<< MAI
->getPrivateGlobalPrefix() << "PC" << Id
;
835 void ARMAsmPrinter::printRegisterList(const MachineInstr
*MI
, int OpNum
) {
837 for (unsigned i
= OpNum
, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
838 if (MI
->getOperand(i
).isImplicit())
840 if ((int)i
!= OpNum
) O
<< ", ";
846 void ARMAsmPrinter::printCPInstOperand(const MachineInstr
*MI
, int OpNum
,
847 const char *Modifier
) {
848 assert(Modifier
&& "This operand only works with a modifier!");
849 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
851 if (!strcmp(Modifier
, "label")) {
852 unsigned ID
= MI
->getOperand(OpNum
).getImm();
853 O
<< MAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
854 << '_' << ID
<< ":\n";
856 assert(!strcmp(Modifier
, "cpentry") && "Unknown modifier for CPE");
857 unsigned CPI
= MI
->getOperand(OpNum
).getIndex();
859 const MachineConstantPoolEntry
&MCPE
= MCP
->getConstants()[CPI
];
861 if (MCPE
.isMachineConstantPoolEntry()) {
862 EmitMachineConstantPoolValue(MCPE
.Val
.MachineCPVal
);
864 EmitGlobalConstant(MCPE
.Val
.ConstVal
);
869 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr
*MI
, int OpNum
) {
870 assert(!Subtarget
->isThumb2() && "Thumb2 should use double-jump jumptables!");
872 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
873 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1); // Unique Id
874 unsigned JTI
= MO1
.getIndex();
875 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
876 << '_' << JTI
<< '_' << MO2
.getImm() << ":\n";
878 const char *JTEntryDirective
= MAI
->getData32bitsDirective();
880 const MachineFunction
*MF
= MI
->getParent()->getParent();
881 const MachineJumpTableInfo
*MJTI
= MF
->getJumpTableInfo();
882 const std::vector
<MachineJumpTableEntry
> &JT
= MJTI
->getJumpTables();
883 const std::vector
<MachineBasicBlock
*> &JTBBs
= JT
[JTI
].MBBs
;
884 bool UseSet
= MAI
->getSetDirective() && TM
.getRelocationModel() == Reloc::PIC_
;
885 SmallPtrSet
<MachineBasicBlock
*, 8> JTSets
;
886 for (unsigned i
= 0, e
= JTBBs
.size(); i
!= e
; ++i
) {
887 MachineBasicBlock
*MBB
= JTBBs
[i
];
888 bool isNew
= JTSets
.insert(MBB
);
891 printPICJumpTableSetLabel(JTI
, MO2
.getImm(), MBB
);
893 O
<< JTEntryDirective
<< ' ';
895 O
<< MAI
->getPrivateGlobalPrefix() << getFunctionNumber()
896 << '_' << JTI
<< '_' << MO2
.getImm()
897 << "_set_" << MBB
->getNumber();
898 else if (TM
.getRelocationModel() == Reloc::PIC_
) {
899 GetMBBSymbol(MBB
->getNumber())->print(O
, MAI
);
900 O
<< '-' << MAI
->getPrivateGlobalPrefix() << "JTI"
901 << getFunctionNumber() << '_' << JTI
<< '_' << MO2
.getImm();
903 GetMBBSymbol(MBB
->getNumber())->print(O
, MAI
);
910 void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr
*MI
, int OpNum
) {
911 const MachineOperand
&MO1
= MI
->getOperand(OpNum
);
912 const MachineOperand
&MO2
= MI
->getOperand(OpNum
+1); // Unique Id
913 unsigned JTI
= MO1
.getIndex();
914 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
915 << '_' << JTI
<< '_' << MO2
.getImm() << ":\n";
917 const MachineFunction
*MF
= MI
->getParent()->getParent();
918 const MachineJumpTableInfo
*MJTI
= MF
->getJumpTableInfo();
919 const std::vector
<MachineJumpTableEntry
> &JT
= MJTI
->getJumpTables();
920 const std::vector
<MachineBasicBlock
*> &JTBBs
= JT
[JTI
].MBBs
;
921 bool ByteOffset
= false, HalfWordOffset
= false;
922 if (MI
->getOpcode() == ARM::t2TBB
)
924 else if (MI
->getOpcode() == ARM::t2TBH
)
925 HalfWordOffset
= true;
927 for (unsigned i
= 0, e
= JTBBs
.size(); i
!= e
; ++i
) {
928 MachineBasicBlock
*MBB
= JTBBs
[i
];
930 O
<< MAI
->getData8bitsDirective();
931 else if (HalfWordOffset
)
932 O
<< MAI
->getData16bitsDirective();
933 if (ByteOffset
|| HalfWordOffset
) {
935 GetMBBSymbol(MBB
->getNumber())->print(O
, MAI
);
936 O
<< "-" << MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
937 << '_' << JTI
<< '_' << MO2
.getImm() << ")/2";
940 GetMBBSymbol(MBB
->getNumber())->print(O
, MAI
);
946 // Make sure the instruction that follows TBB is 2-byte aligned.
947 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
948 if (ByteOffset
&& (JTBBs
.size() & 1)) {
954 void ARMAsmPrinter::printTBAddrMode(const MachineInstr
*MI
, int OpNum
) {
955 O
<< "[pc, " << TRI
->getAsmName(MI
->getOperand(OpNum
).getReg());
956 if (MI
->getOpcode() == ARM::t2TBH
)
961 void ARMAsmPrinter::printNoHashImmediate(const MachineInstr
*MI
, int OpNum
) {
962 O
<< MI
->getOperand(OpNum
).getImm();
965 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNum
,
966 unsigned AsmVariant
, const char *ExtraCode
){
967 // Does this asm operand have a single letter operand modifier?
968 if (ExtraCode
&& ExtraCode
[0]) {
969 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
971 switch (ExtraCode
[0]) {
972 default: return true; // Unknown modifier.
973 case 'a': // Print as a memory address.
974 if (MI
->getOperand(OpNum
).isReg()) {
975 O
<< "[" << TRI
->getAsmName(MI
->getOperand(OpNum
).getReg()) << "]";
979 case 'c': // Don't print "#" before an immediate operand.
980 if (!MI
->getOperand(OpNum
).isImm())
982 printNoHashImmediate(MI
, OpNum
);
984 case 'P': // Print a VFP double precision register.
985 printOperand(MI
, OpNum
);
988 if (TM
.getTargetData()->isLittleEndian())
992 if (TM
.getTargetData()->isBigEndian())
995 case 'H': // Write second word of DI / DF reference.
996 // Verify that this operand has two consecutive registers.
997 if (!MI
->getOperand(OpNum
).isReg() ||
998 OpNum
+1 == MI
->getNumOperands() ||
999 !MI
->getOperand(OpNum
+1).isReg())
1001 ++OpNum
; // Return the high-part.
1005 printOperand(MI
, OpNum
);
1009 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
1010 unsigned OpNum
, unsigned AsmVariant
,
1011 const char *ExtraCode
) {
1012 if (ExtraCode
&& ExtraCode
[0])
1013 return true; // Unknown modifier.
1014 printAddrMode2Operand(MI
, OpNum
);
1018 void ARMAsmPrinter::printMachineInstruction(const MachineInstr
*MI
) {
1021 int Opc
= MI
->getOpcode();
1023 case ARM::CONSTPOOL_ENTRY
:
1024 if (!InCPMode
&& AFI
->isThumbFunction()) {
1030 if (InCPMode
&& AFI
->isThumbFunction())
1034 // Call the autogenerated instruction printer routines.
1035 processDebugLoc(MI
->getDebugLoc());
1036 printInstruction(MI
);
1037 if (VerboseAsm
&& !MI
->getDebugLoc().isUnknown())
1042 bool ARMAsmPrinter::doInitialization(Module
&M
) {
1044 bool Result
= AsmPrinter::doInitialization(M
);
1045 DW
= getAnalysisIfAvailable
<DwarfWriter
>();
1047 // Use unified assembler syntax mode for Thumb.
1048 if (Subtarget
->isThumb())
1049 O
<< "\t.syntax unified\n";
1051 // Emit ARM Build Attributes
1052 if (Subtarget
->isTargetELF()) {
1054 std::string CPUString
= Subtarget
->getCPUString();
1055 if (CPUString
!= "generic")
1056 O
<< "\t.cpu " << CPUString
<< '\n';
1058 // FIXME: Emit FPU type
1059 if (Subtarget
->hasVFP2())
1060 O
<< "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch
<< ", 2\n";
1062 // Signal various FP modes.
1064 O
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal
<< ", 1\n"
1065 << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions
<< ", 1\n";
1067 if (FiniteOnlyFPMath())
1068 O
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model
<< ", 1\n";
1070 O
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model
<< ", 3\n";
1072 // 8-bytes alignment stuff.
1073 O
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed
<< ", 1\n"
1074 << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved
<< ", 1\n";
1076 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
1077 if (Subtarget
->isAAPCS_ABI() && FloatABIType
== FloatABI::Hard
)
1078 O
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use
<< ", 3\n"
1079 << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args
<< ", 1\n";
1081 // FIXME: Should we signal R9 usage?
1087 void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable
* GVar
) {
1088 const TargetData
*TD
= TM
.getTargetData();
1090 if (!GVar
->hasInitializer()) // External global require no code
1093 // Check to see if this is a special global used by LLVM, if so, emit it.
1095 if (EmitSpecialLLVMGlobal(GVar
)) {
1096 if (Subtarget
->isTargetDarwin() &&
1097 TM
.getRelocationModel() == Reloc::Static
) {
1098 if (GVar
->getName() == "llvm.global_ctors")
1099 O
<< ".reference .constructors_used\n";
1100 else if (GVar
->getName() == "llvm.global_dtors")
1101 O
<< ".reference .destructors_used\n";
1106 std::string name
= Mang
->getMangledName(GVar
);
1107 Constant
*C
= GVar
->getInitializer();
1108 const Type
*Type
= C
->getType();
1109 unsigned Size
= TD
->getTypeAllocSize(Type
);
1110 unsigned Align
= TD
->getPreferredAlignmentLog(GVar
);
1111 bool isDarwin
= Subtarget
->isTargetDarwin();
1113 printVisibility(name
, GVar
->getVisibility());
1115 if (Subtarget
->isTargetELF())
1116 O
<< "\t.type " << name
<< ",%object\n";
1118 const MCSection
*TheSection
=
1119 getObjFileLowering().SectionForGlobal(GVar
, Mang
, TM
);
1120 OutStreamer
.SwitchSection(TheSection
);
1122 // FIXME: get this stuff from section kind flags.
1123 if (C
->isNullValue() && !GVar
->hasSection() && !GVar
->isThreadLocal() &&
1124 // Don't put things that should go in the cstring section into "comm".
1125 !TheSection
->getKind().isMergeableCString()) {
1126 if (GVar
->hasExternalLinkage()) {
1127 if (const char *Directive
= MAI
->getZeroFillDirective()) {
1128 O
<< "\t.globl\t" << name
<< "\n";
1129 O
<< Directive
<< "__DATA, __common, " << name
<< ", "
1130 << Size
<< ", " << Align
<< "\n";
1135 if (GVar
->hasLocalLinkage() || GVar
->isWeakForLinker()) {
1136 if (Size
== 0) Size
= 1; // .comm Foo, 0 is undefined, avoid it.
1139 if (GVar
->hasLocalLinkage()) {
1140 O
<< MAI
->getLCOMMDirective() << name
<< "," << Size
1142 } else if (GVar
->hasCommonLinkage()) {
1143 O
<< MAI
->getCOMMDirective() << name
<< "," << Size
1146 OutStreamer
.SwitchSection(TheSection
);
1147 O
<< "\t.globl " << name
<< '\n'
1148 << MAI
->getWeakDefDirective() << name
<< '\n';
1149 EmitAlignment(Align
, GVar
);
1152 O
<< "\t\t\t\t" << MAI
->getCommentString() << ' ';
1153 WriteAsOperand(O
, GVar
, /*PrintType=*/false, GVar
->getParent());
1156 EmitGlobalConstant(C
);
1159 } else if (MAI
->getLCOMMDirective() != NULL
) {
1160 if (GVar
->hasLocalLinkage()) {
1161 O
<< MAI
->getLCOMMDirective() << name
<< "," << Size
;
1163 O
<< MAI
->getCOMMDirective() << name
<< "," << Size
;
1164 if (MAI
->getCOMMDirectiveTakesAlignment())
1165 O
<< ',' << (MAI
->getAlignmentIsInBytes() ? (1 << Align
) : Align
);
1168 if (GVar
->hasLocalLinkage())
1169 O
<< "\t.local\t" << name
<< "\n";
1170 O
<< MAI
->getCOMMDirective() << name
<< "," << Size
;
1171 if (MAI
->getCOMMDirectiveTakesAlignment())
1172 O
<< "," << (MAI
->getAlignmentIsInBytes() ? (1 << Align
) : Align
);
1175 O
<< "\t\t" << MAI
->getCommentString() << " ";
1176 WriteAsOperand(O
, GVar
, /*PrintType=*/false, GVar
->getParent());
1183 switch (GVar
->getLinkage()) {
1184 case GlobalValue::CommonLinkage
:
1185 case GlobalValue::LinkOnceAnyLinkage
:
1186 case GlobalValue::LinkOnceODRLinkage
:
1187 case GlobalValue::WeakAnyLinkage
:
1188 case GlobalValue::WeakODRLinkage
:
1189 case GlobalValue::LinkerPrivateLinkage
:
1191 O
<< "\t.globl " << name
<< "\n"
1192 << "\t.weak_definition " << name
<< "\n";
1194 O
<< "\t.weak " << name
<< "\n";
1197 case GlobalValue::AppendingLinkage
:
1198 // FIXME: appending linkage variables should go into a section of
1199 // their name or something. For now, just emit them as external.
1200 case GlobalValue::ExternalLinkage
:
1201 O
<< "\t.globl " << name
<< "\n";
1203 case GlobalValue::PrivateLinkage
:
1204 case GlobalValue::InternalLinkage
:
1207 llvm_unreachable("Unknown linkage type!");
1210 EmitAlignment(Align
, GVar
);
1213 O
<< "\t\t\t\t" << MAI
->getCommentString() << " ";
1214 WriteAsOperand(O
, GVar
, /*PrintType=*/false, GVar
->getParent());
1217 if (MAI
->hasDotTypeDotSizeDirective())
1218 O
<< "\t.size " << name
<< ", " << Size
<< "\n";
1220 EmitGlobalConstant(C
);
1225 bool ARMAsmPrinter::doFinalization(Module
&M
) {
1226 if (Subtarget
->isTargetDarwin()) {
1227 // All darwin targets use mach-o.
1228 TargetLoweringObjectFileMachO
&TLOFMacho
=
1229 static_cast<TargetLoweringObjectFileMachO
&>(getObjFileLowering());
1233 // Output non-lazy-pointers for external and common global variables.
1234 if (!GVNonLazyPtrs
.empty()) {
1235 // Switch with ".non_lazy_symbol_pointer" directive.
1236 OutStreamer
.SwitchSection(TLOFMacho
.getNonLazySymbolPointerSection());
1238 for (StringMap
<std::string
>::iterator I
= GVNonLazyPtrs
.begin(),
1239 E
= GVNonLazyPtrs
.end(); I
!= E
; ++I
) {
1240 O
<< I
->second
<< ":\n";
1241 O
<< "\t.indirect_symbol " << I
->getKeyData() << "\n";
1242 O
<< "\t.long\t0\n";
1246 if (!HiddenGVNonLazyPtrs
.empty()) {
1247 OutStreamer
.SwitchSection(getObjFileLowering().getDataSection());
1249 for (StringMap
<std::string
>::iterator I
= HiddenGVNonLazyPtrs
.begin(),
1250 E
= HiddenGVNonLazyPtrs
.end(); I
!= E
; ++I
) {
1251 O
<< I
->second
<< ":\n";
1252 O
<< "\t.long " << I
->getKeyData() << "\n";
1256 // Funny Darwin hack: This flag tells the linker that no global symbols
1257 // contain code that falls through to other global symbols (e.g. the obvious
1258 // implementation of multiple entry points). If this doesn't occur, the
1259 // linker can safely perform dead code stripping. Since LLVM never
1260 // generates code that does this, it is always safe to set.
1261 O
<< "\t.subsections_via_symbols\n";
1264 return AsmPrinter::doFinalization(M
);
1267 // Force static initialization.
1268 extern "C" void LLVMInitializeARMAsmPrinter() {
1269 RegisterAsmPrinter
<ARMAsmPrinter
> X(TheARMTarget
);
1270 RegisterAsmPrinter
<ARMAsmPrinter
> Y(TheThumbTarget
);