llvm.org GIT mirror llvm / cf0b01d
[lanai] Add Lanai backend. Add the Lanai backend to lib/Target. General Lanai backend discussion on llvm-dev thread "[RFC] Lanai backend" (http://lists.llvm.org/pipermail/llvm-dev/2016-February/095118.html). Differential Revision: http://reviews.llvm.org/D17011 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264578 91177308-0d34-0410-b5e6-96231b3b80d8 Jacques Pienaar 2 years ago
87 changed file(s) with 12430 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
141141 E: kparzysz@codeaurora.org
142142 D: Hexagon Backend
143143
144 N: Jacques Pienaar
145 E: jpienaar@google.com
146 D: Lanai Backend
147
144148 N: Paul Robinson
145149 E: paul_robinson@playstation.sony.com
146150 D: Sony PlayStation®4 support
193193 ECase(EM_78KOR)
194194 ECase(EM_56800EX)
195195 ECase(EM_AMDGPU)
196 ECase(EM_LANAI)
196197 #undef ECase
197198 }
198199
526527 case ELF::EM_ARM:
527528 #include "llvm/Support/ELFRelocs/ARM.def"
528529 break;
530 case ELF::EM_LANAI:
531 #include "llvm/Support/ELFRelocs/Lanai.def"
532 break;
529533 default:
530534 llvm_unreachable("Unsupported architecture");
531535 }
2424 AVR
2525 BPF
2626 CppBackend
27 Lanai
2728 Hexagon
2829 MSP430
2930 NVPTX
0 include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
1
2 add_llvm_library(LLVMLanaiAsmParser
3 LanaiAsmParser.cpp
4 )
5
6 add_dependencies( LLVMLanaiAsmParser LanaiCommonTableGen )
0 ;===- ./lib/Target/Lanai/AsmParser/LLVMBuild.txt ----------------*- Conf -*-===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = LanaiAsmParser
20 parent = Lanai
21 required_libraries = MC MCParser Support LanaiMCTargetDesc LanaiInfo
22 add_to_library_groups = Lanai
0 //===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Lanai.h"
10 #include "MCTargetDesc/LanaiMCExpr.h"
11 #include "MCTargetDesc/LanaiMCTargetDesc.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/Support/MathExtras.h"
23 #include "llvm/Support/TargetRegistry.h"
24
25 namespace llvm {
26 namespace {
27 struct LanaiOperand;
28
29 class LanaiAsmParser : public MCTargetAsmParser {
30 // Parse operands
31 std::unique_ptr parseRegister();
32
33 std::unique_ptr parseImmediate();
34
35 std::unique_ptr parseIdentifier();
36
37 unsigned parseAluOperator(bool PreOp, bool PostOp);
38
39 // Split the mnemonic stripping conditional code and quantifiers
40 StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
41 OperandVector *Operands);
42
43 bool parsePrePost(StringRef Type, int *OffsetValue);
44
45 bool ParseDirective(AsmToken DirectiveID) override;
46
47 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
48 SMLoc NameLoc, OperandVector &Operands) override;
49
50 bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
51
52 bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
53 OperandVector &Operands, MCStreamer &Out,
54 uint64_t &ErrorInfo,
55 bool MatchingInlineAsm) override;
56
57 // Auto-generated instruction matching functions
58 #define GET_ASSEMBLER_HEADER
59 #include "LanaiGenAsmMatcher.inc"
60
61 OperandMatchResultTy parseOperand(OperandVector *Operands,
62 StringRef Mnemonic);
63
64 OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
65
66 public:
67 LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
68 const MCInstrInfo &MII, const MCTargetOptions &Options)
69 : MCTargetAsmParser(Options, STI), Parser(Parser),
70 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
71 setAvailableFeatures(
72 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
73 }
74
75 private:
76 MCAsmParser &Parser;
77 MCAsmLexer &Lexer;
78
79 const MCSubtargetInfo &SubtargetInfo;
80 };
81
82 // Auto-generated by TableGen
83 static unsigned MatchRegisterName(llvm::StringRef Name);
84
85 // LanaiOperand - Instances of this class represented a parsed machine
86 // instruction
87 struct LanaiOperand : public MCParsedAsmOperand {
88 enum KindTy {
89 TOKEN,
90 REGISTER,
91 IMMEDIATE,
92 MEMORY_IMM,
93 MEMORY_REG_IMM,
94 MEMORY_REG_REG,
95 } Kind;
96
97 SMLoc StartLoc, EndLoc;
98
99 struct Token {
100 const char *Data;
101 unsigned Length;
102 };
103
104 struct RegOp {
105 unsigned RegNum;
106 };
107
108 struct ImmOp {
109 const MCExpr *Value;
110 };
111
112 struct MemOp {
113 unsigned BaseReg;
114 unsigned OffsetReg;
115 unsigned AluOp;
116 const MCExpr *Offset;
117 };
118
119 union {
120 struct Token Tok;
121 struct RegOp Reg;
122 struct ImmOp Imm;
123 struct MemOp Mem;
124 };
125
126 explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}
127
128 public:
129 // The functions below are used by the autogenerated ASM matcher and hence to
130 // be of the form expected.
131
132 // getStartLoc - Gets location of the first token of this operand
133 SMLoc getStartLoc() const override { return StartLoc; }
134
135 // getEndLoc - Gets location of the last token of this operand
136 SMLoc getEndLoc() const override { return EndLoc; }
137
138 unsigned getReg() const override {
139 assert(isReg() && "Invalid type access!");
140 return Reg.RegNum;
141 }
142
143 const MCExpr *getImm() const {
144 assert(isImm() && "Invalid type access!");
145 return Imm.Value;
146 }
147
148 StringRef getToken() const {
149 assert(isToken() && "Invalid type access!");
150 return StringRef(Tok.Data, Tok.Length);
151 }
152
153 unsigned getMemBaseReg() const {
154 assert(isMem() && "Invalid type access!");
155 return Mem.BaseReg;
156 }
157
158 unsigned getMemOffsetReg() const {
159 assert(isMem() && "Invalid type access!");
160 return Mem.OffsetReg;
161 }
162
163 const MCExpr *getMemOffset() const {
164 assert(isMem() && "Invalid type access!");
165 return Mem.Offset;
166 }
167
168 unsigned getMemOp() const {
169 assert(isMem() && "Invalid type access!");
170 return Mem.AluOp;
171 }
172
173 // Functions for testing operand type
174 bool isReg() const override { return Kind == REGISTER; }
175
176 bool isImm() const override { return Kind == IMMEDIATE; }
177
178 bool isMem() const override {
179 return isMemImm() || isMemRegImm() || isMemRegReg();
180 }
181
182 bool isMemImm() const { return Kind == MEMORY_IMM; }
183
184 bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
185
186 bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
187
188 bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
189
190 bool isToken() const override { return Kind == TOKEN; }
191
192 bool isBrImm() {
193 if (!isImm())
194 return false;
195
196 // Constant case
197 if (const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value)) {
198 int64_t Value = ConstExpr->getValue();
199 // Check if value fits in 25 bits with 2 least significant bits 0.
200 return isShiftedUInt<23, 2>(static_cast(Value));
201 }
202
203 // Symbolic reference expression
204 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Imm.Value))
205 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
206
207 // Binary expression
208 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Imm.Value))
209 if (const LanaiMCExpr *SymbolRefExpr =
210 dyn_cast(BinaryExpr->getLHS()))
211 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
212
213 return false;
214 }
215
216 bool isBrTarget() { return isBrImm() || isToken(); }
217
218 bool isCallTarget() { return isImm() || isToken(); }
219
220 bool isHiImm16() {
221 if (!isImm())
222 return false;
223
224 // Constant case
225 if (const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value)) {
226 int64_t Value = ConstExpr->getValue();
227 return Value != 0 && isShiftedUInt<16, 16>(Value);
228 }
229
230 // Symbolic reference expression
231 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Imm.Value))
232 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
233
234 // Binary expression
235 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Imm.Value))
236 if (const LanaiMCExpr *SymbolRefExpr =
237 dyn_cast(BinaryExpr->getLHS()))
238 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
239
240 return false;
241 }
242
243 bool isHiImm16And() {
244 if (!isImm())
245 return false;
246
247 const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value);
248 if (ConstExpr) {
249 int64_t Value = ConstExpr->getValue();
250 // Check if in the form 0xXYZWffff
251 return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
252 }
253 return false;
254 }
255
256 bool isLoImm16() {
257 if (!isImm())
258 return false;
259
260 // Constant case
261 if (const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value)) {
262 int64_t Value = ConstExpr->getValue();
263 // Check if value fits in 16 bits
264 return isUInt<16>(static_cast(Value));
265 }
266
267 // Symbolic reference expression
268 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Imm.Value))
269 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
270
271 // Binary expression
272 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Imm.Value))
273 if (const LanaiMCExpr *SymbolRefExpr =
274 dyn_cast(BinaryExpr->getLHS()))
275 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
276
277 return false;
278 }
279
280 bool isLoImm16Signed() {
281 if (!isImm())
282 return false;
283
284 // Constant case
285 if (const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value)) {
286 int64_t Value = ConstExpr->getValue();
287 // Check if value fits in 16 bits or value of the form 0xffffxyzw
288 return isInt<16>(static_cast(Value));
289 }
290
291 // Symbolic reference expression
292 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Imm.Value))
293 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
294
295 // Binary expression
296 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Imm.Value))
297 if (const LanaiMCExpr *SymbolRefExpr =
298 dyn_cast(BinaryExpr->getLHS()))
299 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
300
301 return false;
302 }
303
304 bool isLoImm16And() {
305 if (!isImm())
306 return false;
307
308 const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value);
309 if (ConstExpr) {
310 int64_t Value = ConstExpr->getValue();
311 // Check if in the form 0xffffXYZW
312 return ((Value & ~0xffff) == 0xffff0000);
313 }
314 return false;
315 }
316
317 bool isImmShift() {
318 if (!isImm())
319 return false;
320
321 const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value);
322 if (!ConstExpr)
323 return false;
324 int64_t Value = ConstExpr->getValue();
325 return (Value >= -31) && (Value <= 31);
326 }
327
328 bool isLoImm21() {
329 if (!isImm())
330 return false;
331
332 // Constant case
333 if (const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value)) {
334 int64_t Value = ConstExpr->getValue();
335 return isUInt<21>(Value);
336 }
337
338 // Symbolic reference expression
339 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Imm.Value))
340 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
341 if (const MCSymbolRefExpr *SymbolRefExpr =
342 dyn_cast(Imm.Value)) {
343 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
344 }
345
346 // Binary expression
347 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Imm.Value)) {
348 if (const LanaiMCExpr *SymbolRefExpr =
349 dyn_cast(BinaryExpr->getLHS()))
350 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
351 if (const MCSymbolRefExpr *SymbolRefExpr =
352 dyn_cast(BinaryExpr->getLHS()))
353 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
354 }
355
356 return false;
357 }
358
359 bool isImm10() {
360 if (!isImm())
361 return false;
362
363 const MCConstantExpr *ConstExpr = dyn_cast(Imm.Value);
364 if (!ConstExpr)
365 return false;
366 int64_t Value = ConstExpr->getValue();
367 return isInt<10>(Value);
368 }
369
370 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
371 // Add as immediates where possible. Null MCExpr = 0
372 if (Expr == nullptr)
373 Inst.addOperand(MCOperand::createImm(0));
374 else if (const MCConstantExpr *ConstExpr = dyn_cast(Expr))
375 Inst.addOperand(
376 MCOperand::createImm(static_cast(ConstExpr->getValue())));
377 else
378 Inst.addOperand(MCOperand::createExpr(Expr));
379 }
380
381 void addRegOperands(MCInst &Inst, unsigned N) const {
382 assert(N == 1 && "Invalid number of operands!");
383 Inst.addOperand(MCOperand::createReg(getReg()));
384 }
385
386 void addImmOperands(MCInst &Inst, unsigned N) const {
387 assert(N == 1 && "Invalid number of operands!");
388 addExpr(Inst, getImm());
389 }
390
391 void addBrTargetOperands(MCInst &Inst, unsigned N) const {
392 assert(N == 1 && "Invalid number of operands!");
393 addExpr(Inst, getImm());
394 }
395
396 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
397 assert(N == 1 && "Invalid number of operands!");
398 addExpr(Inst, getImm());
399 }
400
401 void addMemImmOperands(MCInst &Inst, unsigned N) const {
402 assert(N == 1 && "Invalid number of operands!");
403 const MCExpr *Expr = getMemOffset();
404 addExpr(Inst, Expr);
405 }
406
407 void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
408 assert(N == 3 && "Invalid number of operands!");
409 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
410 const MCExpr *Expr = getMemOffset();
411 addExpr(Inst, Expr);
412 Inst.addOperand(MCOperand::createImm(getMemOp()));
413 }
414
415 void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
416 assert(N == 3 && "Invalid number of operands!");
417 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
418 assert(getMemOffsetReg() != 0 && "Invalid offset");
419 Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
420 Inst.addOperand(MCOperand::createImm(getMemOp()));
421 }
422
423 void addMemSplsOperands(MCInst &Inst, unsigned N) const {
424 if (isMemRegImm())
425 addMemRegImmOperands(Inst, N);
426 if (isMemRegReg())
427 addMemRegRegOperands(Inst, N);
428 }
429
430 void addImmShiftOperands(MCInst &Inst, unsigned N) const {
431 assert(N == 1 && "Invalid number of operands!");
432 addExpr(Inst, getImm());
433 }
434
435 void addImm10Operands(MCInst &Inst, unsigned N) const {
436 assert(N == 1 && "Invalid number of operands!");
437 addExpr(Inst, getImm());
438 }
439
440 void addLoImm16Operands(MCInst &Inst, unsigned N) const {
441 assert(N == 1 && "Invalid number of operands!");
442 if (const MCConstantExpr *ConstExpr = dyn_cast(getImm()))
443 Inst.addOperand(
444 MCOperand::createImm(static_cast(ConstExpr->getValue())));
445 else if (isa(getImm())) {
446 #ifndef NDEBUG
447 const LanaiMCExpr *SymbolRefExpr = dyn_cast(getImm());
448 assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
449 #endif
450 Inst.addOperand(MCOperand::createExpr(getImm()));
451 } else if (isa(getImm())) {
452 #ifndef NDEBUG
453 const MCBinaryExpr *BinaryExpr = dyn_cast(getImm());
454 assert(dyn_cast(BinaryExpr->getLHS()) &&
455 dyn_cast(BinaryExpr->getLHS())->getKind() ==
456 LanaiMCExpr::VK_Lanai_ABS_LO);
457 #endif
458 Inst.addOperand(MCOperand::createExpr(getImm()));
459 } else
460 assert(false && "Operand type not supported.");
461 }
462
463 void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
464 assert(N == 1 && "Invalid number of operands!");
465 if (const MCConstantExpr *ConstExpr = dyn_cast(getImm()))
466 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
467 else
468 assert(false && "Operand type not supported.");
469 }
470
471 void addHiImm16Operands(MCInst &Inst, unsigned N) const {
472 assert(N == 1 && "Invalid number of operands!");
473 if (const MCConstantExpr *ConstExpr = dyn_cast(getImm()))
474 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
475 else if (isa(getImm())) {
476 #ifndef NDEBUG
477 const LanaiMCExpr *SymbolRefExpr = dyn_cast(getImm());
478 assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
479 #endif
480 Inst.addOperand(MCOperand::createExpr(getImm()));
481 } else if (isa(getImm())) {
482 #ifndef NDEBUG
483 const MCBinaryExpr *BinaryExpr = dyn_cast(getImm());
484 assert(dyn_cast(BinaryExpr->getLHS()) &&
485 dyn_cast(BinaryExpr->getLHS())->getKind() ==
486 LanaiMCExpr::VK_Lanai_ABS_HI);
487 #endif
488 Inst.addOperand(MCOperand::createExpr(getImm()));
489 } else
490 assert(false && "Operand type not supported.");
491 }
492
493 void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
494 assert(N == 1 && "Invalid number of operands!");
495 if (const MCConstantExpr *ConstExpr = dyn_cast(getImm()))
496 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
497 else
498 assert(false && "Operand type not supported.");
499 }
500
501 void addLoImm21Operands(MCInst &Inst, unsigned N) const {
502 assert(N == 1 && "Invalid number of operands!");
503 if (const MCConstantExpr *ConstExpr = dyn_cast(getImm()))
504 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
505 else if (isa(getImm())) {
506 #ifndef NDEBUG
507 const LanaiMCExpr *SymbolRefExpr = dyn_cast(getImm());
508 assert(SymbolRefExpr &&
509 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
510 #endif
511 Inst.addOperand(MCOperand::createExpr(getImm()));
512 } else if (isa(getImm())) {
513 #ifndef NDEBUG
514 const MCSymbolRefExpr *SymbolRefExpr =
515 dyn_cast(getImm());
516 assert(SymbolRefExpr &&
517 SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
518 #endif
519 Inst.addOperand(MCOperand::createExpr(getImm()));
520 } else if (isa(getImm())) {
521 #ifndef NDEBUG
522 const MCBinaryExpr *BinaryExpr = dyn_cast(getImm());
523 const LanaiMCExpr *SymbolRefExpr =
524 dyn_cast(BinaryExpr->getLHS());
525 assert(SymbolRefExpr &&
526 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
527 #endif
528 Inst.addOperand(MCOperand::createExpr(getImm()));
529 } else
530 assert(false && "Operand type not supported.");
531 }
532
533 void print(raw_ostream &OS) const override {
534 switch (Kind) {
535 case IMMEDIATE:
536 OS << "Imm: " << getImm() << "\n";
537 break;
538 case TOKEN:
539 OS << "Token: " << getToken() << "\n";
540 break;
541 case REGISTER:
542 OS << "Reg: %r" << getReg() << "\n";
543 break;
544 case MEMORY_IMM:
545 OS << "MemImm: " << *getMemOffset() << "\n";
546 break;
547 case MEMORY_REG_IMM:
548 OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
549 break;
550 case MEMORY_REG_REG:
551 assert(getMemOffset() == nullptr);
552 OS << "MemRegReg: " << getMemBaseReg() << "+"
553 << "%r" << getMemOffsetReg() << "\n";
554 break;
555 }
556 }
557
558 static std::unique_ptr CreateToken(StringRef Str, SMLoc Start) {
559 auto Op = make_unique(TOKEN);
560 Op->Tok.Data = Str.data();
561 Op->Tok.Length = Str.size();
562 Op->StartLoc = Start;
563 Op->EndLoc = Start;
564 return Op;
565 }
566
567 static std::unique_ptr createReg(unsigned RegNum, SMLoc Start,
568 SMLoc End) {
569 auto Op = make_unique(REGISTER);
570 Op->Reg.RegNum = RegNum;
571 Op->StartLoc = Start;
572 Op->EndLoc = End;
573 return Op;
574 }
575
576 static std::unique_ptr createImm(const MCExpr *Value,
577 SMLoc Start, SMLoc End) {
578 auto Op = make_unique(IMMEDIATE);
579 Op->Imm.Value = Value;
580 Op->StartLoc = Start;
581 Op->EndLoc = End;
582 return Op;
583 }
584
585 static std::unique_ptr
586 MorphToMemImm(std::unique_ptr Op) {
587 const MCExpr *Imm = Op->getImm();
588 Op->Kind = MEMORY_IMM;
589 Op->Mem.BaseReg = 0;
590 Op->Mem.AluOp = LPAC::ADD;
591 Op->Mem.OffsetReg = 0;
592 Op->Mem.Offset = Imm;
593 return Op;
594 }
595
596 static std::unique_ptr
597 MorphToMemRegReg(unsigned BaseReg, std::unique_ptr Op,
598 unsigned AluOp) {
599 unsigned OffsetReg = Op->getReg();
600 Op->Kind = MEMORY_REG_REG;
601 Op->Mem.BaseReg = BaseReg;
602 Op->Mem.AluOp = AluOp;
603 Op->Mem.OffsetReg = OffsetReg;
604 Op->Mem.Offset = nullptr;
605 return Op;
606 }
607
608 static std::unique_ptr
609 MorphToMemRegImm(unsigned BaseReg, std::unique_ptr Op,
610 unsigned AluOp) {
611 const MCExpr *Imm = Op->getImm();
612 Op->Kind = MEMORY_REG_IMM;
613 Op->Mem.BaseReg = BaseReg;
614 Op->Mem.AluOp = AluOp;
615 Op->Mem.OffsetReg = 0;
616 Op->Mem.Offset = Imm;
617 return Op;
618 }
619 };
620
621 bool LanaiAsmParser::ParseDirective(AsmToken DirectiveId) { return true; }
622
623 bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
624 OperandVector &Operands,
625 MCStreamer &Out,
626 uint64_t &ErrorInfo,
627 bool MatchingInlineAsm) {
628 MCInst Inst;
629 SMLoc ErrorLoc;
630
631 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
632 case Match_Success:
633 Out.EmitInstruction(Inst, SubtargetInfo);
634 return false;
635 case Match_MissingFeature:
636 return Error(IdLoc, "Instruction use requires option to be enabled");
637 case Match_MnemonicFail:
638 return Error(IdLoc, "Unrecognized instruction mnemonic");
639 case Match_InvalidOperand: {
640 ErrorLoc = IdLoc;
641 if (ErrorInfo != ~0U) {
642 if (ErrorInfo >= Operands.size())
643 return Error(IdLoc, "Too few operands for instruction");
644
645 ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
646 if (ErrorLoc == SMLoc())
647 ErrorLoc = IdLoc;
648 }
649 return Error(ErrorLoc, "Invalid operand for instruction");
650 }
651 default:
652 break;
653 }
654
655 llvm_unreachable("Unknown match type detected!");
656 }
657
658 // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
659 // backwards compatible with GCC and the different ways inline assembly is
660 // handled.
661 // TODO: see if there isn't a better way to do this.
662 std::unique_ptr LanaiAsmParser::parseRegister() {
663 SMLoc Start = Parser.getTok().getLoc();
664 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
665
666 unsigned RegNum;
667 // Eat the '%'.
668 if (Lexer.getKind() == AsmToken::Percent)
669 Parser.Lex();
670 if (Lexer.getKind() == AsmToken::Identifier) {
671 RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
672 if (RegNum == 0)
673 return 0;
674 Parser.Lex(); // Eat identifier token
675 return LanaiOperand::createReg(RegNum, Start, End);
676 }
677 return 0;
678 }
679
680 bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
681 SMLoc &EndLoc) {
682 std::unique_ptr Op = parseRegister();
683 if (Op != 0)
684 RegNum = Op->getReg();
685 return (Op == 0);
686 }
687
688 std::unique_ptr LanaiAsmParser::parseIdentifier() {
689 SMLoc Start = Parser.getTok().getLoc();
690 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
691 const MCExpr *Res, *RHS = 0;
692 LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
693
694 if (Lexer.getKind() != AsmToken::Identifier)
695 return 0;
696
697 StringRef Identifier;
698 if (Parser.parseIdentifier(Identifier))
699 return 0;
700
701 // Check if identifier has a modifier
702 if (Identifier.equals_lower("hi"))
703 Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
704 else if (Identifier.equals_lower("lo"))
705 Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
706
707 // If the identifier corresponds to a variant then extract the real
708 // identifier.
709 if (Kind != LanaiMCExpr::VK_Lanai_None) {
710 if (Lexer.getKind() != AsmToken::LParen) {
711 Error(Lexer.getLoc(), "Expected '('");
712 return 0;
713 }
714 Lexer.Lex(); // lex '('
715
716 // Parse identifier
717 if (Parser.parseIdentifier(Identifier))
718 return 0;
719 }
720
721 // If addition parse the RHS.
722 if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
723 return 0;
724
725 // For variants parse the final ')'
726 if (Kind != LanaiMCExpr::VK_Lanai_None) {
727 if (Lexer.getKind() != AsmToken::RParen) {
728 Error(Lexer.getLoc(), "Expected ')'");
729 return 0;
730 }
731 Lexer.Lex(); // lex ')'
732 }
733
734 End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
735 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
736 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
737 Res = LanaiMCExpr::create(Kind, Expr, getContext());
738
739 // Nest if this was an addition
740 if (RHS)
741 Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
742
743 return LanaiOperand::createImm(Res, Start, End);
744 }
745
746 std::unique_ptr LanaiAsmParser::parseImmediate() {
747 SMLoc Start = Parser.getTok().getLoc();
748 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
749
750 const MCExpr *ExprVal;
751 switch (Lexer.getKind()) {
752 case AsmToken::Identifier:
753 return parseIdentifier();
754 case AsmToken::Plus:
755 case AsmToken::Minus:
756 case AsmToken::Integer:
757 case AsmToken::Dot:
758 if (!Parser.parseExpression(ExprVal))
759 return LanaiOperand::createImm(ExprVal, Start, End);
760 default:
761 return 0;
762 }
763 }
764
765 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
766 if (PreOp)
767 return LPAC::makePreOp(AluCode);
768 if (PostOp)
769 return LPAC::makePostOp(AluCode);
770 return AluCode;
771 }
772
773 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
774 StringRef IdString;
775 Parser.parseIdentifier(IdString);
776 unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
777 if (AluCode == LPAC::UNKNOWN) {
778 Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
779 return 0;
780 }
781 return AluCode;
782 }
783
784 static int SizeForSuffix(StringRef T) {
785 return StringSwitch(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
786 }
787
788 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
789 bool PreOrPost = false;
790 if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
791 PreOrPost = true;
792 if (Lexer.is(AsmToken::Minus))
793 *OffsetValue = -SizeForSuffix(Type);
794 else if (Lexer.is(AsmToken::Plus))
795 *OffsetValue = SizeForSuffix(Type);
796 else
797 return false;
798
799 // Eat the '-' '-' or '+' '+'
800 Parser.Lex();
801 Parser.Lex();
802 } else if (Lexer.is(AsmToken::Star)) {
803 Parser.Lex(); // Eat the '*'
804 PreOrPost = true;
805 }
806
807 return PreOrPost;
808 }
809
810 bool shouldBeSls(const LanaiOperand &Op) {
811 // The instruction should be encoded as an SLS if the constant is word
812 // aligned and will fit in 21 bits
813 if (const MCConstantExpr *ConstExpr = dyn_cast(Op.getImm())) {
814 int64_t Value = ConstExpr->getValue();
815 return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
816 }
817 // The instruction should be encoded as an SLS if the operand is a symbolic
818 // reference with no variant.
819 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast(Op.getImm()))
820 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
821 // The instruction should be encoded as an SLS if the operand is a binary
822 // expression with the left-hand side being a symbolic reference with no
823 // variant.
824 if (const MCBinaryExpr *BinaryExpr = dyn_cast(Op.getImm())) {
825 const LanaiMCExpr *LHSSymbolRefExpr =
826 dyn_cast(BinaryExpr->getLHS());
827 return (LHSSymbolRefExpr &&
828 LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
829 }
830 return false;
831 }
832
833 // Matches memory operand. Returns true if error encountered.
834 LanaiAsmParser::OperandMatchResultTy
835 LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
836 // Try to match a memory operand.
837 // The memory operands are of the form:
838 // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
839 // ^
840 // (2) '[' '*'? Register '*'? AluOperator Register ']'
841 // ^
842 // (3) '[' '--'|'++' Register '--'|'++' ']'
843 //
844 // (4) '[' Immediate ']' (for SLS)
845
846 // Store the type for use in parsing pre/post increment/decrement operators
847 StringRef Type;
848 if (Operands[0]->isToken())
849 Type = static_cast(Operands[0].get())->getToken();
850
851 // Use 0 if no offset given
852 int OffsetValue = 0;
853 unsigned BaseReg = 0;
854 unsigned AluOp = LPAC::ADD;
855 bool PostOp = false, PreOp = false;
856
857 // Try to parse the offset
858 std::unique_ptr Op = parseRegister();
859 if (!Op)
860 Op = parseImmediate();
861
862 // Only continue if next token is '['
863 if (Lexer.isNot(AsmToken::LBrac)) {
864 if (!Op)
865 return MatchOperand_NoMatch;
866
867 // The start of this custom parsing overlaps with register/immediate so
868 // consider this as a successful match of an operand of that type as the
869 // token stream can't be rewound to allow them to match separately.
870 Operands.push_back(std::move(Op));
871 return MatchOperand_Success;
872 }
873
874 Parser.Lex(); // Eat the '['.
875 std::unique_ptr Offset = nullptr;
876 if (Op)
877 Offset.swap(Op);
878
879 // Determine if a pre operation
880 PreOp = parsePrePost(Type, &OffsetValue);
881
882 Op = parseRegister();
883 if (!Op) {
884 if (!Offset) {
885 if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
886 Parser.Lex(); // Eat the ']'
887
888 // Memory address operations aligned to word boundary are encoded as
889 // SLS, the rest as RM.
890 if (shouldBeSls(*Op)) {
891 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
892 } else {
893 if (!Op->isLoImm16Signed()) {
894 Error(Parser.getTok().getLoc(),
895 "Memory address is not word "
896 "aligned and larger than class RM can handle");
897 return MatchOperand_ParseFail;
898 }
899 Operands.push_back(LanaiOperand::MorphToMemRegImm(
900 Lanai::R0, std::move(Op), LPAC::ADD));
901 }
902 return MatchOperand_Success;
903 }
904 }
905
906 Error(Parser.getTok().getLoc(),
907 "Unknown operand, expected register or immediate");
908 return MatchOperand_ParseFail;
909 }
910 BaseReg = Op->getReg();
911
912 // Determine if a post operation
913 if (!PreOp)
914 PostOp = parsePrePost(Type, &OffsetValue);
915
916 // If ] match form (1) else match form (2)
917 if (Lexer.is(AsmToken::RBrac)) {
918 Parser.Lex(); // Eat the ']'.
919 if (!Offset) {
920 SMLoc Start = Parser.getTok().getLoc();
921 SMLoc End =
922 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
923 const MCConstantExpr *OffsetConstExpr =
924 MCConstantExpr::create(OffsetValue, getContext());
925 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
926 }
927 } else {
928 if (Offset || OffsetValue != 0) {
929 Error(Parser.getTok().getLoc(), "Expected ']'");
930 return MatchOperand_ParseFail;
931 }
932
933 // Parse operator
934 AluOp = parseAluOperator(PreOp, PostOp);
935
936 // Second form requires offset register
937 Offset = parseRegister();
938 if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
939 Error(Parser.getTok().getLoc(), "Expected ']'");
940 return MatchOperand_ParseFail;
941 }
942 Parser.Lex(); // Eat the ']'.
943 }
944
945 // First form has addition as operator. Add pre- or post-op indicator as
946 // needed.
947 AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
948
949 // Ensure immediate offset is not too large
950 if (Offset->isImm() && !Offset->isLoImm16Signed()) {
951 Error(Parser.getTok().getLoc(),
952 "Memory address is not word "
953 "aligned and larger than class RM can handle");
954 return MatchOperand_ParseFail;
955 }
956
957 Operands.push_back(
958 Offset->isImm()
959 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
960 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
961
962 return MatchOperand_Success;
963 }
964
965 // Looks at a token type and creates the relevant operand from this
966 // information, adding to operands.
967 // If operand was parsed, returns false, else true.
968 LanaiAsmParser::OperandMatchResultTy
969 LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
970 // Check if the current operand has a custom associated parser, if so, try to
971 // custom parse the operand, or fallback to the general approach.
972 OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
973
974 if (Result == MatchOperand_Success)
975 return Result;
976 if (Result == MatchOperand_ParseFail) {
977 Parser.eatToEndOfStatement();
978 return Result;
979 }
980
981 // Attempt to parse token as register
982 std::unique_ptr Op = parseRegister();
983
984 // Attempt to parse token as immediate
985 if (!Op)
986 Op = parseImmediate();
987
988 // If the token could not be parsed then fail
989 if (!Op) {
990 Error(Parser.getTok().getLoc(), "Unknown operand");
991 Parser.eatToEndOfStatement();
992 return MatchOperand_ParseFail;
993 }
994
995 // Push back parsed operand into list of operands
996 Operands->push_back(std::move(Op));
997
998 return MatchOperand_Success;
999 }
1000
1001 // Split the mnemonic into ASM operand, conditional code and instruction
1002 // qualifier (half-word, byte).
1003 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1004 OperandVector *Operands) {
1005 size_t Next = Name.find('.');
1006
1007 StringRef Mnemonic = Name;
1008
1009 bool IsBRR = false;
1010 if (Name.endswith(".r")) {
1011 Mnemonic = Name.substr(0, Name.size() - 2);
1012 IsBRR = true;
1013 }
1014
1015 // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1016 if (Mnemonic[0] == 'b' ||
1017 (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1018 !Mnemonic.startswith("st"))) {
1019 // Parse instructions with a conditional code. For example, 'bne' is
1020 // converted into two operands 'b' and 'ne'.
1021 LPCC::CondCode CondCode =
1022 LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1023 if (CondCode != LPCC::UNKNOWN) {
1024 Mnemonic = Mnemonic.slice(0, 1);
1025 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1026 Operands->push_back(LanaiOperand::createImm(
1027 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1028 if (IsBRR) {
1029 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1030 }
1031 return Mnemonic;
1032 }
1033 }
1034
1035 // Parse other instructions with condition codes (RR instructions).
1036 // We ignore .f here and assume they are flag-setting operations, not
1037 // conditional codes (except for select instructions where flag-setting
1038 // variants are not yet implemented).
1039 if (Mnemonic.startswith("sel") ||
1040 (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1041 LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1042 if (CondCode != LPCC::UNKNOWN) {
1043 size_t Next = Mnemonic.rfind('.', Name.size());
1044 Mnemonic = Mnemonic.substr(0, Next + 1);
1045 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1046 Operands->push_back(LanaiOperand::createImm(
1047 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1048 return Mnemonic;
1049 }
1050 }
1051
1052 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1053 if (IsBRR) {
1054 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1055 }
1056
1057 return Mnemonic;
1058 }
1059
1060 bool IsMemoryAssignmentError(const OperandVector &Operands) {
1061 // Detects if a memory operation has an erroneous base register modification.
1062 // Memory operations are detected by matching the types of operands.
1063 //
1064 // TODO: This test is focussed on one specific instance (ld/st).
1065 // Extend it to handle more cases or be more robust.
1066 bool Modifies = false;
1067
1068 int Offset = 0;
1069
1070 if (Operands.size() < 5)
1071 return false;
1072 else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1073 Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1074 Offset = 0;
1075 else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1076 Operands[2]->isReg() && Operands[3]->isImm() &&
1077 Operands[4]->isImm() && Operands[5]->isReg())
1078 Offset = 1;
1079 else
1080 return false;
1081
1082 int PossibleAluOpIdx = Offset + 3;
1083 int PossibleBaseIdx = Offset + 1;
1084 int PossibleDestIdx = Offset + 4;
1085 if (LanaiOperand *PossibleAluOp =
1086 static_cast(Operands[PossibleAluOpIdx].get()))
1087 if (PossibleAluOp->isImm())
1088 if (const MCConstantExpr *ConstExpr =
1089 dyn_cast(PossibleAluOp->getImm()))
1090 Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1091 return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1092 Operands[PossibleDestIdx]->isReg() &&
1093 Operands[PossibleBaseIdx]->getReg() ==
1094 Operands[PossibleDestIdx]->getReg();
1095 }
1096
1097 bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1098 StringRef Name, SMLoc NameLoc,
1099 OperandVector &Operands) {
1100 // First operand is token for instruction
1101 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1102
1103 // If there are no more operands, then finish
1104 if (Lexer.is(AsmToken::EndOfStatement))
1105 return false;
1106
1107 // Parse first operand
1108 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1109 return true;
1110
1111 // If it is a st instruction with one 1 operand then it is a "store true".
1112 // Transform <"st"> to <"s">,
1113 if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1114 Operands.size() == 2) {
1115 Operands.erase(Operands.begin(), Operands.begin() + 1);
1116 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1117 Operands.insert(Operands.begin() + 1,
1118 LanaiOperand::createImm(
1119 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1120 NameLoc, NameLoc));
1121 }
1122
1123 // If the instruction is a bt instruction with 1 operand (in assembly) then it
1124 // is an unconditional branch instruction and the first two elements of
1125 // operands need to be merged.
1126 if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1127 Operands.size() == 3) {
1128 Operands.erase(Operands.begin(), Operands.begin() + 2);
1129 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1130 }
1131
1132 // Parse until end of statement, consuming commas between operands
1133 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1134 // Consume comma token
1135 Lexer.Lex();
1136
1137 // Parse next operand
1138 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1139 return true;
1140 }
1141
1142 if (IsMemoryAssignmentError(Operands)) {
1143 Error(Parser.getTok().getLoc(),
1144 "the destination register can't equal the base register in an "
1145 "instruction that modifies the base register.");
1146 return true;
1147 }
1148
1149 return false;
1150 }
1151
1152 #define GET_REGISTER_MATCHER
1153 #define GET_MATCHER_IMPLEMENTATION
1154 #include "LanaiGenAsmMatcher.inc"
1155 } // namespace
1156
1157 extern "C" void LLVMInitializeLanaiAsmParser() {
1158 RegisterMCAsmParser x(TheLanaiTarget);
1159 }
1160
1161 } // namespace llvm
0 set(LLVM_TARGET_DEFINITIONS Lanai.td)
1
2 tablegen(LLVM LanaiGenAsmMatcher.inc -gen-asm-matcher)
3 tablegen(LLVM LanaiGenAsmWriter.inc -gen-asm-writer)
4 tablegen(LLVM LanaiGenCallingConv.inc -gen-callingconv)
5 tablegen(LLVM LanaiGenDAGISel.inc -gen-dag-isel)
6 tablegen(LLVM LanaiGenDisassemblerTables.inc -gen-disassembler)
7 tablegen(LLVM LanaiGenInstrInfo.inc -gen-instr-info)
8 tablegen(LLVM LanaiGenMCCodeEmitter.inc -gen-emitter)
9 tablegen(LLVM LanaiGenRegisterInfo.inc -gen-register-info)
10 tablegen(LLVM LanaiGenSubtargetInfo.inc -gen-subtarget)
11 add_public_tablegen_target(LanaiCommonTableGen)
12
13 add_llvm_target(LanaiCodeGen
14 LanaiAsmPrinter.cpp
15 LanaiDelaySlotFiller.cpp
16 LanaiFrameLowering.cpp
17 LanaiInstrInfo.cpp
18 LanaiISelDAGToDAG.cpp
19 LanaiISelLowering.cpp
20 LanaiMachineFunctionInfo.cpp
21 LanaiMCInstLower.cpp
22 LanaiMemAluCombiner.cpp
23 LanaiRegisterInfo.cpp
24 LanaiSelectionDAGInfo.cpp
25 LanaiSetflagAluCombiner.cpp
26 LanaiSubtarget.cpp
27 LanaiTargetMachine.cpp
28 LanaiTargetObjectFile.cpp
29 )
30
31 add_subdirectory(AsmParser)
32 add_subdirectory(TargetInfo)
33 add_subdirectory(MCTargetDesc)
34 add_subdirectory(InstPrinter)
35 add_subdirectory(Disassembler)
0 add_llvm_library(LLVMLanaiDisassembler
1 LanaiDisassembler.cpp
2 )
0 ;===-- ./lib/Target/Lanai/Disassembler/LLVMBuild.txt -----------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = LanaiDisassembler
20 parent = Lanai
21 required_libraries = LanaiMCTargetDesc LanaiInfo MC MCDisassembler Support
22 add_to_library_groups = Lanai
0 //===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is part of the Lanai Disassembler.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LanaiDisassembler.h"
14
15 #include "Lanai.h"
16 #include "LanaiSubtarget.h"
17 #include "llvm/MC/MCFixedLenDisassembler.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCSubtargetInfo.h"
20 #include "llvm/Support/MathExtras.h"
21 #include "llvm/Support/MemoryObject.h"
22 #include "llvm/Support/TargetRegistry.h"
23
24 using namespace llvm;
25
26 typedef MCDisassembler::DecodeStatus DecodeStatus;
27
28 namespace llvm {
29 extern Target TheLanaiTarget;
30 }
31
32 static MCDisassembler *createLanaiDisassembler(const Target &T,
33 const MCSubtargetInfo &STI,
34 MCContext &Ctx) {
35 return new LanaiDisassembler(STI, Ctx);
36 }
37
38 extern "C" void LLVMInitializeLanaiDisassembler() {
39 // Register the disassembler
40 TargetRegistry::RegisterMCDisassembler(TheLanaiTarget,
41 createLanaiDisassembler);
42 }
43
44 LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
45 : MCDisassembler(STI, Ctx) {}
46
47 // Forward declare because the autogenerated code will reference this.
48 // Definition is further down.
49 DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
50 uint64_t Address, const void *Decoder);
51
52 static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
53 uint64_t Address, const void *Decoder);
54
55 static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
56 uint64_t Address, const void *Decoder);
57
58 static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
59 uint64_t Address, const void *Decoder);
60
61 static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
62 const void *Decoder);
63
64 static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
65 uint64_t Address, const void *Decoder);
66
67 #include "LanaiGenDisassemblerTables.inc"
68
69 static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address,
70 uint64_t &Size, uint32_t &Insn) {
71 // We want to read exactly 4 bytes of data.
72 if (Bytes.size() < 4) {
73 Size = 0;
74 return MCDisassembler::Fail;
75 }
76
77 // Encoded as big-endian 32-bit word in the stream.
78 Insn =
79 (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
80
81 return MCDisassembler::Success;
82 }
83
84 static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
85 unsigned AluOp = LPAC::ADD;
86 // Fix up for pre and post operations.
87 int PqShift = -1;
88 if (isRMOpcode(Instr.getOpcode()))
89 PqShift = 16;
90 else if (isSPLSOpcode(Instr.getOpcode()))
91 PqShift = 10;
92 else if (isRRMOpcode(Instr.getOpcode())) {
93 PqShift = 16;
94 // Determine RRM ALU op.
95 AluOp = (Insn >> 8) & 0x7;
96 if (AluOp == 7)
97 // Handle JJJJJ
98 // 0b10000 or 0b11000
99 AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
100 }
101
102 if (PqShift != -1) {
103 unsigned PQ = (Insn >> PqShift) & 0x3;
104 switch (PQ) {
105 case 0x0:
106 if (Instr.getOperand(2).isReg()) {
107 Instr.getOperand(2).setReg(Lanai::R0);
108 }
109 if (Instr.getOperand(2).isImm())
110 Instr.getOperand(2).setImm(0);
111 break;
112 case 0x1:
113 AluOp = LPAC::makePostOp(AluOp);
114 break;
115 case 0x2:
116 break;
117 case 0x3:
118 AluOp = LPAC::makePreOp(AluOp);
119 break;
120 }
121 Instr.addOperand(MCOperand::createImm(AluOp));
122 }
123 }
124
125 DecodeStatus LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
126 ArrayRef Bytes,
127 uint64_t Address,
128 raw_ostream &VStream,
129 raw_ostream &CStream) const {
130 uint32_t Insn;
131
132 DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn);
133
134 if (Result == MCDisassembler::Fail)
135 return MCDisassembler::Fail;
136
137 // Call auto-generated decoder function
138 Result =
139 decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
140
141 if (Result != MCDisassembler::Fail) {
142 PostOperandDecodeAdjust(Instr, Insn);
143 Size = 4;
144 return Result;
145 }
146
147 return MCDisassembler::Fail;
148 }
149
150 static const unsigned GPRDecoderTable[] = {
151 Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
152 Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
153 Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
154 Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
155 Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
156 Lanai::R30, Lanai::R31};
157
158 DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
159 uint64_t Address, const void *Decoder) {
160 if (RegNo > 31)
161 return MCDisassembler::Fail;
162
163 unsigned Reg = GPRDecoderTable[RegNo];
164 Inst.addOperand(MCOperand::createReg(Reg));
165 return MCDisassembler::Success;
166 }
167
168 static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
169 uint64_t Address, const void *Decoder) {
170 // RI memory values encoded using 23 bits:
171 // 5 bit register, 16 bit constant
172 unsigned Register = (Insn >> 18) & 0x1f;
173 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
174 unsigned Offset = (Insn & 0xffff);
175 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
176
177 return MCDisassembler::Success;
178 }
179
180 static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
181 uint64_t Address, const void *Decoder) {
182 // RR memory values encoded using 20 bits:
183 // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
184 unsigned Register = (Insn >> 15) & 0x1f;
185 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
186 Register = (Insn >> 10) & 0x1f;
187 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
188
189 return MCDisassembler::Success;
190 }
191
192 static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
193 uint64_t Address, const void *Decoder) {
194 // RI memory values encoded using 17 bits:
195 // 5 bit register, 10 bit constant
196 unsigned Register = (Insn >> 12) & 0x1f;
197 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
198 unsigned Offset = (Insn & 0x3ff);
199 Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
200
201 return MCDisassembler::Success;
202 }
203
204 static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
205 uint64_t Address, uint64_t Offset,
206 uint64_t Width, MCInst &MI,
207 const void *Decoder) {
208 const MCDisassembler *Dis = static_cast(Decoder);
209 return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
210 Width);
211 }
212
213 static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
214 const void *Decoder) {
215 if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
216 Decoder))
217 MI.addOperand(MCOperand::createImm(Insn));
218 return MCDisassembler::Success;
219 }
220
221 static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
222 uint64_t Address, const void *Decoder) {
223 unsigned Offset = (Insn & 0xffff);
224 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
225
226 return MCDisassembler::Success;
227 }
0 //===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is part of the Lanai Disassembler.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
14 #define LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
15
16 #define DEBUG_TYPE "lanai-disassembler"
17
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19
20 namespace llvm {
21
22 class MCInst;
23 class raw_ostream;
24
25 class LanaiDisassembler : public MCDisassembler {
26 public:
27 LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx);
28
29 ~LanaiDisassembler() override {}
30
31 // getInstruction - See MCDisassembler.
32 MCDisassembler::DecodeStatus
33 getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef Bytes,
34 uint64_t Address, raw_ostream &VStream,
35 raw_ostream &CStream) const override;
36 };
37
38 } // namespace llvm
39
40 #endif // LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
0 add_llvm_library(LLVMLanaiInstPrinter
1 LanaiInstPrinter.cpp
2 )
0 ;===-- ./lib/Target/Lanai/InstPrinter/LLVMBuild.txt ------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = LanaiInstPrinter
20 parent = Lanai
21 required_libraries = LanaiInfo MC Support
22 add_to_library_groups = Lanai
0 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints an Lanai MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Lanai.h"
14 #include "LanaiInstPrinter.h"
15 #include "MCTargetDesc/LanaiMCExpr.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/FormattedStream.h"
22
23 using namespace llvm;
24
25 #define DEBUG_TYPE "asm-printer"
26
27 // Include the auto-generated portion of the assembly writer.
28 #define PRINT_ALIAS_INSTR
29 #include "LanaiGenAsmWriter.inc"
30
31 void LanaiInstPrinter::printRegName(raw_ostream &Ostream,
32 unsigned RegNo) const {
33 Ostream << StringRef(getRegisterName(RegNo)).lower();
34 }
35
36 bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
37 StringRef Alias, unsigned OpNo0,
38 unsigned OpNo1) {
39 Ostream << "\t" << Alias << " ";
40 printOperand(MI, OpNo0, Ostream);
41 Ostream << ", ";
42 printOperand(MI, OpNo1, Ostream);
43 return true;
44 }
45
46 static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
47 unsigned AluCode = MI->getOperand(3).getImm();
48 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
49 (MI->getOperand(2).getImm() == AddOffset ||
50 MI->getOperand(2).getImm() == -AddOffset);
51 }
52
53 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
54 unsigned AluCode = MI->getOperand(3).getImm();
55 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
56 }
57
58 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
59 unsigned AluCode = MI->getOperand(3).getImm();
60 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
61 }
62
63 static StringRef decIncOperator(const MCInst *MI) {
64 if (MI->getOperand(2).getImm() < 0)
65 return "--";
66 return "++";
67 }
68
69 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
70 raw_ostream &Ostream,
71 StringRef Opcode,
72 int AddOffset) {
73 if (isPreIncrementForm(MI, AddOffset)) {
74 Ostream << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
75 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
76 << getRegisterName(MI->getOperand(0).getReg());
77 return true;
78 }
79 if (isPostIncrementForm(MI, AddOffset)) {
80 Ostream << "\t" << Opcode << "\t[%"
81 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
82 << "], %" << getRegisterName(MI->getOperand(0).getReg());
83 return true;
84 }
85 return false;
86 }
87
88 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
89 raw_ostream &Ostream,
90 StringRef Opcode,
91 int AddOffset) {
92 if (isPreIncrementForm(MI, AddOffset)) {
93 Ostream << "\t" << Opcode << "\t%"
94 << getRegisterName(MI->getOperand(0).getReg()) << ", ["
95 << decIncOperator(MI) << "%"
96 << getRegisterName(MI->getOperand(1).getReg()) << "]";
97 return true;
98 }
99 if (isPostIncrementForm(MI, AddOffset)) {
100 Ostream << "\t" << Opcode << "\t%"
101 << getRegisterName(MI->getOperand(0).getReg()) << ", [%"
102 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
103 << "]";
104 return true;
105 }
106 return false;
107 }
108
109 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &Ostream) {
110 switch (MI->getOpcode()) {
111 case Lanai::LDW_RI:
112 // ld 4[*%rN], %rX => ld [++imm], %rX
113 // ld -4[*%rN], %rX => ld [--imm], %rX
114 // ld 4[%rN*], %rX => ld [imm++], %rX
115 // ld -4[%rN*], %rX => ld [imm--], %rX
116 return printMemoryLoadIncrement(MI, Ostream, "ld", 4);
117 case Lanai::LDHs_RI:
118 return printMemoryLoadIncrement(MI, Ostream, "ld.h", 2);
119 case Lanai::LDHz_RI:
120 return printMemoryLoadIncrement(MI, Ostream, "uld.h", 2);
121 case Lanai::LDBs_RI:
122 return printMemoryLoadIncrement(MI, Ostream, "ld.b", 1);
123 case Lanai::LDBz_RI:
124 return printMemoryLoadIncrement(MI, Ostream, "uld.b", 1);
125 case Lanai::SW_RI:
126 // st %rX, 4[*%rN] => st %rX, [++imm]
127 // st %rX, -4[*%rN] => st %rX, [--imm]
128 // st %rX, 4[%rN*] => st %rX, [imm++]
129 // st %rX, -4[%rN*] => st %rX, [imm--]
130 return printMemoryStoreIncrement(MI, Ostream, "st", 4);
131 case Lanai::STH_RI:
132 return printMemoryStoreIncrement(MI, Ostream, "st.h", 2);
133 case Lanai::STB_RI:
134 return printMemoryStoreIncrement(MI, Ostream, "st.b", 1);
135 default:
136 return false;
137 }
138 }
139
140 void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
141 StringRef Annotation,
142 const MCSubtargetInfo &STI) {
143 if (!printAlias(MI, Ostream) && !printAliasInstr(MI, Ostream))
144 printInstruction(MI, Ostream);
145 printAnnotation(Ostream, Annotation);
146 }
147
148 static void printExpr(const MCAsmInfo &MAI, const MCExpr &Expr,
149 raw_ostream &Ostream) {
150 const MCExpr *SRE;
151
152 if (const MCBinaryExpr *BE = dyn_cast(&Expr))
153 SRE = dyn_cast(BE->getLHS());
154 else if (isa(&Expr)) {
155 SRE = dyn_cast(&Expr);
156 } else {
157 SRE = dyn_cast(&Expr);
158 }
159 assert(SRE && "Unexpected MCExpr type.");
160
161 SRE->print(Ostream, &MAI);
162 }
163
164 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
165 raw_ostream &Ostream,
166 const char *Modifier) {
167 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
168 const MCOperand &Op = MI->getOperand(OpNo);
169 if (Op.isReg())
170 Ostream << "%" << getRegisterName(Op.getReg());
171 else if (Op.isImm())
172 Ostream << formatHex(Op.getImm());
173 else {
174 assert(Op.isExpr() && "Expected an expression");
175 printExpr(MAI, *Op.getExpr(), Ostream);
176 }
177 }
178
179 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
180 raw_ostream &Ostream) {
181 const MCOperand &Op = MI->getOperand(OpNo);
182 if (Op.isImm()) {
183 Ostream << '[' << formatHex(Op.getImm()) << ']';
184 } else {
185 // Symbolic operand will be lowered to immediate value by linker
186 assert(Op.isExpr() && "Expected an expression");
187 Ostream << '[';
188 printExpr(MAI, *Op.getExpr(), Ostream);
189 Ostream << ']';
190 }
191 }
192
193 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
194 raw_ostream &Ostream) {
195 const MCOperand &Op = MI->getOperand(OpNo);
196 if (Op.isImm()) {
197 Ostream << formatHex(Op.getImm() << 16);
198 } else {
199 // Symbolic operand will be lowered to immediate value by linker
200 assert(Op.isExpr() && "Expected an expression");
201 printExpr(MAI, *Op.getExpr(), Ostream);
202 }
203 }
204
205 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
206 raw_ostream &Ostream) {
207 const MCOperand &Op = MI->getOperand(OpNo);
208 if (Op.isImm()) {
209 Ostream << formatHex((Op.getImm() << 16) | 0xffff);
210 } else {
211 // Symbolic operand will be lowered to immediate value by linker
212 assert(Op.isExpr() && "Expected an expression");
213 printExpr(MAI, *Op.getExpr(), Ostream);
214 }
215 }
216
217 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
218 raw_ostream &Ostream) {
219 const MCOperand &Op = MI->getOperand(OpNo);
220 if (Op.isImm()) {
221 Ostream << formatHex(0xffff0000 | Op.getImm());
222 } else {
223 // Symbolic operand will be lowered to immediate value by linker
224 assert(Op.isExpr() && "Expected an expression");
225 printExpr(MAI, *Op.getExpr(), Ostream);
226 }
227 }
228
229 static void printMemoryBaseRegister(raw_ostream &Ostream, const unsigned AluCode,
230 const MCOperand &RegOp) {
231 assert(RegOp.isReg() && "Register operand expected");
232 Ostream << "[";
233 if (LPAC::isPreOp(AluCode))
234 Ostream << "*";
235 Ostream << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
236 if (LPAC::isPostOp(AluCode))
237 Ostream << "*";
238 Ostream << "]";
239 }
240
241 template
242 static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
243 const MCOperand &OffsetOp,
244 raw_ostream &Ostream) {
245 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
246 if (OffsetOp.isImm()) {
247 assert(isInt(OffsetOp.getImm()) && "Constant value truncated");
248 Ostream << OffsetOp.getImm();
249 } else
250 printExpr(MAI, *OffsetOp.getExpr(), Ostream);
251 }
252
253 void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
254 raw_ostream &Ostream,
255 const char *Modifier) {
256 const MCOperand &RegOp = MI->getOperand(OpNo);
257 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
258 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
259 const unsigned AluCode = AluOp.getImm();
260
261 // Offset
262 printMemoryImmediateOffset<16>(MAI, OffsetOp, Ostream);
263
264 // Register
265 printMemoryBaseRegister(Ostream, AluCode, RegOp);
266 }
267
268 void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
269 raw_ostream &Ostream,
270 const char *Modifier) {
271 const MCOperand &RegOp = MI->getOperand(OpNo);
272 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
273 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
274 const unsigned AluCode = AluOp.getImm();
275 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
276
277 // [ Base OP Offset ]
278 Ostream << "[";
279 if (LPAC::isPreOp(AluCode))
280 Ostream << "*";
281 Ostream << "%" << getRegisterName(RegOp.getReg());
282 if (LPAC::isPostOp(AluCode))
283 Ostream << "*";
284 Ostream << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
285 Ostream << "%" << getRegisterName(OffsetOp.getReg());
286 Ostream << "]";
287 }
288
289 void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
290 raw_ostream &Ostream,
291 const char *Modifier) {
292 const MCOperand &RegOp = MI->getOperand(OpNo);
293 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
294 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
295 const unsigned AluCode = AluOp.getImm();
296
297 // Offset
298 printMemoryImmediateOffset<10>(MAI, OffsetOp, Ostream);
299
300 // Register
301 printMemoryBaseRegister(Ostream, AluCode, RegOp);
302 }
303
304 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
305 raw_ostream &Ostream) {
306 const int CC = static_cast(MI->getOperand(OpNo).getImm());
307 Ostream << lanaiCondCodeToString(static_cast(CC));
308 }
0 //= LanaiInstPrinter.h - Convert Lanai MCInst to asm syntax -------*- C++ -*--//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints a Lanai MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
14 #define LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
15
16 #include "llvm/MC/MCInstPrinter.h"
17
18 namespace llvm {
19 class MCOperand;
20
21 class LanaiInstPrinter : public MCInstPrinter {
22 public:
23 LanaiInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
24 const MCRegisterInfo &MRI)
25 : MCInstPrinter(MAI, MII, MRI) {}
26
27 void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
28 const MCSubtargetInfo &STI) override;
29 void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
30 const char *Modifier = 0);
31 void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O,
32 const char *Modifier = 0);
33 void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O,
34 const char *Modifier = 0);
35 void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O,
36 const char *Modifier = 0);
37 void printCCOperand(const MCInst *MI, int OpNo, raw_ostream &O);
38 void printAluOperand(const MCInst *MI, int OpNo, raw_ostream &O);
39 void printHi16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
40 void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
41 void printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
42 void printMemImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
43
44 // Autogenerated by tblgen.
45 void printInstruction(const MCInst *MI, raw_ostream &O);
46 bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
47 void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
48 unsigned PrintMethodIdx, raw_ostream &O);
49 static const char *getRegisterName(unsigned RegNo);
50 void printRegName(raw_ostream &OS, unsigned RegNo) const override;
51
52 private:
53 bool printAlias(const MCInst *MI, raw_ostream &Ostream);
54 bool printInst(const MCInst *MI, raw_ostream &Ostream, StringRef Alias,
55 unsigned OpNo0, unsigned OpnNo1);
56 bool printMemoryLoadIncrement(const MCInst *MI, raw_ostream &Ostream,
57 StringRef Opcode, int AddOffset);
58 bool printMemoryStoreIncrement(const MCInst *MI, raw_ostream &Ostream,
59 StringRef Opcode, int AddOffset);
60 };
61 } // namespace llvm
62
63 #endif // LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
0 ;===- ./lib/Target/Lanai/LLVMBuild.txt -------------------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [common]
18 subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
19
20 [component_0]
21 type = TargetGroup
22 name = Lanai
23 parent = Target
24 has_asmprinter = 1
25
26 [component_1]
27 type = Library
28 name = LanaiCodeGen
29 parent = Lanai
30 required_libraries =
31 Analysis
32 AsmPrinter
33 CodeGen
34 Core
35 LanaiAsmParser
36 LanaiMCTargetDesc
37 LanaiInfo
38 LanaiInstPrinter
39 MC
40 SelectionDAG
41 Support
42 Target
43 TransformUtils
44 add_to_library_groups = Lanai
0 //===-- Lanai.h - Top-level interface for Lanai representation --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the entry points for global functions defined in the LLVM
10 // Lanai back-end.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_LIB_TARGET_LANAI_LANAI_H
15 #define LLVM_LIB_TARGET_LANAI_LANAI_H
16
17 #include "LanaiAluCode.h"
18 #include "LanaiCondCode.h"
19 #include "MCTargetDesc/LanaiBaseInfo.h"
20 #include "MCTargetDesc/LanaiMCTargetDesc.h"
21 #include "llvm/CodeGen/ISDOpcodes.h"
22 #include "llvm/Target/TargetMachine.h"
23
24 namespace llvm {
25 class FunctionPass;
26 class LanaiTargetMachine;
27 class MachineFunctionPass;
28 class TargetMachine;
29 class formatted_raw_ostream;
30
31 // createLanaiISelDag - This pass converts a legalized DAG into a
32 // Lanai-specific DAG, ready for instruction scheduling.
33 FunctionPass *createLanaiISelDag(LanaiTargetMachine &TM);
34
35 // createLanaiDelaySlotFillerPass - This pass fills delay slots
36 // with useful instructions or nop's
37 FunctionPass *createLanaiDelaySlotFillerPass(const LanaiTargetMachine &TM);
38
39 // createLanaiMemAluCombinerPass - This pass combines loads/stores and
40 // arithmetic operations.
41 FunctionPass *createLanaiMemAluCombinerPass();
42
43 // createLanaiSetflagAluCombinerPass - This pass combines SET_FLAG and ALU
44 // operations.
45 FunctionPass *createLanaiSetflagAluCombinerPass();
46
47 extern Target TheLanaiTarget;
48 } // namespace llvm
49
50 #endif // LLVM_LIB_TARGET_LANAI_LANAI_H
0 //===- Lanai.td - Describe the Lanai Target Machine --------*- tablegen -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 //===----------------------------------------------------------------------===//
10 // Target-independent interfaces which we are implementing
11 //===----------------------------------------------------------------------===//
12
13 include "llvm/Target/Target.td"
14
15 //===----------------------------------------------------------------------===//
16 // Register File, Calling Conv, Instruction Descriptions
17 //===----------------------------------------------------------------------===//
18
19 include "LanaiSchedule.td"
20 include "LanaiRegisterInfo.td"
21 include "LanaiCallingConv.td"
22 include "LanaiInstrInfo.td"
23
24 def LanaiInstrInfo : InstrInfo;
25
26 //===----------------------------------------------------------------------===//
27 // Lanai processors supported.
28 //===----------------------------------------------------------------------===//
29
30 def : ProcessorModel<"generic", LanaiSchedModel, []>;
31 def : ProcessorModel<"v11", LanaiSchedModel, []>;
32
33 def LanaiInstPrinter : AsmWriter {
34 string AsmWriterClassName = "InstPrinter";
35 bit isMCAsmWriter = 1;
36 }
37
38 //===----------------------------------------------------------------------===//
39 // Declare the target which we are implementing
40 //===----------------------------------------------------------------------===//
41
42 def Lanai : Target {
43 // Pull in Instruction Info:
44 let InstructionSet = LanaiInstrInfo;
45 let AssemblyWriters = [LanaiInstPrinter];
46 }
0 //===-- LanaiAluCode.h - ALU operator encoding ----------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The encoding for ALU operators used in RM and RRM operands
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
14 #define LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
15
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/CodeGen/ISDOpcodes.h"
18 #include "llvm/Support/ErrorHandling.h"
19
20 namespace llvm {
21 namespace LPAC {
22 enum AluCode {
23 ADD = 0x00,
24 ADDC = 0x01,
25 SUB = 0x02,
26 SUBB = 0x03,
27 AND = 0x04,
28 OR = 0x05,
29 XOR = 0x06,
30 SPECIAL = 0x07,
31
32 // Shift instructions are treated as SPECIAL when encoding the machine
33 // instruction, but kept distinct until lowering. The constant values are
34 // chosen to ease lowering.
35 SHL = 0x17,
36 SRL = 0x27,
37 SRA = 0x37,
38
39 // Indicates an unknown/unsupported operator
40 UNKNOWN = 0xFF,
41 };
42
43 // Bits indicating post- and pre-operators should be tested and set using Is*
44 // and Make* utility functions
45 constexpr int Lanai_PRE_OP = 0x40;
46 constexpr int Lanai_POST_OP = 0x80;
47
48 inline static unsigned encodeLanaiAluCode(unsigned AluOp) {
49 unsigned const OP_ENCODING_MASK = 0x07;
50 return AluOp & OP_ENCODING_MASK;
51 }
52
53 inline static unsigned getAluOp(unsigned AluOp) {
54 unsigned const ALU_MASK = 0x3F;
55 return AluOp & ALU_MASK;
56 }
57
58 inline static bool isPreOp(unsigned AluOp) { return AluOp & Lanai_PRE_OP; }
59
60 inline static bool isPostOp(unsigned AluOp) { return AluOp & Lanai_POST_OP; }
61
62 inline static unsigned makePreOp(unsigned AluOp) {
63 assert(!isPostOp(AluOp) && "Operator can't be a post- and pre-op");
64 return AluOp | Lanai_PRE_OP;
65 }
66
67 inline static unsigned makePostOp(unsigned AluOp) {
68 assert(!isPreOp(AluOp) && "Operator can't be a post- and pre-op");
69 return AluOp | Lanai_POST_OP;
70 }
71
72 inline static bool modifiesOp(unsigned AluOp) {
73 return isPreOp(AluOp) | isPostOp(AluOp);
74 }
75
76 inline static const char *lanaiAluCodeToString(unsigned AluOp) {
77 switch (getAluOp(AluOp)) {
78 case ADD:
79 return "add";
80 case ADDC:
81 return "addc";
82 case SUB:
83 return "sub";
84 case SUBB:
85 return "subb";
86 case AND:
87 return "and";
88 case OR:
89 return "or";
90 case XOR:
91 return "xor";
92 case SHL:
93 return "sh";
94 case SRL:
95 return "sh";
96 case SRA:
97 return "sha";
98 default:
99 llvm_unreachable("Invalid ALU code.");
100 }
101 }
102
103 inline static AluCode stringToLanaiAluCode(StringRef S) {
104 return StringSwitch(S)
105 .Case("add", ADD)
106 .Case("addc", ADDC)
107 .Case("sub", SUB)
108 .Case("subb", SUBB)
109 .Case("and", AND)
110 .Case("or", OR)
111 .Case("xor", XOR)
112 .Case("sh", SHL)
113 .Case("srl", SRL)
114 .Case("sha", SRA)
115 .Default(UNKNOWN);
116 }
117
118 inline static AluCode isdToLanaiAluCode(ISD::NodeType Node_type) {
119 switch (Node_type) {
120 case ISD::ADD:
121 return AluCode::ADD;
122 case ISD::ADDE:
123 return AluCode::ADDC;
124 case ISD::SUB:
125 return AluCode::SUB;
126 case ISD::SUBE:
127 return AluCode::SUBB;
128 case ISD::AND:
129 return AluCode::AND;
130 case ISD::OR:
131 return AluCode::OR;
132 case ISD::XOR:
133 return AluCode::XOR;
134 case ISD::SHL:
135 return AluCode::SHL;
136 case ISD::SRL:
137 return AluCode::SRL;
138 case ISD::SRA:
139 return AluCode::SRA;
140 default:
141 return AluCode::UNKNOWN;
142 }
143 }
144 } // namespace LPAC
145 } // namespace llvm
146
147 #endif // LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
0 //===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to the Lanai assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Lanai.h"
15 #include "InstPrinter/LanaiInstPrinter.h"
16 #include "LanaiInstrInfo.h"
17 #include "LanaiMCInstLower.h"
18 #include "LanaiTargetMachine.h"
19 #include "llvm/CodeGen/AsmPrinter.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCInst.h"
30 #include "llvm/MC/MCInstBuilder.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Support/raw_ostream.h"
35
36 #define DEBUG_TYPE "asm-printer"
37
38 using namespace llvm;
39
40 namespace {
41 class LanaiAsmPrinter : public AsmPrinter {
42 public:
43 explicit LanaiAsmPrinter(TargetMachine &TM,
44 std::unique_ptr Streamer)
45 : AsmPrinter(TM, std::move(Streamer)) {}
46
47 const char *getPassName() const override { return "Lanai Assembly Printer"; }
48
49 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
50 const char *Modifier = 0);
51 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
52 unsigned AsmVariant, const char *ExtraCode,
53 raw_ostream &O) override;
54 void EmitInstruction(const MachineInstr *MI) override;
55 bool isBlockOnlyReachableByFallthrough(
56 const MachineBasicBlock *MBB) const override;
57
58 private:
59 void customEmitInstruction(const MachineInstr *MI);
60 void emitCallInstruction(const MachineInstr *MI);
61 };
62 } // end of anonymous namespace
63
64 void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
65 raw_ostream &O, const char *Modifier) {
66 const MachineOperand &MO = MI->getOperand(OpNum);
67 unsigned TF = MO.getTargetFlags();
68
69 switch (MO.getType()) {
70 case MachineOperand::MO_Register:
71 O << LanaiInstPrinter::getRegisterName(MO.getReg());
72 break;
73
74 case MachineOperand::MO_Immediate:
75 O << MO.getImm();
76 break;
77
78 case MachineOperand::MO_MachineBasicBlock:
79 O << *MO.getMBB()->getSymbol();
80 break;
81
82 case MachineOperand::MO_GlobalAddress:
83 if (TF == LanaiII::MO_PLT)
84 O << "plt(" << *getSymbol(MO.getGlobal()) << ")";
85 else
86 O << *getSymbol(MO.getGlobal());
87 break;
88
89 case MachineOperand::MO_BlockAddress: {
90 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
91 O << BA->getName();
92 break;
93 }
94
95 case MachineOperand::MO_ExternalSymbol:
96 if (TF == LanaiII::MO_PLT)
97 O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")";
98 else
99 O << *GetExternalSymbolSymbol(MO.getSymbolName());
100 break;
101
102 case MachineOperand::MO_JumpTableIndex:
103 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
104 << MO.getIndex();
105 break;
106
107 case MachineOperand::MO_ConstantPoolIndex:
108 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
109 << MO.getIndex();
110 return;
111
112 default:
113 llvm_unreachable("");
114 }
115 }
116
117 // PrintAsmOperand - Print out an operand for an inline asm expression.
118 //
119 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
120 unsigned AsmVariant,
121 const char *ExtraCode, raw_ostream &O) {
122 // Does this asm operand have a single letter operand modifier?
123 if (ExtraCode && ExtraCode[0]) {
124 if (ExtraCode[1])
125 return true; // Unknown modifier.
126
127 switch (ExtraCode[0]) {
128 // The highest-numbered register of a pair.
129 case 'H': {
130 if (OpNo == 0)
131 return true;
132 const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
133 if (!FlagsOP.isImm())
134 return true;
135 unsigned Flags = FlagsOP.getImm();
136 unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
137 if (NumVals != 2)
138 return true;
139 unsigned RegOp = OpNo + 1;
140 if (RegOp >= MI->getNumOperands())
141 return true;
142 const MachineOperand &MO = MI->getOperand(RegOp);
143 if (!MO.isReg())
144 return true;
145 unsigned Reg = MO.getReg();
146 O << LanaiInstPrinter::getRegisterName(Reg);
147 return false;
148 }
149 default:
150 return true; // Unknown modifier.
151 }
152 }
153 printOperand(MI, OpNo, O);
154 return false;
155 }
156
157 //===----------------------------------------------------------------------===//
158 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
159 assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
160 "Unsupported call function");
161
162 LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
163 MCSubtargetInfo STI = getSubtargetInfo();
164 // Insert save rca instruction immediately before the call.
165 // TODO: We should generate a pc-relative mov instruction here instead
166 // of pc + 16 (should be mov .+16 %rca).
167 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
168 .addReg(Lanai::RCA)
169 .addReg(Lanai::PC)
170 .addImm(16),
171 STI);
172
173 // Push rca onto the stack.
174 // st %rca, [--%sp]
175 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
176 .addReg(Lanai::RCA)
177 .addReg(Lanai::SP)
178 .addImm(-4)
179 .addImm(LPAC::makePreOp(LPAC::ADD)),
180 STI);
181
182 // Lower the call instruction.
183 if (MI->getOpcode() == Lanai::CALL) {
184 MCInst TmpInst;
185 MCInstLowering.Lower(MI, TmpInst);
186 TmpInst.setOpcode(Lanai::BT);
187 OutStreamer->EmitInstruction(TmpInst, STI);
188 } else {
189 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
190 .addReg(Lanai::PC)
191 .addReg(MI->getOperand(0).getReg())
192 .addReg(Lanai::R0)
193 .addImm(LPCC::ICC_T),
194 STI);
195 }
196 }
197
198 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
199 LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
200 MCSubtargetInfo STI = getSubtargetInfo();
201 MCInst TmpInst;
202 MCInstLowering.Lower(MI, TmpInst);
203 OutStreamer->EmitInstruction(TmpInst, STI);
204 }
205
206 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
207 MachineBasicBlock::const_instr_iterator I = MI->getIterator();
208 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
209
210 do {
211 if (I->isCall()) {
212 emitCallInstruction(&*I);
213 continue;
214 }
215
216 customEmitInstruction(&*I);
217 } while ((++I != E) && I->isInsideBundle());
218 }
219
220 // isBlockOnlyReachableByFallthough - Return true if the basic block has
221 // exactly one predecessor and the control transfer mechanism between
222 // the predecessor and this block is a fall-through.
223 // FIXME: could the overridden cases be handled in AnalyzeBranch?
224 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
225 const MachineBasicBlock *MBB) const {
226 // The predecessor has to be immediately before this block.
227 const MachineBasicBlock *Pred = *MBB->pred_begin();
228
229 // If the predecessor is a switch statement, assume a jump table
230 // implementation, so it is not a fall through.
231 if (const BasicBlock *B = Pred->getBasicBlock())
232 if (isa(B->getTerminator()))
233 return false;
234
235 // Check default implementation
236 if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))
237 return false;
238
239 // Otherwise, check the last instruction.
240 // Check if the last terminator is an unconditional branch.
241 MachineBasicBlock::const_iterator I = Pred->end();
242 while (I != Pred->begin() && !(--I)->isTerminator()) {
243 }
244
245 return !I->isBarrier();
246 }
247
248 // Force static initialization.
249 extern "C" void LLVMInitializeLanaiAsmPrinter() {
250 RegisterAsmPrinter X(TheLanaiTarget);
251 }
0 //===- LanaiCallingConv.td - Calling Conventions Lanai -------*- tablegen -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This describes the calling conventions for the Lanai architectures.
10 //
11 //===----------------------------------------------------------------------===//
12
13 //===----------------------------------------------------------------------===//
14 // Return Value Calling Conventions
15 //===----------------------------------------------------------------------===//
16
17 // Lanai 32-bit C Calling convention.
18 def CC_Lanai32 : CallingConv<[
19 // Promote i8/i16 args to i32
20 CCIfType<[i8, i16], CCPromoteToType>,
21
22 // Put argument in registers if marked 'inreg' and not a vararg call.
23 CCIfNotVarArg
24 CCAssignToReg<[R6, R7, R18, R19]>>>>,
25
26 // Otherwise they are assigned to the stack in 4-byte aligned units.
27 CCAssignToStack<4, 4>
28 ]>;
29
30 // Lanai 32-bit Fast Calling convention.
31 def CC_Lanai32_Fast : CallingConv<[
32 // Promote i8/i16 args to i32
33 CCIfType<[ i8, i16 ], CCPromoteToType>,
34
35 // Put arguments in registers.
36 CCIfNotVarArg>>,
37
38 // Otherwise they are assigned to the stack in 4-byte aligned units.
39 CCAssignToStack<4, 4>
40 ]>;
41
42 // Lanai 32-bit C return-value convention.
43 def RetCC_Lanai32 : CallingConv<[
44 // Specify two registers to allow returning 64-bit results that have already
45 // been lowered to 2 32-bit values.
46 CCIfType<[i32], CCAssignToReg<[RV, R9]>>
47 ]>;
48
49 def CSR: CalleeSavedRegs<(add)>;
0 // The encoding used for conditional codes used in BR instructions
1
2 #ifndef LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
3 #define LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
4
5 #include "llvm/ADT/StringSwitch.h"
6
7 namespace llvm {
8 namespace LPCC {
9 enum CondCode {
10 ICC_T = 0, // true
11 ICC_F = 1, // false
12 ICC_HI = 2, // high
13 ICC_UGT = 2, // unsigned greater than
14 ICC_LS = 3, // low or same
15 ICC_ULE = 3, // unsigned less than or equal
16 ICC_CC = 4, // carry cleared
17 ICC_ULT = 4, // unsigned less than
18 ICC_CS = 5, // carry set
19 ICC_UGE = 5, // unsigned greater than or equal
20 ICC_NE = 6, // not equal
21 ICC_EQ = 7, // equal
22 ICC_VC = 8, // oVerflow cleared
23 ICC_VS = 9, // oVerflow set
24 ICC_PL = 10, // plus
25 ICC_MI = 11, // minus
26 ICC_GE = 12, // greater than or equal
27 ICC_LT = 13, // less than
28 ICC_GT = 14, // greater than
29 ICC_LE = 15, // less than or equal
30 UNKNOWN
31 };
32
33 inline static StringRef lanaiCondCodeToString(LPCC::CondCode CC) {
34 switch (CC) {
35 case LPCC::ICC_T:
36 return "t"; // true
37 case LPCC::ICC_F:
38 return "f"; // false
39 case LPCC::ICC_NE:
40 return "ne"; // not equal
41 case LPCC::ICC_EQ:
42 return "eq"; // equal
43 case LPCC::ICC_VC:
44 return "vc"; // oVerflow cleared
45 case LPCC::ICC_VS:
46 return "vs"; // oVerflow set
47 case LPCC::ICC_PL:
48 return "pl"; // plus
49 case LPCC::ICC_MI:
50 return "mi"; // minus
51 case LPCC::ICC_GE:
52 return "ge"; // greater than or equal
53 case LPCC::ICC_LT:
54 return "lt"; // less than
55 case LPCC::ICC_GT:
56 return "gt"; // greater than
57 case LPCC::ICC_LE:
58 return "le"; // less than or equal
59 case LPCC::ICC_UGT:
60 return "ugt"; // high | unsigned greater than
61 case LPCC::ICC_ULE:
62 return "ule"; // low or same | unsigned less or equal
63 case LPCC::ICC_ULT:
64 return "ult"; // carry cleared | unsigned less than
65 case LPCC::ICC_UGE:
66 return "uge"; // carry set | unsigned than or equal
67 default:
68 llvm_unreachable("Invalid cond code");
69 }
70 }
71
72 inline static CondCode suffixToLanaiCondCode(StringRef S) {
73 return StringSwitch(S)
74 .EndsWith("f", LPCC::ICC_F)
75 .EndsWith("hi", LPCC::ICC_HI)
76 .EndsWith("ugt", LPCC::ICC_UGT)
77 .EndsWith("ls", LPCC::ICC_LS)
78 .EndsWith("ule", LPCC::ICC_ULE)
79 .EndsWith("cc", LPCC::ICC_CC)
80 .EndsWith("ult", LPCC::ICC_ULT)
81 .EndsWith("cs", LPCC::ICC_CS)
82 .EndsWith("uge", LPCC::ICC_UGE)
83 .EndsWith("ne", LPCC::ICC_NE)
84 .EndsWith("eq", LPCC::ICC_EQ)
85 .EndsWith("vc", LPCC::ICC_VC)
86 .EndsWith("vs", LPCC::ICC_VS)
87 .EndsWith("pl", LPCC::ICC_PL)
88 .EndsWith("mi", LPCC::ICC_MI)
89 .EndsWith("ge", LPCC::ICC_GE)
90 .EndsWith("lt", LPCC::ICC_LT)
91 .EndsWith("gt", LPCC::ICC_GT)
92 .EndsWith("le", LPCC::ICC_LE)
93 .EndsWith("t", LPCC::ICC_T) // Has to be after others with suffix t
94 .Default(LPCC::UNKNOWN);
95 }
96 } // namespace LPCC
97 } // namespace llvm
98
99 #endif // LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
0 //===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Simple pass to fills delay slots with useful instructions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Lanai.h"
14 #include "LanaiTargetMachine.h"
15 #include "llvm/ADT/SmallSet.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Target/TargetInstrInfo.h"
21
22 using namespace llvm;
23
24 #define DEBUG_TYPE "delay-slot-filler"
25
26 STATISTIC(FilledSlots, "Number of delay slots filled");
27
28 static cl::opt
29 NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
30 cl::desc("Fill Lanai delay slots with NOPs."),
31 cl::Hidden);
32
33 namespace {
34 struct Filler : public MachineFunctionPass {
35 // Target machine description which we query for reg. names, data
36 // layout, etc.
37 const TargetInstrInfo *TII;
38 const TargetRegisterInfo *TRI;
39 MachineBasicBlock::instr_iterator LastFiller;
40
41 static char ID;
42 explicit Filler() : MachineFunctionPass(ID) {}
43
44 const char *getPassName() const override { return "Lanai Delay Slot Filler"; }
45
46 bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
47
48 bool runOnMachineFunction(MachineFunction &MF) override {
49 const LanaiSubtarget &Subtarget = MF.getSubtarget();
50 TII = Subtarget.getInstrInfo();
51 TRI = Subtarget.getRegisterInfo();
52
53 bool Changed = false;
54 for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
55 ++FI)
56 Changed |= runOnMachineBasicBlock(*FI);
57 return Changed;
58 }
59
60 void insertDefsUses(MachineBasicBlock::instr_iterator MI,
61 SmallSet &RegDefs,
62 SmallSet &RegUses);
63
64 bool isRegInSet(SmallSet &RegSet, unsigned Reg);
65
66 bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
67 bool &SawStore, SmallSet &RegDefs,
68 SmallSet &RegUses);
69
70 bool findDelayInstr(MachineBasicBlock &MBB,
71 MachineBasicBlock::instr_iterator Slot,
72 MachineBasicBlock::instr_iterator &Filler);
73 };
74 char Filler::ID = 0;
75 } // end of anonymous namespace
76
77 // createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
78 // slots in Lanai MachineFunctions
79 FunctionPass *
80 llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine &tm) {
81 return new Filler();
82 }
83
84 // runOnMachineBasicBlock - Fill in delay slots for the given basic block.
85 // There is one or two delay slot per delayed instruction.
86 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
87 bool Changed = false;
88 LastFiller = MBB.instr_end();
89
90 for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
91 I != MBB.instr_end(); ++I) {
92 if (I->getDesc().hasDelaySlot()) {
93 MachineBasicBlock::instr_iterator InstrWithSlot = I;
94 MachineBasicBlock::instr_iterator J = I;
95
96 // Treat RET specially as it is only instruction with 2 delay slots
97 // generated while all others generated have 1 delay slot.
98 if (I->getOpcode() == Lanai::RET) {
99 // RET is generated as part of epilogue generation and hence we know
100 // what the two instructions preceding it are and that it is safe to
101 // insert RET above them.
102 MachineBasicBlock::reverse_instr_iterator RI(I);
103 assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
104 RI->getOperand(0).getReg() == Lanai::FP &&
105 RI->getOperand(1).isReg() &&
106 RI->getOperand(1).getReg() == Lanai::FP &&
107 RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
108 ++RI;
109 assert(RI->getOpcode() == Lanai::ADD_I_LO &&
110 RI->getOperand(0).isReg() &&
111 RI->getOperand(0).getReg() == Lanai::SP &&
112 RI->getOperand(1).isReg() &&
113 RI->getOperand(1).getReg() == Lanai::FP);
114 ++RI;
115 MachineBasicBlock::instr_iterator FI(RI.base());
116 MBB.splice(std::next(I), &MBB, FI, I);
117 FilledSlots += 2;
118 } else {
119 if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) {
120 MBB.splice(std::next(I), &MBB, J);
121 } else {
122 BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
123 }
124 ++FilledSlots;
125 }
126
127 Changed = true;
128 // Record the filler instruction that filled the delay slot.
129 // The instruction after it will be visited in the next iteration.
130 LastFiller = ++I;
131
132 // Bundle the delay slot filler to InstrWithSlot so that the machine
133 // verifier doesn't expect this instruction to be a terminator.
134 MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
135 }
136 }
137 return Changed;
138 }
139
140 bool Filler::findDelayInstr(MachineBasicBlock &MBB,
141 MachineBasicBlock::instr_iterator Slot,
142 MachineBasicBlock::instr_iterator &Filler) {
143 SmallSet RegDefs;
144 SmallSet RegUses;
145
146 insertDefsUses(Slot, RegDefs, RegUses);
147
148 bool SawLoad = false;
149 bool SawStore = false;
150
151 for (MachineBasicBlock::reverse_instr_iterator I(Slot); I != MBB.instr_rend();
152 ++I) {
153 // skip debug value
154 if (I->isDebugValue())
155 continue;
156
157 // Convert to forward iterator.
158 MachineBasicBlock::instr_iterator FI(std::next(I).base());
159
160 if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
161 FI == LastFiller || I->isPseudo())
162 break;
163
164 if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
165 insertDefsUses(FI, RegDefs, RegUses);
166 continue;
167 }
168 Filler = FI;
169 return true;
170 }
171 return false;
172 }
173
174 bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
175 bool &SawStore, SmallSet &RegDefs,
176 SmallSet &RegUses) {
177 if (MI->isImplicitDef() || MI->isKill())
178 return true;
179
180 // Loads or stores cannot be moved past a store to the delay slot
181 // and stores cannot be moved past a load.
182 if (MI->mayLoad()) {
183 if (SawStore)
184 return true;
185 SawLoad = true;
186 }
187
188 if (MI->mayStore()) {
189 if (SawStore)
190 return true;
191 SawStore = true;
192 if (SawLoad)
193 return true;
194 }
195
196 assert((!MI->isCall() && !MI->isReturn()) &&
197 "Cannot put calls or returns in delay slot.");
198
199 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
200 const MachineOperand &MO = MI->getOperand(I);
201 unsigned Reg;
202
203 if (!MO.isReg() || !(Reg = MO.getReg()))
204 continue; // skip
205
206 if (MO.isDef()) {
207 // check whether Reg is defined or used before delay slot.
208 if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
209 return true;
210 }
211 if (MO.isUse()) {
212 // check whether Reg is defined before delay slot.
213 if (isRegInSet(RegDefs, Reg))
214 return true;
215 }
216 }
217 return false;
218 }
219
220 // Insert Defs and Uses of MI into the sets RegDefs and RegUses.
221 void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
222 SmallSet &RegDefs,
223 SmallSet &RegUses) {
224 // If MI is a call or return, just examine the explicit non-variadic operands.
225 MCInstrDesc MCID = MI->getDesc();
226 unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands()
227 : MI->getNumOperands();
228 for (unsigned I = 0; I != E; ++I) {
229 const MachineOperand &MO = MI->getOperand(I);
230 unsigned Reg;
231
232 if (!MO.isReg() || !(Reg = MO.getReg()))
233 continue;
234
235 if (MO.isDef())
236 RegDefs.insert(Reg);
237 else if (MO.isUse())
238 RegUses.insert(Reg);
239 }
240 }
241
242 // Returns true if the Reg or its alias is in the RegSet.
243 bool Filler::isRegInSet(SmallSet &RegSet, unsigned Reg) {
244 // Check Reg and all aliased Registers.
245 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
246 if (RegSet.count(*AI))
247 return true;
248 return false;
249 }
0 //===-- LanaiFrameLowering.cpp - Lanai Frame Information ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the Lanai implementation of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LanaiFrameLowering.h"
14
15 #include "LanaiInstrInfo.h"
16 #include "LanaiMachineFunctionInfo.h"
17 #include "LanaiSubtarget.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/IR/Function.h"
23
24 using namespace llvm;
25
26 // Determines the size of the frame and maximum call frame size.
27 void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
28 MachineFrameInfo *MFI = MF.getFrameInfo();
29 const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
30
31 // Get the number of bytes to allocate from the FrameInfo.
32 unsigned FrameSize = MFI->getStackSize();
33
34 // Get the alignment.
35 unsigned StackAlign = LRI->needsStackRealignment(MF) ? MFI->getMaxAlignment()
36 : getStackAlignment();
37
38 // Get the maximum call frame size of all the calls.
39 unsigned MaxCallFrameSize = MFI->getMaxCallFrameSize();
40
41 // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
42 // that allocations will be aligned.
43 if (MFI->hasVarSizedObjects())
44 MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
45
46 // Update maximum call frame size.
47 MFI->setMaxCallFrameSize(MaxCallFrameSize);
48
49 // Include call frame size in total.
50 if (!(hasReservedCallFrame(MF) && MFI->adjustsStack()))
51 FrameSize += MaxCallFrameSize;
52
53 // Make sure the frame is aligned.
54 FrameSize = alignTo(FrameSize, StackAlign);
55
56 // Update frame info.
57 MFI->setStackSize(FrameSize);
58 }
59
60 // Iterates through each basic block in a machine function and replaces
61 // ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
62 // maximum call frame size as the immediate.
63 void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
64 const LanaiInstrInfo &LII =
65 *static_cast(STI.getInstrInfo());
66 unsigned MaxCallFrameSize = MF.getFrameInfo()->getMaxCallFrameSize();
67
68 for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E;
69 ++MBB) {
70 MachineBasicBlock::iterator MBBI = MBB->begin();
71 while (MBBI != MBB->end()) {
72 MachineInstr *MI = MBBI++;
73 if (MI->getOpcode() == Lanai::ADJDYNALLOC) {
74 DebugLoc DL = MI->getDebugLoc();
75 unsigned Dst = MI->getOperand(0).getReg();
76 unsigned Src = MI->getOperand(1).getReg();
77
78 BuildMI(*MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
79 .addReg(Src)
80 .addImm(MaxCallFrameSize);
81 MI->eraseFromParent();
82 }
83 }
84 }
85 }
86
87 // Generates the following sequence for function entry:
88 // st %fp,-4[*%sp] !push old FP
89 // add %sp,8,%fp !generate new FP
90 // sub %sp,0x4,%sp !allocate stack space (as needed)
91 void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
92 MachineBasicBlock &MBB) const {
93 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
94
95 MachineFrameInfo *MFI = MF.getFrameInfo();
96 const LanaiInstrInfo &LII =
97 *static_cast(STI.getInstrInfo());
98 MachineBasicBlock::iterator MBBI = MBB.begin();
99
100 // Debug location must be unknown since the first debug location is used
101 // to determine the end of the prologue.
102 DebugLoc DL;
103
104 // Determine the correct frame layout
105 determineFrameLayout(MF);
106
107 // FIXME: This appears to be overallocating. Needs investigation.
108 // Get the number of bytes to allocate from the FrameInfo.
109 unsigned StackSize = MFI->getStackSize();
110
111 // Push old FP
112 // st %fp,-4[*%sp]
113 BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
114 .addReg(Lanai::FP)
115 .addReg(Lanai::SP)
116 .addImm(-4)
117 .addImm(LPAC::makePreOp(LPAC::ADD))
118 .setMIFlag(MachineInstr::FrameSetup);
119
120 // Generate new FP
121 // add %sp,8,%fp
122 BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
123 .addReg(Lanai::SP)
124 .addImm(8)
125 .setMIFlag(MachineInstr::FrameSetup);
126
127 // Allocate space on the stack if needed
128 // sub %sp,StackSize,%sp
129 if (StackSize != 0) {
130 BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
131 .addReg(Lanai::SP)
132 .addImm(StackSize)
133 .setMIFlag(MachineInstr::FrameSetup);
134 }
135
136 // Replace ADJDYNANALLOC
137 if (MFI->hasVarSizedObjects())
138 replaceAdjDynAllocPseudo(MF);
139 }
140
141 void LanaiFrameLowering::eliminateCallFramePseudoInstr(
142 MachineFunction &MF, MachineBasicBlock &MBB,
143 MachineBasicBlock::iterator I) const {
144 // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
145 MBB.erase(I);
146 }
147
148 // The function epilogue should not depend on the current stack pointer!
149 // It should use the frame pointer only. This is mandatory because
150 // of alloca; we also take advantage of it to omit stack adjustments
151 // before returning.
152 //
153 // Note that when we go to restore the preserved register values we must
154 // not try to address their slots by using offsets from the stack pointer.
155 // That's because the stack pointer may have been moved during the function
156 // execution due to a call to alloca(). Rather, we must restore all
157 // preserved registers via offsets from the frame pointer value.
158 //
159 // Note also that when the current frame is being "popped" (by adjusting
160 // the value of the stack pointer) on function exit, we must (for the
161 // sake of alloca) set the new value of the stack pointer based upon
162 // the current value of the frame pointer. We can't just add what we
163 // believe to be the (static) frame size to the stack pointer because
164 // if we did that, and alloca() had been called during this function,
165 // we would end up returning *without* having fully deallocated all of
166 // the space grabbed by alloca. If that happened, and a function
167 // containing one or more alloca() calls was called over and over again,
168 // then the stack would grow without limit!
169 //
170 // RET is lowered to
171 // ld -4[%fp],%pc # modify %pc (two delay slots)
172 // as the return address is in the stack frame and mov to pc is allowed.
173 // emitEpilogue emits
174 // mov %fp,%sp # restore the stack pointer
175 // ld -8[%fp],%fp # restore the caller's frame pointer
176 // before RET and the delay slot filler will move RET such that these
177 // instructions execute in the delay slots of the load to PC.
178 void LanaiFrameLowering::emitEpilogue(MachineFunction &MF,
179 MachineBasicBlock &MBB) const {
180 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
181 const LanaiInstrInfo &LII =
182 *static_cast(STI.getInstrInfo());
183 DebugLoc DL = MBBI->getDebugLoc();
184
185 // Restore the stack pointer using the callee's frame pointer value.
186 BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
187 .addReg(Lanai::FP)
188 .addImm(0);
189
190 // Restore the frame pointer from the stack.
191 BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
192 .addReg(Lanai::FP)
193 .addImm(-8)
194 .addImm(LPAC::ADD);
195 }
196
197 void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
198 BitVector &SavedRegs,
199 RegScavenger *RS) const {
200 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
201
202 MachineFrameInfo *MFI = MF.getFrameInfo();
203 const LanaiRegisterInfo *LRI =
204 static_cast(STI.getRegisterInfo());
205 int Offset = -4;
206
207 // Reserve 4 bytes for the saved RCA
208 MFI->CreateFixedObject(4, Offset, true);
209 Offset -= 4;
210
211 // Reserve 4 bytes for the saved FP
212 MFI->CreateFixedObject(4, Offset, true);
213 Offset -= 4;
214
215 if (LRI->hasBasePointer(MF)) {
216 MFI->CreateFixedObject(4, Offset, true);
217 SavedRegs.reset(LRI->getBaseRegister());
218 }
219 }
0 //===-- LanaiFrameLowering.h - Define frame lowering for Lanai --*- C++-*--===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class implements Lanai-specific bits of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
14 #define LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
15
16 #include "Lanai.h"
17 #include "llvm/Target/TargetFrameLowering.h"
18
19 namespace llvm {
20
21 class BitVector;
22 class LanaiSubtarget;
23
24 class LanaiFrameLowering : public TargetFrameLowering {
25 private:
26 void determineFrameLayout(MachineFunction &MF) const;
27 void replaceAdjDynAllocPseudo(MachineFunction &MF) const;
28
29 protected:
30 const LanaiSubtarget &STI;
31
32 public:
33 explicit LanaiFrameLowering(const LanaiSubtarget &Subtarget)
34 : TargetFrameLowering(StackGrowsDown,
35 /*StackAlignment=*/8,
36 /*LocalAreaOffset=*/0),
37 STI(Subtarget) {}
38
39 // emitProlog/emitEpilog - These methods insert prolog and epilog code into
40 // the function.
41 void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
42 void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
43
44 void
45 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
46 MachineBasicBlock::iterator I) const override;
47
48 bool hasFP(const MachineFunction &MF) const override { return true; }
49
50 void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
51 RegScavenger *RS = nullptr) const override;
52 };
53
54 } // namespace llvm
55
56 #endif // LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
0 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an instruction selector for the Lanai target.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Lanai.h"
14 #include "LanaiMachineFunctionInfo.h"
15 #include "LanaiRegisterInfo.h"
16 #include "LanaiSubtarget.h"
17 #include "LanaiTargetMachine.h"
18 #include "llvm/CodeGen/MachineConstantPool.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/SelectionDAGISel.h"
24 #include "llvm/IR/CFG.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/Intrinsics.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
33
34 using namespace llvm;
35
36 #define DEBUG_TYPE "lanai-isel"
37
38 //===----------------------------------------------------------------------===//
39 // Instruction Selector Implementation
40 //===----------------------------------------------------------------------===//
41
42 //===----------------------------------------------------------------------===//
43 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
44 // instructions for SelectionDAG operations.
45 //===----------------------------------------------------------------------===//
46 namespace {
47
48 class LanaiDAGToDAGISel : public SelectionDAGISel {
49 public:
50 explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
51 : SelectionDAGISel(TargetMachine) {}
52
53 bool runOnMachineFunction(MachineFunction &MF) override {
54 return SelectionDAGISel::runOnMachineFunction(MF);
55 }
56
57 // Pass Name
58 const char *getPassName() const override {
59 return "Lanai DAG->DAG Pattern Instruction Selection";
60 }
61
62 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
63 std::vector &OutOps) override;
64
65 private:
66 // Include the pieces autogenerated from the target description.
67 #include "LanaiGenDAGISel.inc"
68
69 // Instruction Selection not handled by the auto-generated tablgen
70 SDNode *Select(SDNode *N) override;
71
72 // Support functions for the opcodes of Instruction Selection
73 // not handled by the auto-generated tablgen
74 SDNode *selectFrameIndex(SDNode *N);
75
76 // Complex Pattern for address selection.
77 bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,
78 SDValue &AluOp);
79 bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);
80 bool selectAddrSls(SDValue Addr, SDValue &Offset);
81 bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
82 SDValue &AluOp);
83
84 // getI32Imm - Return a target constant with the specified value, of type i32.
85 inline SDValue getI32Imm(unsigned Imm, SDLoc DL) {
86 return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
87 }
88
89 private:
90 bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
91 SDValue &AluOp, bool RiMode);
92 };
93
94 bool canBeRepresentedAsSls(const ConstantSDNode &CN) {
95 // Fits in 21-bit signed immediate and two low-order bits are zero.
96 return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);
97 }
98
99 } // namespace
100
101 // Helper functions for ComplexPattern used on LanaiInstrInfo
102 // Used on Lanai Load/Store instructions.
103 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
104 if (ConstantSDNode *CN = dyn_cast(Addr)) {
105 SDLoc DL(Addr);
106 // Loading from a constant address.
107 if (canBeRepresentedAsSls(*CN)) {
108 int32_t Imm = CN->getSExtValue();
109 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
110 return true;
111 }
112 }
113 if (Addr.getOpcode() == ISD::OR &&
114 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
115 Offset = Addr.getOperand(1).getOperand(0);
116 return true;
117 }
118 return false;
119 }
120
121 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
122 SDValue &Offset, SDValue &AluOp,
123 bool RiMode) {
124 SDLoc DL(Addr);
125
126 if (ConstantSDNode *CN = dyn_cast(Addr)) {
127 if (RiMode) {
128 // Fits in 16-bit signed immediate.
129 if (isInt<16>(CN->getSExtValue())) {
130 int16_t Imm = CN->getSExtValue();
131 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
132 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
133 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
134 return true;
135 }
136 // Allow SLS to match if the constant doesn't fit in 16 bits but can be
137 // represented as an SLS.
138 if (canBeRepresentedAsSls(*CN))
139 return false;
140 } else {
141 // Fits in 10-bit signed immediate.
142 if (isInt<10>(CN->getSExtValue())) {
143 int16_t Imm = CN->getSExtValue();
144 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
145 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
146 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
147 return true;
148 }
149 }
150 }
151
152 // if Address is FI, get the TargetFrameIndex.
153 if (FrameIndexSDNode *FIN = dyn_cast(Addr)) {
154 Base = CurDAG->getTargetFrameIndex(
155 FIN->getIndex(),
156 getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
157 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
158 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
159 return true;
160 }
161
162 // Skip direct calls
163 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
164 Addr.getOpcode() == ISD::TargetGlobalAddress))
165 return false;
166
167 // Address of the form imm + reg
168 ISD::NodeType AluOperator = static_cast(Addr.getOpcode());
169 if (AluOperator == ISD::ADD) {
170 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
171 // Addresses of the form FI+const
172 if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)))
173 if ((RiMode && isInt<16>(CN->getSExtValue())) ||
174 (!RiMode && isInt<10>(CN->getSExtValue()))) {
175 // If the first operand is a FI, get the TargetFI Node
176 if (FrameIndexSDNode *FIN =
177 dyn_cast(Addr.getOperand(0))) {
178 Base = CurDAG->getTargetFrameIndex(
179 FIN->getIndex(),
180 getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
181 } else {
182 Base = Addr.getOperand(0);
183 }
184
185 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
186 return true;
187 }
188 }
189
190 // Let SLS match SMALL instead of RI.
191 if (AluOperator == ISD::OR && RiMode &&
192 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
193 return false;
194
195 Base = Addr;
196 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
197 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
198 return true;
199 }
200
201 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
202 SDValue &Offset, SDValue &AluOp) {
203 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RImode=*/true);
204 }
205
206 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
207 SDValue &Offset, SDValue &AluOp) {
208 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
209 }
210
211 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
212 SDValue &AluOp) {
213 // if Address is FI, get the TargetFrameIndex.
214 if (Addr.getOpcode() == ISD::FrameIndex)
215 return false;
216
217 // Skip direct calls
218 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
219 Addr.getOpcode() == ISD::TargetGlobalAddress))
220 return false;
221
222 // Address of the form OP + OP
223 ISD::NodeType AluOperator = static_cast(Addr.getOpcode());
224 LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator);
225 if (AluCode != LPAC::UNKNOWN) {
226 // Skip addresses of the form FI OP const
227 if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)))
228 if (isInt<16>(CN->getSExtValue()))
229 return false;
230
231 // Skip addresses with hi/lo operands
232 if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
233 Addr.getOperand(0).getOpcode() == LanaiISD::LO ||
234 Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||
235 Addr.getOperand(1).getOpcode() == LanaiISD::HI ||
236 Addr.getOperand(1).getOpcode() == LanaiISD::LO ||
237 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
238 return false;
239
240 // Addresses of the form register OP register
241 R1 = Addr.getOperand(0);
242 R2 = Addr.getOperand(1);
243 AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
244 return true;
245 }
246
247 // Skip addresses with zero offset
248 return false;
249 }
250
251 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
252 const SDValue &Op, unsigned ConstraintCode, std::vector &OutOps) {
253 SDValue Op0, Op1, AluOp;
254 switch (ConstraintCode) {
255 default:
256 return true;
257 case InlineAsm::Constraint_m: // memory
258 if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
259 !selectAddrRi(Op, Op0, Op1, AluOp))
260 return true;
261 break;
262 }
263
264 OutOps.push_back(Op0);
265 OutOps.push_back(Op1);
266 OutOps.push_back(AluOp);
267 return false;
268 }
269
270 // Select instructions not customized! Used for
271 // expanded, promoted and normal instructions
272 SDNode *LanaiDAGToDAGISel::Select(SDNode *Node) {
273 unsigned Opcode = Node->getOpcode();
274
275 // Dump information about the Node being selected
276 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
277
278 // If we have a custom node, we already have selected!
279 if (Node->isMachineOpcode()) {
280 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
281 return NULL;
282 }