EDEmitter.cpp revision e6913600c723a10ab1f06a43c93d82ee8e26c71c
1//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This tablegen backend is responsible for emitting a description of each 11// instruction in a format that the enhanced disassembler can use to tokenize 12// and parse instructions. 13// 14//===----------------------------------------------------------------------===// 15 16#include "EDEmitter.h" 17 18#include "AsmWriterInst.h" 19#include "CodeGenTarget.h" 20#include "Record.h" 21 22#include "llvm/MC/EDInstInfo.h" 23#include "llvm/Support/ErrorHandling.h" 24#include "llvm/Support/Format.h" 25#include "llvm/Support/raw_ostream.h" 26 27#include <map> 28#include <string> 29#include <vector> 30 31using namespace llvm; 32 33/////////////////////////////////////////////////////////// 34// Support classes for emitting nested C data structures // 35/////////////////////////////////////////////////////////// 36 37namespace { 38 39 class EnumEmitter { 40 private: 41 std::string Name; 42 std::vector<std::string> Entries; 43 public: 44 EnumEmitter(const char *N) : Name(N) { 45 } 46 int addEntry(const char *e) { 47 Entries.push_back(std::string(e)); 48 return Entries.size() - 1; 49 } 50 void emit(raw_ostream &o, unsigned int &i) { 51 o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; 52 i += 2; 53 54 unsigned int index = 0; 55 unsigned int numEntries = Entries.size(); 56 for (index = 0; index < numEntries; ++index) { 57 o.indent(i) << Entries[index]; 58 if (index < (numEntries - 1)) 59 o << ","; 60 o << "\n"; 61 } 62 63 i -= 2; 64 o.indent(i) << "};" << "\n"; 65 } 66 67 void emitAsFlags(raw_ostream &o, unsigned int &i) { 68 o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; 69 i += 2; 70 71 unsigned int index = 0; 72 unsigned int numEntries = Entries.size(); 73 unsigned int flag = 1; 74 for (index = 0; index < numEntries; ++index) { 75 o.indent(i) << Entries[index] << " = " << format("0x%x", flag); 76 if (index < (numEntries - 1)) 77 o << ","; 78 o << "\n"; 79 flag <<= 1; 80 } 81 82 i -= 2; 83 o.indent(i) << "};" << "\n"; 84 } 85 }; 86 87 class ConstantEmitter { 88 public: 89 virtual ~ConstantEmitter() { } 90 virtual void emit(raw_ostream &o, unsigned int &i) = 0; 91 }; 92 93 class LiteralConstantEmitter : public ConstantEmitter { 94 private: 95 bool IsNumber; 96 union { 97 int Number; 98 const char* String; 99 }; 100 public: 101 LiteralConstantEmitter(int number = 0) : 102 IsNumber(true), 103 Number(number) { 104 } 105 void set(const char *string) { 106 IsNumber = false; 107 Number = 0; 108 String = string; 109 } 110 bool is(const char *string) { 111 return !strcmp(String, string); 112 } 113 void emit(raw_ostream &o, unsigned int &i) { 114 if (IsNumber) 115 o << Number; 116 else 117 o << String; 118 } 119 }; 120 121 class CompoundConstantEmitter : public ConstantEmitter { 122 private: 123 unsigned int Padding; 124 std::vector<ConstantEmitter *> Entries; 125 public: 126 CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) { 127 } 128 CompoundConstantEmitter &addEntry(ConstantEmitter *e) { 129 Entries.push_back(e); 130 131 return *this; 132 } 133 ~CompoundConstantEmitter() { 134 while (Entries.size()) { 135 ConstantEmitter *entry = Entries.back(); 136 Entries.pop_back(); 137 delete entry; 138 } 139 } 140 void emit(raw_ostream &o, unsigned int &i) { 141 o << "{" << "\n"; 142 i += 2; 143 144 unsigned int index; 145 unsigned int numEntries = Entries.size(); 146 147 unsigned int numToPrint; 148 149 if (Padding) { 150 if (numEntries > Padding) { 151 fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); 152 llvm_unreachable("More entries than padding"); 153 } 154 numToPrint = Padding; 155 } else { 156 numToPrint = numEntries; 157 } 158 159 for (index = 0; index < numToPrint; ++index) { 160 o.indent(i); 161 if (index < numEntries) 162 Entries[index]->emit(o, i); 163 else 164 o << "-1"; 165 166 if (index < (numToPrint - 1)) 167 o << ","; 168 o << "\n"; 169 } 170 171 i -= 2; 172 o.indent(i) << "}"; 173 } 174 }; 175 176 class FlagsConstantEmitter : public ConstantEmitter { 177 private: 178 std::vector<std::string> Flags; 179 public: 180 FlagsConstantEmitter() { 181 } 182 FlagsConstantEmitter &addEntry(const char *f) { 183 Flags.push_back(std::string(f)); 184 return *this; 185 } 186 void emit(raw_ostream &o, unsigned int &i) { 187 unsigned int index; 188 unsigned int numFlags = Flags.size(); 189 if (numFlags == 0) 190 o << "0"; 191 192 for (index = 0; index < numFlags; ++index) { 193 o << Flags[index].c_str(); 194 if (index < (numFlags - 1)) 195 o << " | "; 196 } 197 } 198 }; 199} 200 201EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) { 202} 203 204/// populateOperandOrder - Accepts a CodeGenInstruction and generates its 205/// AsmWriterInst for the desired assembly syntax, giving an ordered list of 206/// operands in the order they appear in the printed instruction. Then, for 207/// each entry in that list, determines the index of the same operand in the 208/// CodeGenInstruction, and emits the resulting mapping into an array, filling 209/// in unused slots with -1. 210/// 211/// @arg operandOrder - The array that will be populated with the operand 212/// mapping. Each entry will contain -1 (invalid index 213/// into the operands present in the AsmString) or a number 214/// representing an index in the operand descriptor array. 215/// @arg inst - The instruction to use when looking up the operands 216/// @arg syntax - The syntax to use, according to LLVM's enumeration 217void populateOperandOrder(CompoundConstantEmitter *operandOrder, 218 const CodeGenInstruction &inst, 219 unsigned syntax) { 220 unsigned int numArgs = 0; 221 222 AsmWriterInst awInst(inst, syntax, -1, -1); 223 224 std::vector<AsmWriterOperand>::iterator operandIterator; 225 226 for (operandIterator = awInst.Operands.begin(); 227 operandIterator != awInst.Operands.end(); 228 ++operandIterator) { 229 if (operandIterator->OperandType == 230 AsmWriterOperand::isMachineInstrOperand) { 231 operandOrder->addEntry( 232 new LiteralConstantEmitter(operandIterator->CGIOpNo)); 233 numArgs++; 234 } 235 } 236} 237 238///////////////////////////////////////////////////// 239// Support functions for handling X86 instructions // 240///////////////////////////////////////////////////// 241 242#define SET(flag) { type->set(flag); return 0; } 243 244#define REG(str) if (name == str) SET("kOperandTypeRegister"); 245#define MEM(str) if (name == str) SET("kOperandTypeX86Memory"); 246#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress"); 247#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); 248#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative"); 249 250/// X86TypeFromOpName - Processes the name of a single X86 operand (which is 251/// actually its type) and translates it into an operand type 252/// 253/// @arg flags - The type object to set 254/// @arg name - The name of the operand 255static int X86TypeFromOpName(LiteralConstantEmitter *type, 256 const std::string &name) { 257 REG("GR8"); 258 REG("GR8_NOREX"); 259 REG("GR16"); 260 REG("GR32"); 261 REG("GR32_NOREX"); 262 REG("GR32_TC"); 263 REG("FR32"); 264 REG("RFP32"); 265 REG("GR64"); 266 REG("GR64_TC"); 267 REG("FR64"); 268 REG("VR64"); 269 REG("RFP64"); 270 REG("RFP80"); 271 REG("VR128"); 272 REG("VR256"); 273 REG("RST"); 274 REG("SEGMENT_REG"); 275 REG("DEBUG_REG"); 276 REG("CONTROL_REG"); 277 278 IMM("i8imm"); 279 IMM("i16imm"); 280 IMM("i16i8imm"); 281 IMM("i32imm"); 282 IMM("i32i8imm"); 283 IMM("i64imm"); 284 IMM("i64i8imm"); 285 IMM("i64i32imm"); 286 IMM("SSECC"); 287 288 // all R, I, R, I, R 289 MEM("i8mem"); 290 MEM("i8mem_NOREX"); 291 MEM("i16mem"); 292 MEM("i32mem"); 293 MEM("i32mem_TC"); 294 MEM("f32mem"); 295 MEM("ssmem"); 296 MEM("opaque32mem"); 297 MEM("opaque48mem"); 298 MEM("i64mem"); 299 MEM("i64mem_TC"); 300 MEM("f64mem"); 301 MEM("sdmem"); 302 MEM("f80mem"); 303 MEM("opaque80mem"); 304 MEM("i128mem"); 305 MEM("i256mem"); 306 MEM("f128mem"); 307 MEM("f256mem"); 308 MEM("opaque512mem"); 309 310 // all R, I, R, I 311 LEA("lea32mem"); 312 LEA("lea64_32mem"); 313 LEA("lea64mem"); 314 315 // all I 316 PCR("i16imm_pcrel"); 317 PCR("i32imm_pcrel"); 318 PCR("i64i32imm_pcrel"); 319 PCR("brtarget8"); 320 PCR("offset8"); 321 PCR("offset16"); 322 PCR("offset32"); 323 PCR("offset64"); 324 PCR("brtarget"); 325 326 return 1; 327} 328 329#undef REG 330#undef MEM 331#undef LEA 332#undef IMM 333#undef PCR 334 335#undef SET 336 337/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding 338/// the appropriate flags to their descriptors 339/// 340/// @operandFlags - A reference the array of operand flag objects 341/// @inst - The instruction to use as a source of information 342static void X86PopulateOperands( 343 LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], 344 const CodeGenInstruction &inst) { 345 if (!inst.TheDef->isSubClassOf("X86Inst")) 346 return; 347 348 unsigned int index; 349 unsigned int numOperands = inst.Operands.size(); 350 351 for (index = 0; index < numOperands; ++index) { 352 const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; 353 Record &rec = *operandInfo.Rec; 354 355 if (X86TypeFromOpName(operandTypes[index], rec.getName())) { 356 errs() << "Operand type: " << rec.getName().c_str() << "\n"; 357 errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; 358 errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n"; 359 llvm_unreachable("Unhandled type"); 360 } 361 } 362} 363 364/// decorate1 - Decorates a named operand with a new flag 365/// 366/// @operandFlags - The array of operand flag objects, which don't have names 367/// @inst - The CodeGenInstruction, which provides a way to translate 368/// between names and operand indices 369/// @opName - The name of the operand 370/// @flag - The name of the flag to add 371static inline void decorate1( 372 FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], 373 const CodeGenInstruction &inst, 374 const char *opName, 375 const char *opFlag) { 376 unsigned opIndex; 377 378 opIndex = inst.Operands.getOperandNamed(std::string(opName)); 379 380 operandFlags[opIndex]->addEntry(opFlag); 381} 382 383#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) 384 385#define MOV(source, target) { \ 386 instType.set("kInstructionTypeMove"); \ 387 DECORATE1(source, "kOperandFlagSource"); \ 388 DECORATE1(target, "kOperandFlagTarget"); \ 389} 390 391#define BRANCH(target) { \ 392 instType.set("kInstructionTypeBranch"); \ 393 DECORATE1(target, "kOperandFlagTarget"); \ 394} 395 396#define PUSH(source) { \ 397 instType.set("kInstructionTypePush"); \ 398 DECORATE1(source, "kOperandFlagSource"); \ 399} 400 401#define POP(target) { \ 402 instType.set("kInstructionTypePop"); \ 403 DECORATE1(target, "kOperandFlagTarget"); \ 404} 405 406#define CALL(target) { \ 407 instType.set("kInstructionTypeCall"); \ 408 DECORATE1(target, "kOperandFlagTarget"); \ 409} 410 411#define RETURN() { \ 412 instType.set("kInstructionTypeReturn"); \ 413} 414 415/// X86ExtractSemantics - Performs various checks on the name of an X86 416/// instruction to determine what sort of an instruction it is and then adds 417/// the appropriate flags to the instruction and its operands 418/// 419/// @arg instType - A reference to the type for the instruction as a whole 420/// @arg operandFlags - A reference to the array of operand flag object pointers 421/// @arg inst - A reference to the original instruction 422static void X86ExtractSemantics( 423 LiteralConstantEmitter &instType, 424 FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], 425 const CodeGenInstruction &inst) { 426 const std::string &name = inst.TheDef->getName(); 427 428 if (name.find("MOV") != name.npos) { 429 if (name.find("MOV_V") != name.npos) { 430 // ignore (this is a pseudoinstruction) 431 } else if (name.find("MASK") != name.npos) { 432 // ignore (this is a masking move) 433 } else if (name.find("r0") != name.npos) { 434 // ignore (this is a pseudoinstruction) 435 } else if (name.find("PS") != name.npos || 436 name.find("PD") != name.npos) { 437 // ignore (this is a shuffling move) 438 } else if (name.find("MOVS") != name.npos) { 439 // ignore (this is a string move) 440 } else if (name.find("_F") != name.npos) { 441 // TODO handle _F moves to ST(0) 442 } else if (name.find("a") != name.npos) { 443 // TODO handle moves to/from %ax 444 } else if (name.find("CMOV") != name.npos) { 445 MOV("src2", "dst"); 446 } else if (name.find("PC") != name.npos) { 447 MOV("label", "reg") 448 } else { 449 MOV("src", "dst"); 450 } 451 } 452 453 if (name.find("JMP") != name.npos || 454 name.find("J") == 0) { 455 if (name.find("FAR") != name.npos && name.find("i") != name.npos) { 456 BRANCH("off"); 457 } else { 458 BRANCH("dst"); 459 } 460 } 461 462 if (name.find("PUSH") != name.npos) { 463 if (name.find("CS") != name.npos || 464 name.find("DS") != name.npos || 465 name.find("ES") != name.npos || 466 name.find("FS") != name.npos || 467 name.find("GS") != name.npos || 468 name.find("SS") != name.npos) { 469 instType.set("kInstructionTypePush"); 470 // TODO add support for fixed operands 471 } else if (name.find("F") != name.npos) { 472 // ignore (this pushes onto the FP stack) 473 } else if (name.find("A") != name.npos) { 474 // ignore (pushes all GP registoers onto the stack) 475 } else if (name[name.length() - 1] == 'm') { 476 PUSH("src"); 477 } else if (name.find("i") != name.npos) { 478 PUSH("imm"); 479 } else { 480 PUSH("reg"); 481 } 482 } 483 484 if (name.find("POP") != name.npos) { 485 if (name.find("POPCNT") != name.npos) { 486 // ignore (not a real pop) 487 } else if (name.find("CS") != name.npos || 488 name.find("DS") != name.npos || 489 name.find("ES") != name.npos || 490 name.find("FS") != name.npos || 491 name.find("GS") != name.npos || 492 name.find("SS") != name.npos) { 493 instType.set("kInstructionTypePop"); 494 // TODO add support for fixed operands 495 } else if (name.find("F") != name.npos) { 496 // ignore (this pops from the FP stack) 497 } else if (name.find("A") != name.npos) { 498 // ignore (pushes all GP registoers onto the stack) 499 } else if (name[name.length() - 1] == 'm') { 500 POP("dst"); 501 } else { 502 POP("reg"); 503 } 504 } 505 506 if (name.find("CALL") != name.npos) { 507 if (name.find("ADJ") != name.npos) { 508 // ignore (not a call) 509 } else if (name.find("SYSCALL") != name.npos) { 510 // ignore (doesn't go anywhere we know about) 511 } else if (name.find("VMCALL") != name.npos) { 512 // ignore (rather different semantics than a regular call) 513 } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { 514 CALL("off"); 515 } else { 516 CALL("dst"); 517 } 518 } 519 520 if (name.find("RET") != name.npos) { 521 RETURN(); 522 } 523} 524 525#undef MOV 526#undef BRANCH 527#undef PUSH 528#undef POP 529#undef CALL 530#undef RETURN 531 532///////////////////////////////////////////////////// 533// Support functions for handling ARM instructions // 534///////////////////////////////////////////////////// 535 536#define SET(flag) { type->set(flag); return 0; } 537 538#define REG(str) if (name == str) SET("kOperandTypeRegister"); 539#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); 540 541#define MISC(str, type) if (name == str) SET(type); 542 543/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is 544/// actually its type) and translates it into an operand type 545/// 546/// @arg type - The type object to set 547/// @arg name - The name of the operand 548static int ARMFlagFromOpName(LiteralConstantEmitter *type, 549 const std::string &name) { 550 REG("GPR"); 551 REG("rGPR"); 552 REG("tcGPR"); 553 REG("cc_out"); 554 REG("s_cc_out"); 555 REG("tGPR"); 556 REG("DPR"); 557 REG("DPR_VFP2"); 558 REG("DPR_8"); 559 REG("SPR"); 560 REG("QPR"); 561 REG("QQPR"); 562 REG("QQQQPR"); 563 564 IMM("i32imm"); 565 IMM("bf_inv_mask_imm"); 566 IMM("jtblock_operand"); 567 IMM("nohash_imm"); 568 IMM("cpinst_operand"); 569 IMM("setend_op"); 570 IMM("cps_opt"); 571 IMM("vfp_f64imm"); 572 IMM("vfp_f32imm"); 573 IMM("memb_opt"); 574 IMM("msr_mask"); 575 IMM("neg_zero"); 576 IMM("imm0_31"); 577 IMM("imm0_31_m1"); 578 IMM("nModImm"); 579 IMM("imm0_4095"); 580 IMM("jt2block_operand"); 581 IMM("t_imm_s4"); 582 IMM("pclabel"); 583 IMM("shift_imm"); 584 IMM("neon_vcvt_imm32"); 585 586 MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? 587 MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I 588 MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I 589 MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I 590 MISC("so_imm", "kOperandTypeARMSoImm"); // I 591 MISC("rot_imm", "kOperandTypeARMRotImm"); // I 592 MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I 593 MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I 594 MISC("pred", "kOperandTypeARMPredicate"); // I, R 595 MISC("it_pred", "kOperandTypeARMPredicate"); // I 596 MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I 597 MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I 598 MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I 599 MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I 600 MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I 601 MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I 602 MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I 603 MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I 604 MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I 605 MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I 606 MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I 607 MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... 608 MISC("it_mask", "kOperandTypeThumbITMask"); // I 609 MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I 610 MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I 611 MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I 612 MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I 613 MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I 614 MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); 615 // R, I 616 MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I 617 MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R 618 MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R 619 MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R 620 MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R 621 MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I 622 623 return 1; 624} 625 626#undef SOREG 627#undef SOIMM 628#undef PRED 629#undef REG 630#undef MEM 631#undef LEA 632#undef IMM 633#undef PCR 634 635#undef SET 636 637/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding 638/// the appropriate flags to their descriptors 639/// 640/// @operandFlags - A reference the array of operand flag objects 641/// @inst - The instruction to use as a source of information 642static void ARMPopulateOperands( 643 LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], 644 const CodeGenInstruction &inst) { 645 if (!inst.TheDef->isSubClassOf("InstARM") && 646 !inst.TheDef->isSubClassOf("InstThumb")) 647 return; 648 649 unsigned int index; 650 unsigned int numOperands = inst.Operands.size(); 651 652 if (numOperands > EDIS_MAX_OPERANDS) { 653 errs() << "numOperands == " << numOperands << " > " << 654 EDIS_MAX_OPERANDS << '\n'; 655 llvm_unreachable("Too many operands"); 656 } 657 658 for (index = 0; index < numOperands; ++index) { 659 const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; 660 Record &rec = *operandInfo.Rec; 661 662 if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { 663 errs() << "Operand type: " << rec.getName() << '\n'; 664 errs() << "Operand name: " << operandInfo.Name << '\n'; 665 errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; 666 llvm_unreachable("Unhandled type"); 667 } 668 } 669} 670 671#define BRANCH(target) { \ 672 instType.set("kInstructionTypeBranch"); \ 673 DECORATE1(target, "kOperandFlagTarget"); \ 674} 675 676/// ARMExtractSemantics - Performs various checks on the name of an ARM 677/// instruction to determine what sort of an instruction it is and then adds 678/// the appropriate flags to the instruction and its operands 679/// 680/// @arg instType - A reference to the type for the instruction as a whole 681/// @arg operandTypes - A reference to the array of operand type object pointers 682/// @arg operandFlags - A reference to the array of operand flag object pointers 683/// @arg inst - A reference to the original instruction 684static void ARMExtractSemantics( 685 LiteralConstantEmitter &instType, 686 LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], 687 FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], 688 const CodeGenInstruction &inst) { 689 const std::string &name = inst.TheDef->getName(); 690 691 if (name == "tBcc" || 692 name == "tB" || 693 name == "t2Bcc" || 694 name == "Bcc" || 695 name == "tCBZ" || 696 name == "tCBNZ") { 697 BRANCH("target"); 698 } 699 700 if (name == "tBLr9" || 701 name == "BLr9_pred" || 702 name == "tBLXi_r9" || 703 name == "tBLXr_r9" || 704 name == "BLXr9" || 705 name == "t2BXJ" || 706 name == "BXJ") { 707 BRANCH("func"); 708 709 unsigned opIndex; 710 opIndex = inst.Operands.getOperandNamed("func"); 711 if (operandTypes[opIndex]->is("kOperandTypeImmediate")) 712 operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); 713 } 714} 715 716#undef BRANCH 717 718/// populateInstInfo - Fills an array of InstInfos with information about each 719/// instruction in a target 720/// 721/// @arg infoArray - The array of InstInfo objects to populate 722/// @arg target - The CodeGenTarget to use as a source of instructions 723static void populateInstInfo(CompoundConstantEmitter &infoArray, 724 CodeGenTarget &target) { 725 const std::vector<const CodeGenInstruction*> &numberedInstructions = 726 target.getInstructionsByEnumValue(); 727 728 unsigned int index; 729 unsigned int numInstructions = numberedInstructions.size(); 730 731 for (index = 0; index < numInstructions; ++index) { 732 const CodeGenInstruction& inst = *numberedInstructions[index]; 733 734 CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; 735 infoArray.addEntry(infoStruct); 736 737 LiteralConstantEmitter *instType = new LiteralConstantEmitter; 738 infoStruct->addEntry(instType); 739 740 LiteralConstantEmitter *numOperandsEmitter = 741 new LiteralConstantEmitter(inst.Operands.size()); 742 infoStruct->addEntry(numOperandsEmitter); 743 744 CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; 745 infoStruct->addEntry(operandTypeArray); 746 747 LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; 748 749 CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; 750 infoStruct->addEntry(operandFlagArray); 751 752 FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; 753 754 for (unsigned operandIndex = 0; 755 operandIndex < EDIS_MAX_OPERANDS; 756 ++operandIndex) { 757 operandTypes[operandIndex] = new LiteralConstantEmitter; 758 operandTypeArray->addEntry(operandTypes[operandIndex]); 759 760 operandFlags[operandIndex] = new FlagsConstantEmitter; 761 operandFlagArray->addEntry(operandFlags[operandIndex]); 762 } 763 764 unsigned numSyntaxes = 0; 765 766 if (target.getName() == "X86") { 767 X86PopulateOperands(operandTypes, inst); 768 X86ExtractSemantics(*instType, operandFlags, inst); 769 numSyntaxes = 2; 770 } 771 else if (target.getName() == "ARM") { 772 ARMPopulateOperands(operandTypes, inst); 773 ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); 774 numSyntaxes = 1; 775 } 776 777 CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; 778 779 infoStruct->addEntry(operandOrderArray); 780 781 for (unsigned syntaxIndex = 0; 782 syntaxIndex < EDIS_MAX_SYNTAXES; 783 ++syntaxIndex) { 784 CompoundConstantEmitter *operandOrder = 785 new CompoundConstantEmitter(EDIS_MAX_OPERANDS); 786 787 operandOrderArray->addEntry(operandOrder); 788 789 if (syntaxIndex < numSyntaxes) { 790 populateOperandOrder(operandOrder, inst, syntaxIndex); 791 } 792 } 793 794 infoStruct = NULL; 795 } 796} 797 798static void emitCommonEnums(raw_ostream &o, unsigned int &i) { 799 EnumEmitter operandTypes("OperandTypes"); 800 operandTypes.addEntry("kOperandTypeNone"); 801 operandTypes.addEntry("kOperandTypeImmediate"); 802 operandTypes.addEntry("kOperandTypeRegister"); 803 operandTypes.addEntry("kOperandTypeX86Memory"); 804 operandTypes.addEntry("kOperandTypeX86EffectiveAddress"); 805 operandTypes.addEntry("kOperandTypeX86PCRelative"); 806 operandTypes.addEntry("kOperandTypeARMBranchTarget"); 807 operandTypes.addEntry("kOperandTypeARMSoReg"); 808 operandTypes.addEntry("kOperandTypeARMSoImm"); 809 operandTypes.addEntry("kOperandTypeARMRotImm"); 810 operandTypes.addEntry("kOperandTypeARMSoImm2Part"); 811 operandTypes.addEntry("kOperandTypeARMPredicate"); 812 operandTypes.addEntry("kOperandTypeAddrModeImm12"); 813 operandTypes.addEntry("kOperandTypeLdStSOReg"); 814 operandTypes.addEntry("kOperandTypeARMAddrMode2"); 815 operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); 816 operandTypes.addEntry("kOperandTypeARMAddrMode3"); 817 operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); 818 operandTypes.addEntry("kOperandTypeARMLdStmMode"); 819 operandTypes.addEntry("kOperandTypeARMAddrMode5"); 820 operandTypes.addEntry("kOperandTypeARMAddrMode6"); 821 operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); 822 operandTypes.addEntry("kOperandTypeARMAddrModePC"); 823 operandTypes.addEntry("kOperandTypeARMRegisterList"); 824 operandTypes.addEntry("kOperandTypeARMTBAddrMode"); 825 operandTypes.addEntry("kOperandTypeThumbITMask"); 826 operandTypes.addEntry("kOperandTypeThumbAddrModeS1"); 827 operandTypes.addEntry("kOperandTypeThumbAddrModeS2"); 828 operandTypes.addEntry("kOperandTypeThumbAddrModeS4"); 829 operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); 830 operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); 831 operandTypes.addEntry("kOperandTypeThumb2SoReg"); 832 operandTypes.addEntry("kOperandTypeThumb2SoImm"); 833 operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); 834 operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset"); 835 operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12"); 836 operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg"); 837 operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); 838 operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); 839 operandTypes.emit(o, i); 840 841 o << "\n"; 842 843 EnumEmitter operandFlags("OperandFlags"); 844 operandFlags.addEntry("kOperandFlagSource"); 845 operandFlags.addEntry("kOperandFlagTarget"); 846 operandFlags.emitAsFlags(o, i); 847 848 o << "\n"; 849 850 EnumEmitter instructionTypes("InstructionTypes"); 851 instructionTypes.addEntry("kInstructionTypeNone"); 852 instructionTypes.addEntry("kInstructionTypeMove"); 853 instructionTypes.addEntry("kInstructionTypeBranch"); 854 instructionTypes.addEntry("kInstructionTypePush"); 855 instructionTypes.addEntry("kInstructionTypePop"); 856 instructionTypes.addEntry("kInstructionTypeCall"); 857 instructionTypes.addEntry("kInstructionTypeReturn"); 858 instructionTypes.emit(o, i); 859 860 o << "\n"; 861} 862 863void EDEmitter::run(raw_ostream &o) { 864 unsigned int i = 0; 865 866 CompoundConstantEmitter infoArray; 867 CodeGenTarget target; 868 869 populateInstInfo(infoArray, target); 870 871 emitCommonEnums(o, i); 872 873 o << "namespace {\n"; 874 875 o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = "; 876 infoArray.emit(o, i); 877 o << ";" << "\n"; 878 879 o << "}\n"; 880} 881