Jakub Staszak | 88ac78c | 2004-04-06 19:31:31 +0000 | [diff] [blame] | 1 | //===- SimpleInstrSelEmitter.cpp - Generate a Simple Instruction Selector ------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This tablegen backend is responsible for emitting an instruction selector |
| 11 | // |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | #include "InstrInfoEmitter.h" |
| 15 | #include "SimpleInstrSelEmitter.h" |
| 16 | #include "CodeGenWrappers.h" |
| 17 | #include "Record.h" |
| 18 | #include "Support/Debug.h" |
| 19 | #include "Support/StringExtras.h" |
| 20 | #include <set> |
| 21 | |
| 22 | |
| 23 | #include "Record.h" |
| 24 | #include "Support/CommandLine.h" |
| 25 | #include "Support/Signals.h" |
| 26 | #include "Support/FileUtilities.h" |
| 27 | #include "CodeEmitterGen.h" |
| 28 | #include "RegisterInfoEmitter.h" |
| 29 | #include "InstrInfoEmitter.h" |
| 30 | #include "InstrSelectorEmitter.h" |
| 31 | #include "SimpleInstrSelEmitter.h" |
| 32 | #include <algorithm> |
| 33 | #include <cstdio> |
| 34 | #include <fstream> |
| 35 | #include <vector> |
| 36 | |
| 37 | namespace llvm { |
| 38 | |
| 39 | std::string FnDecs; |
| 40 | |
| 41 | // run - Emit the main instruction description records for the target... |
| 42 | void SimpleInstrSelEmitter::run(std::ostream &OS) { |
| 43 | |
| 44 | |
| 45 | // EmitSourceFileHeader("Mark's Instruction Selector for the X86 target", OS); |
| 46 | |
| 47 | |
| 48 | // OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n"; |
| 49 | |
| 50 | // OS << "#include \"llvm/Constants.h\"\n"; |
| 51 | // OS << "#include \"llvm/DerivedTypes.h\"\n"; |
| 52 | // OS << "#include \"llvm/Function.h\"\n"; |
| 53 | // OS << "#include \"llvm/Instructions.h\"\n"; |
| 54 | // OS << "#include \"llvm/IntrinsicLowering.h\"\n"; |
| 55 | // OS << "#include \"llvm/Pass.h\"\n"; |
| 56 | // OS << "#include \"llvm/CodeGen/MachineConstantPool.h\"\n"; |
| 57 | // OS << "#include \"llvm/CodeGen/MachineFrameInfo.h\"\n"; |
| 58 | // OS << "#include \"llvm/CodeGen/MachineFunction.h\"\n"; |
| 59 | // OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n"; |
| 60 | // OS << "#include \"llvm/CodeGen/SSARegMap.h\"\n"; |
| 61 | // OS << "#include \"llvm/Target/MRegisterInfo.h\"\n"; |
| 62 | // OS << "#include \"llvm/Target/TargetMachine.h\"\n"; |
| 63 | // OS << "#include \"llvm/Support/InstVisitor.h\"\n"; |
| 64 | |
| 65 | // OS << "using namespace llvm;\n\n"; |
| 66 | |
| 67 | |
| 68 | FnDecs = ""; |
| 69 | |
| 70 | // for each InstrClass |
| 71 | |
| 72 | std::vector<Record*> Recs = Records.getAllDerivedDefinitions("InstrClass"); |
| 73 | for (unsigned i = 0, e = Recs.size(); i != e; ++i) { |
| 74 | std::string InstrClassName = Recs[i]->getName(); |
| 75 | OS << "// Generate BMI instructions for " << InstrClassName << "\n\n"; |
| 76 | OS << "void ISel::visit"; |
| 77 | OS << Recs[i]->getValueAsString("FunctionName"); |
| 78 | OS << "(" << Recs[i]->getValueAsString("InstructionName") << " &I)\n{" << "\n"; |
| 79 | // for each supported InstrSubclass |
| 80 | |
| 81 | OS << spacing() << "unsigned DestReg = getReg(I);\n"; |
| 82 | OS << spacing() << "unsigned Op0Reg = getReg(I.getOperand(0));\n"; |
| 83 | OS << spacing() << "unsigned Op1Reg = getReg(I.getOperand(1));\n"; |
| 84 | OS << spacing() << "Value *Op0Val = I.getOperand(0);\n"; |
| 85 | OS << spacing() << "Value *Op1Val = I.getOperand(1);\n"; |
| 86 | |
| 87 | OS << spacing() << "MachineBasicBlock::iterator IP = BB->end();\n"; |
| 88 | |
| 89 | OS << std::endl; |
| 90 | |
| 91 | ListInit *SupportedSubclasses = Recs[i]->getValueAsListInit("Supports"); |
| 92 | |
| 93 | //OS << spacing() << InstrClassName << "Prep();" << "\n"; |
| 94 | //FnDecs += "void ISel::" + InstrClassName + "Prep() {\n\n}\n\n"; |
| 95 | |
| 96 | std::vector<std::string> vi; |
| 97 | |
| 98 | // generate subclasses nested switch statements |
| 99 | InstrSubclasses(OS, InstrClassName, InstrClassName, SupportedSubclasses, vi, 0); |
| 100 | |
| 101 | //OS << spacing() << InstrClassName << "Post();\n"; |
| 102 | //FnDecs += "void ISel::" + InstrClassName + "Post() {\n\n}\n\n"; |
| 103 | |
| 104 | OS << "}\n"; |
| 105 | OS << "\n\n\n"; |
| 106 | |
| 107 | } // for each instrclass |
| 108 | |
| 109 | // OS << "} //namespace\n"; |
| 110 | |
| 111 | |
| 112 | #if 0 |
| 113 | // print out function stubs |
| 114 | OS << "\n\n\n//Functions\n\n" << FnDecs; |
| 115 | |
| 116 | // print out getsubclass() definitions |
| 117 | std::vector<Record*> SubclassColRec = Records.getAllDerivedDefinitions("InstrSubclassCollection"); |
| 118 | for (unsigned j=0, m=SubclassColRec.getSize(); j!=m; ++j) { |
| 119 | std::string SubclassName = SubclassColRec[j]->getName(); |
| 120 | FnDecs += "unsigned ISel::get" + SubclassName + "() {\n\n"; |
| 121 | |
| 122 | ListInit* list = dynamic_cast<ListInit*>(SubclassColRec[j].getValueAsListInit("List")); |
| 123 | |
| 124 | for (unsigned k=0; n=list.getSize(); k!=n; ++k) { |
| 125 | |
| 126 | FnDecs += "}\n\n"; |
| 127 | } |
| 128 | #endif |
| 129 | |
| 130 | } //run |
| 131 | |
| 132 | |
| 133 | |
| 134 | // find instructions that match all the subclasses (only support for 1 now) |
| 135 | Record* SimpleInstrSelEmitter::findInstruction(std::ostream &OS, std::string cl, std::vector<std::string>& vi) { |
| 136 | std::vector<Record*> Recs = Records.getAllDerivedDefinitions("TargInstrSet"); |
| 137 | |
| 138 | for (unsigned i = 0, e = Recs.size(); i != e; ++i) { |
| 139 | Record* thisClass = Recs[i]->getValueAsDef("Class"); |
| 140 | |
| 141 | if (thisClass->getName() == cl) { |
| 142 | |
| 143 | // get the Subclasses this supports |
| 144 | ListInit* SubclassList = Recs[i]->getValueAsListInit("List"); |
| 145 | |
| 146 | bool Match = true; |
| 147 | |
| 148 | if (SubclassList->getSize() != vi.size()) |
| 149 | Match = false; |
| 150 | |
| 151 | // match the instruction's supported subclasses with the subclasses we are looking for |
| 152 | |
| 153 | for (unsigned j=0, f=SubclassList->getSize(); j!=f; ++j) { |
| 154 | DefInit* SubclassDef = dynamic_cast<DefInit*>(SubclassList->getElement(j)); |
| 155 | Record* thisSubclass = SubclassDef->getDef(); |
| 156 | |
| 157 | std::string searchingFor = vi[j]; |
| 158 | |
| 159 | if (thisSubclass->getName() != searchingFor) { |
| 160 | Match = false; |
| 161 | } |
| 162 | |
| 163 | } // for each subclass list |
| 164 | |
| 165 | if (Match == true) { return Recs[i]; } |
| 166 | |
| 167 | } //if instrclass matches |
| 168 | |
| 169 | } // for all instructions |
| 170 | |
| 171 | // if no instructions found, return NULL |
| 172 | return NULL; |
| 173 | |
| 174 | } //findInstruction |
| 175 | |
| 176 | |
| 177 | |
| 178 | Record* SimpleInstrSelEmitter::findRegister(std::ostream &OS, std::string regname) { |
| 179 | std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Register"); |
| 180 | |
| 181 | for (unsigned i = 0, e = Recs.size(); i != e; ++i) { |
| 182 | Record* thisReg = Recs[i]; |
| 183 | |
| 184 | if (thisReg->getName() == regname) return Recs[i]; |
| 185 | } |
| 186 | |
| 187 | return NULL; |
| 188 | |
| 189 | } |
| 190 | |
| 191 | // handle "::" and "+" etc |
| 192 | std::string SimpleInstrSelEmitter::formatRegister(std::ostream &OS, std::string regname) { |
| 193 | std::string Reg; |
| 194 | std::string suffix; |
| 195 | |
| 196 | int x = std::strcspn(regname.c_str(),"+-"); |
| 197 | |
| 198 | // operate on text before "+" or "-", append it back at the end |
| 199 | Reg = regname.substr(0,x); |
| 200 | suffix = regname.substr(x,regname.length()); |
| 201 | |
| 202 | unsigned int y = std::strcspn(Reg.c_str(),":"); |
| 203 | |
| 204 | if (y == Reg.length()) { // does not contain "::" |
| 205 | |
| 206 | Record* RegRec = findRegister(OS,Reg); |
| 207 | |
| 208 | assert(RegRec && "Register not found!"); |
| 209 | |
| 210 | if (RegRec->getValueAsString("Namespace") != "Virtual") { |
| 211 | Reg = RegRec->getValueAsString("Namespace") + "::" + RegRec->getName(); |
| 212 | } else { |
| 213 | Reg = RegRec->getName(); |
| 214 | } |
| 215 | } // regular case |
| 216 | |
| 217 | // append + or - at the end again (i.e. X86::EAX+1) |
| 218 | Reg = Reg + suffix; |
| 219 | |
| 220 | return Reg; |
| 221 | } |
| 222 | |
| 223 | |
| 224 | // take information in the instruction class and generate the correct BMI call |
| 225 | void SimpleInstrSelEmitter::generateBMIcall(std::ostream &OS, std::string MBB, std::string IP, std::string Opcode, int NumOperands, ListInit &instroperands, ListInit &operands) { |
| 226 | |
| 227 | // find Destination Register |
| 228 | StringInit* DestRegStr = dynamic_cast<StringInit*>(operands.getElement(0)); |
| 229 | std::string DestReg = formatRegister(OS,DestRegStr->getValue()); |
| 230 | |
| 231 | OS << "BuildMI("; |
| 232 | OS << MBB << ", "; |
| 233 | OS << IP << ", "; |
| 234 | OS << Opcode << ", "; |
| 235 | OS << NumOperands; |
| 236 | |
| 237 | if (DestReg != "Pseudo") { |
| 238 | OS << ", " << DestReg << ")"; |
| 239 | } else { |
| 240 | OS << ")"; |
| 241 | } |
| 242 | |
| 243 | // handle the .add stuff |
| 244 | for (unsigned i=0, e=instroperands.getSize(); i!=e; ++i) { |
| 245 | DefInit* OpDef = dynamic_cast<DefInit*>(instroperands.getElement(i)); |
| 246 | StringInit* RegStr = dynamic_cast<StringInit*>(operands.getElement(i+1)); |
| 247 | |
| 248 | Record* Op = OpDef->getDef(); |
| 249 | |
| 250 | std::string opstr = Op->getValueAsString("Name"); |
| 251 | |
| 252 | std::string regname; |
| 253 | |
| 254 | if (opstr == "Register") { |
| 255 | regname = formatRegister(OS,RegStr->getValue()); |
| 256 | } else { |
| 257 | regname = RegStr->getValue(); |
| 258 | } |
| 259 | |
| 260 | OS << ".add" << opstr << "(" << regname << ")"; |
| 261 | } |
| 262 | |
| 263 | OS << ";\n"; |
| 264 | |
| 265 | } //generateBMIcall |
| 266 | |
| 267 | |
| 268 | std::string SimpleInstrSelEmitter::spacing() { |
| 269 | return globalSpacing; |
| 270 | } |
| 271 | |
| 272 | std::string SimpleInstrSelEmitter::addspacing() { |
| 273 | globalSpacing += " "; |
| 274 | return globalSpacing; |
| 275 | } |
| 276 | |
| 277 | std::string SimpleInstrSelEmitter::remspacing() { |
| 278 | globalSpacing = globalSpacing.substr(0,globalSpacing.length()-2); |
| 279 | return globalSpacing; |
| 280 | } |
| 281 | |
| 282 | |
| 283 | // recursively print out the subclasses of an instruction |
| 284 | // |
| 285 | void SimpleInstrSelEmitter::InstrSubclasses(std::ostream &OS, std::string prefix, std::string InstrClassName, ListInit* SupportedSubclasses, std::vector<std::string>& vi, unsigned depth) { |
| 286 | |
| 287 | |
| 288 | if (depth >= SupportedSubclasses->getSize()) { |
| 289 | return; |
| 290 | } |
| 291 | |
| 292 | // get the subclass collection |
| 293 | |
| 294 | DefInit* InstrSubclassColl = dynamic_cast<DefInit*>(SupportedSubclasses->getElement(depth)); |
| 295 | |
| 296 | Record* InstrSubclassRec = InstrSubclassColl->getDef(); |
| 297 | |
| 298 | std::string SubclassName = InstrSubclassRec->getName(); |
| 299 | |
| 300 | |
| 301 | if (InstrSubclassRec->getValueAsString("PreCode") != "") { |
| 302 | // OS << spacing() << prefix << "_" << Subclass->getName() << "_Prep();\n"; |
| 303 | OS << spacing() << InstrSubclassRec->getValueAsString("PreCode") << "\n\n"; |
| 304 | } |
| 305 | |
| 306 | |
| 307 | OS << spacing() << "// Looping through " << SubclassName << "\n"; |
| 308 | |
| 309 | OS << spacing() << "switch (" << SubclassName <<") {\n"; |
| 310 | addspacing(); |
| 311 | |
| 312 | ListInit* SubclassList = InstrSubclassRec->getValueAsListInit("List"); |
| 313 | |
| 314 | for (unsigned k=0, g = SubclassList->getSize(); k!=g; ++k) { |
| 315 | |
| 316 | DefInit* SubclassDef = dynamic_cast<DefInit*>(SubclassList->getElement(k)); |
| 317 | |
| 318 | Record* Subclass = SubclassDef->getDef(); |
| 319 | |
| 320 | OS << spacing() << "// " << prefix << "_" << Subclass->getName() << "\n"; |
| 321 | OS << spacing() << "case " << Subclass->getName() << ":\n"; |
| 322 | addspacing(); |
| 323 | OS << spacing() << "{\n"; |
| 324 | |
| 325 | |
| 326 | vi.push_back(Subclass->getName()); |
| 327 | |
| 328 | // go down hierarchy |
| 329 | InstrSubclasses(OS, prefix + "_" + Subclass->getName(), InstrClassName, SupportedSubclasses, vi, depth+1); |
| 330 | |
| 331 | // find the record that matches this |
| 332 | Record *theInstructionSet = findInstruction(OS, InstrClassName, vi); |
| 333 | |
| 334 | // only print out the assertion if this is a leaf |
| 335 | if ( (theInstructionSet == NULL) && (depth == (SupportedSubclasses->getSize() - 1)) ) { |
| 336 | |
| 337 | OS << spacing() << "assert(0 && \"No instructions defined for " << InstrClassName << " instructions of subclasses " << prefix << "_" << Subclass->getName() << "!\");" << "\n"; |
| 338 | |
| 339 | } else if (theInstructionSet != NULL) { |
| 340 | |
| 341 | if (theInstructionSet->getValueAsString("PreCode") != "") { |
| 342 | OS << spacing() << theInstructionSet->getValueAsString("PreCode") << "\n\n"; |
| 343 | } |
| 344 | |
| 345 | ListInit *theInstructions = theInstructionSet->getValueAsListInit("Instructions"); |
| 346 | |
| 347 | ListInit *registerlists = theInstructionSet->getValueAsListInit("Operands"); // not necessarily registers anymore, but the name will stay for now |
| 348 | |
| 349 | for (unsigned l=0, h=theInstructions->getSize(); l!=h; ++l) { |
| 350 | |
| 351 | DefInit *theInstructionDef = dynamic_cast<DefInit*>(theInstructions->getElement(l)); |
| 352 | Record *theInstruction = theInstructionDef->getDef(); |
| 353 | |
| 354 | ListInit *operands = theInstruction->getValueAsListInit("Params"); |
| 355 | |
| 356 | OS << spacing(); |
| 357 | |
| 358 | ListInit* registers = dynamic_cast<ListInit*>(registerlists->getElement(l)); |
| 359 | |
| 360 | // handle virtual instructions here before going to generateBMIcall |
| 361 | |
| 362 | if (theInstruction->getValueAsString("Namespace") == "Virtual") { |
| 363 | |
| 364 | // create reg for different sizes |
| 365 | std::string Instr = theInstruction->getName(); |
| 366 | StringInit* DestRegInit = dynamic_cast<StringInit*>(registers->getElement(0)); |
| 367 | std::string DestReg = DestRegInit->getValue(); |
| 368 | std::string theType; |
| 369 | |
| 370 | if (Instr == "NullInstruction") { } // do nothing |
| 371 | else if (Instr == "CreateRegByte") |
| 372 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SByteTy);\n"; |
| 373 | else if (Instr == "CreateRegShort") |
| 374 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SShortTy);\n"; |
| 375 | else if (Instr == "CreateRegInt") |
| 376 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SIntTy);\n"; |
| 377 | else if (Instr == "CreateRegLong") |
| 378 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SLongTy);\n"; |
| 379 | else if (Instr == "CreateRegUByte") |
| 380 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UByteTy);\n"; |
| 381 | else if (Instr == "CreateRegUShort") |
| 382 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UShortTy);\n"; |
| 383 | else if (Instr == "CreateRegUInt") |
| 384 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UIntTy);\n"; |
| 385 | else if (Instr == "CreateRegULong") |
| 386 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::ULongTy);\n"; |
| 387 | else if (Instr == "CreateRegFloat") |
| 388 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::FloatTy);\n"; |
| 389 | else if (Instr == "CreateRegDouble") |
| 390 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::DoubleTy);\n"; |
| 391 | else if (Instr == "CreateRegPointer") |
| 392 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::PointerTy_;\n"; |
| 393 | else |
| 394 | OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SByteTy);\n"; // create a byte by default |
| 395 | |
| 396 | |
| 397 | } else { |
| 398 | std::string InstrName; |
| 399 | |
| 400 | if (theInstruction->getValueAsString("Namespace") != "Virtual") { |
| 401 | InstrName = theInstruction->getValueAsString("Namespace") + "::" + theInstruction->getValueAsString("Name"); |
| 402 | } else { |
| 403 | // shouldn't ever happen, virtual instrs should be caught before this |
| 404 | InstrName = theInstruction->getValueAsString("Name"); |
| 405 | } |
| 406 | |
| 407 | generateBMIcall(OS, "*BB","IP",InstrName,theInstruction->getValueAsInt("NumOperands"),*operands,*registers); |
| 408 | } |
| 409 | |
| 410 | } |
| 411 | |
| 412 | if (theInstructionSet->getValueAsString("PostCode") != "") { |
| 413 | OS << spacing() << theInstructionSet->getValueAsString("PostCode") << "\n\n"; |
| 414 | } |
| 415 | |
| 416 | } |
| 417 | |
| 418 | |
| 419 | |
| 420 | if (InstrSubclassRec->getValueAsString("PostCode") != "") { |
| 421 | //OS << spacing() << "// " << prefix << "_" << Subclass->getName() << "_Prep();\n"; |
| 422 | OS << spacing() << InstrSubclassRec->getValueAsString("PostCode") << "\n\n"; |
| 423 | } |
| 424 | |
| 425 | |
| 426 | OS << spacing() << "break;\n"; |
| 427 | |
| 428 | OS << spacing() << "}\n\n"; |
| 429 | |
| 430 | remspacing(); |
| 431 | |
| 432 | vi.pop_back(); |
| 433 | } |
| 434 | |
| 435 | // provide a default case for the switch |
| 436 | |
| 437 | OS << spacing() << "default:\n"; |
| 438 | OS << spacing() << " assert(0 && \"No instructions defined for " << InstrClassName << " instructions of subclasses " << prefix << "_" << SubclassName << "!\");" << "\n"; |
| 439 | OS << spacing() << " break;\n\n"; |
| 440 | |
| 441 | remspacing(); |
| 442 | OS << spacing() << "}\n"; |
| 443 | |
| 444 | } |
| 445 | |
| 446 | |
| 447 | // ret br switch invoke unwind |
| 448 | // add sub mul div rem setcc (eq ne lt gt le ge) |
| 449 | // and or xor sbl sbr |
| 450 | // malloc free alloca load store |
| 451 | // getelementptr phi cast call vanext vaarg |
| 452 | |
| 453 | } // End llvm namespace |