1 //===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to NVPTX assembly language.
13 //===----------------------------------------------------------------------===//
15 #ifndef NVPTXASMPRINTER_H
16 #define NVPTXASMPRINTER_H
19 #include "NVPTXSubtarget.h"
20 #include "NVPTXTargetMachine.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/CodeGen/AsmPrinter.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCExpr.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/FormattedStream.h"
30 #include "llvm/Target/Mangler.h"
31 #include "llvm/Target/TargetMachine.h"
34 // The ptx syntax and format is very different from that usually seem in a .s
36 // therefore we are not able to use the MCAsmStreamer interface here.
38 // We are handcrafting the output method here.
40 // A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
41 // (subclass of MCStreamer).
43 // This is defined in AsmPrinter.cpp.
44 // Used to process the constant expressions in initializers.
46 const llvm::MCExpr
*LowerConstant(const llvm::Constant
*CV
,
47 llvm::AsmPrinter
&AP
) ;
57 std::string theFileName
;
58 SmallVector
<unsigned, 32> lineOffset
;
60 LineReader(std::string filename
) {
62 fstr
.open(filename
.c_str());
63 theFileName
= filename
;
65 std::string
fileName() { return theFileName
; }
69 std::string
readLine(unsigned line
);
74 class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter
: public AsmPrinter
{
78 // Used to buffer the emitted string for initializing global
81 // Normally an aggregate (array, vector or structure) is emitted
82 // as a u8[]. However, if one element/field of the aggregate
83 // is a non-NULL address, then the aggregate is emitted as u32[]
86 // We first layout the aggregate in 'buffer' in bytes, except for
87 // those symbol addresses. For the i-th symbol address in the
88 //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
89 // are filled with 0s. symbolPosInBuffer[i-1] records its position
90 // in 'buffer', and Symbols[i-1] records the Value*.
92 // Once we have this AggBuffer setup, we can choose how to print
95 unsigned size
; // size of the buffer in bytes
96 unsigned char *buffer
; // the buffer
97 unsigned numSymbols
; // number of symbol addresses
98 SmallVector
<unsigned, 4> symbolPosInBuffer
;
99 SmallVector
<Value
*, 4> Symbols
;
107 AggBuffer(unsigned _size
, raw_ostream
&_O
, NVPTXAsmPrinter
&_AP
)
109 buffer
= new unsigned char[_size
];
117 unsigned addBytes(unsigned char *Ptr
, int Num
, int Bytes
) {
118 assert((curpos
+Num
) <= size
);
119 assert((curpos
+Bytes
) <= size
);
120 for ( int i
= 0; i
< Num
; ++i
) {
121 buffer
[curpos
] = Ptr
[i
];
124 for ( int i
=Num
; i
< Bytes
; ++i
) {
130 unsigned addZeros(int Num
) {
131 assert((curpos
+Num
) <= size
);
132 for ( int i
= 0; i
< Num
; ++i
) {
138 void addSymbol(Value
*GVar
) {
139 symbolPosInBuffer
.push_back(curpos
);
140 Symbols
.push_back(GVar
);
144 if (numSymbols
== 0) {
145 // print out in bytes
146 for (unsigned i
=0; i
<size
; i
++) {
149 O
<< (unsigned int)buffer
[i
];
152 // print out in 4-bytes or 8-bytes
153 unsigned int pos
= 0;
154 unsigned int nSym
= 0;
155 unsigned int nextSymbolPos
= symbolPosInBuffer
[nSym
];
156 unsigned int nBytes
= 4;
157 if (AP
.nvptxSubtarget
.is64Bit())
159 for (pos
=0; pos
<size
; pos
+=nBytes
) {
162 if (pos
== nextSymbolPos
) {
163 Value
*v
= Symbols
[nSym
];
164 if (GlobalValue
*GVar
= dyn_cast
<GlobalValue
>(v
)) {
165 MCSymbol
*Name
= AP
.Mang
->getSymbol(GVar
);
168 else if (ConstantExpr
*Cexpr
=
169 dyn_cast
<ConstantExpr
>(v
)) {
170 O
<< *nvptx::LowerConstant(Cexpr
, AP
);
172 llvm_unreachable("symbol type unknown");
174 if (nSym
>= numSymbols
)
175 nextSymbolPos
= size
+1;
177 nextSymbolPos
= symbolPosInBuffer
[nSym
];
180 O
<< *(unsigned int*)(buffer
+pos
);
182 O
<< *(unsigned long long*)(buffer
+pos
);
188 friend class AggBuffer
;
190 virtual void emitSrcInText(StringRef filename
, unsigned line
);
193 virtual const char *getPassName() const {
194 return "NVPTX Assembly Printer";
198 std::string CurrentFnName
;
200 void EmitFunctionEntryLabel();
201 void EmitFunctionBodyStart();
202 void EmitFunctionBodyEnd();
204 void EmitInstruction(const MachineInstr
*);
206 void EmitAlignment(unsigned NumBits
, const GlobalValue
*GV
= 0) const {}
208 void printGlobalVariable(const GlobalVariable
*GVar
);
209 void printOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
210 const char *Modifier
=0);
211 void printLdStCode(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
212 const char *Modifier
=0);
213 void printVecModifiedImmediate(const MachineOperand
&MO
,
214 const char *Modifier
, raw_ostream
&O
);
215 void printMemOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
216 const char *Modifier
=0);
217 void printImplicitDef(const MachineInstr
*MI
, raw_ostream
&O
) const;
218 // definition autogenerated.
219 void printInstruction(const MachineInstr
*MI
, raw_ostream
&O
);
220 void printModuleLevelGV(GlobalVariable
* GVar
, raw_ostream
&O
,
222 void printParamName(int paramIndex
, raw_ostream
&O
);
223 void printParamName(Function::const_arg_iterator I
, int paramIndex
,
225 void emitHeader(Module
&M
, raw_ostream
&O
);
226 void emitKernelFunctionDirectives(const Function
& F
,
227 raw_ostream
&O
) const;
228 void emitVirtualRegister(unsigned int vr
, bool isVec
, raw_ostream
&O
);
229 void emitFunctionExternParamList(const MachineFunction
&MF
);
230 void emitFunctionParamList(const Function
*, raw_ostream
&O
);
231 void emitFunctionParamList(const MachineFunction
&MF
, raw_ostream
&O
);
232 void setAndEmitFunctionVirtualRegisters(const MachineFunction
&MF
);
233 void emitFunctionTempData(const MachineFunction
&MF
,
234 unsigned &FrameSize
);
235 bool isImageType(const Type
*Ty
);
236 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
237 unsigned AsmVariant
, const char *ExtraCode
,
239 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
240 unsigned AsmVariant
, const char *ExtraCode
,
242 void printReturnValStr(const Function
*, raw_ostream
&O
);
243 void printReturnValStr(const MachineFunction
&MF
, raw_ostream
&O
);
246 bool doInitialization(Module
&M
);
247 bool doFinalization(Module
&M
);
250 std::string CurrentBankselLabelInBasicBlock
;
252 // This is specific per MachineFunction.
253 const MachineRegisterInfo
*MRI
;
254 // The contents are specific for each
255 // MachineFunction. But the size of the
257 std::map
<unsigned, unsigned> *VRidGlobal2LocalMap
;
258 // cache the subtarget here.
259 const NVPTXSubtarget
&nvptxSubtarget
;
260 // Build the map between type name and ID based on module's type
262 std::map
<const Type
*, std::string
> TypeNameMap
;
264 // List of variables demoted to a function scope.
265 std::map
<const Function
*, std::vector
<GlobalVariable
*> > localDecls
;
267 // To record filename to ID mapping
268 std::map
<std::string
, unsigned> filenameMap
;
269 void recordAndEmitFilenames(Module
&);
271 void emitPTXGlobalVariable(const GlobalVariable
*GVar
, raw_ostream
&O
);
272 void emitPTXAddressSpace(unsigned int AddressSpace
,
273 raw_ostream
&O
) const;
274 std::string
getPTXFundamentalTypeStr(const Type
*Ty
, bool=true) const ;
275 void printScalarConstant(Constant
*CPV
, raw_ostream
&O
) ;
276 void printFPConstant(const ConstantFP
*Fp
, raw_ostream
&O
) ;
277 void bufferLEByte(Constant
*CPV
, int Bytes
, AggBuffer
*aggBuffer
) ;
278 void bufferAggregateConstant(Constant
*CV
, AggBuffer
*aggBuffer
) ;
280 void printOperandProper(const MachineOperand
&MO
);
282 void emitLinkageDirective(const GlobalValue
* V
, raw_ostream
&O
);
283 void emitDeclarations(Module
&, raw_ostream
&O
);
284 void emitDeclaration(const Function
*, raw_ostream
&O
);
286 static const char *getRegisterName(unsigned RegNo
);
287 void emitDemotedVars(const Function
*, raw_ostream
&);
290 LineReader
*getReader(std::string
);
292 NVPTXAsmPrinter(TargetMachine
&TM
,
293 MCStreamer
&Streamer
)
294 : AsmPrinter(TM
, Streamer
),
295 nvptxSubtarget(TM
.getSubtarget
<NVPTXSubtarget
>()) {
296 CurrentBankselLabelInBasicBlock
= "";
297 VRidGlobal2LocalMap
= NULL
;
306 bool ignoreLoc(const MachineInstr
&);
308 virtual void getVirtualRegisterName(unsigned, bool, raw_ostream
&);
310 DebugLoc prevDebugLoc
;
311 void emitLineNumberAsDotLoc(const MachineInstr
&);
313 } // end of namespace