1 //===- MachineOperandTest.cpp ---------------------------------===// 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 #include "llvm/CodeGen/MachineOperand.h" 11 #include "llvm/ADT/ilist_node.h" 12 #include "llvm/IR/Constants.h" 13 #include "llvm/IR/InstrTypes.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/IR/ModuleSlotTracker.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCAsmInfo.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include "gtest/gtest.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 TEST(MachineOperandTest, ChangeToTargetIndexTest) { 27 // Creating a MachineOperand to change it to TargetIndex 28 MachineOperand MO = MachineOperand::CreateImm(50); 29 30 // Checking some precondition on the newly created 31 // MachineOperand. 32 ASSERT_TRUE(MO.isImm()); 33 ASSERT_TRUE(MO.getImm() == 50); 34 ASSERT_FALSE(MO.isTargetIndex()); 35 36 // Changing to TargetIndex with some arbitrary values 37 // for index, offset and flags. 38 MO.ChangeToTargetIndex(74, 57, 12); 39 40 // Checking that the mutation to TargetIndex happened 41 // correctly. 42 ASSERT_TRUE(MO.isTargetIndex()); 43 ASSERT_TRUE(MO.getIndex() == 74); 44 ASSERT_TRUE(MO.getOffset() == 57); 45 ASSERT_TRUE(MO.getTargetFlags() == 12); 46 } 47 48 TEST(MachineOperandTest, PrintRegisterMask) { 49 uint32_t Dummy; 50 MachineOperand MO = MachineOperand::CreateRegMask(&Dummy); 51 52 // Checking some preconditions on the newly created 53 // MachineOperand. 54 ASSERT_TRUE(MO.isRegMask()); 55 ASSERT_TRUE(MO.getRegMask() == &Dummy); 56 57 // Print a MachineOperand containing a RegMask. Here we check that without a 58 // TRI and IntrinsicInfo we still print a less detailed regmask. 59 std::string str; 60 raw_string_ostream OS(str); 61 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 62 ASSERT_TRUE(OS.str() == "<regmask ...>"); 63 } 64 65 TEST(MachineOperandTest, PrintSubReg) { 66 // Create a MachineOperand with RegNum=1 and SubReg=5. 67 MachineOperand MO = MachineOperand::CreateReg( 68 /*Reg=*/1, /*isDef=*/false, /*isImp=*/false, /*isKill=*/false, 69 /*isDead=*/false, /*isUndef=*/false, /*isEarlyClobber=*/false, 70 /*SubReg=*/5, /*isDebug=*/false, /*isInternalRead=*/false); 71 72 // Checking some preconditions on the newly created 73 // MachineOperand. 74 ASSERT_TRUE(MO.isReg()); 75 ASSERT_TRUE(MO.getReg() == 1); 76 ASSERT_TRUE(MO.getSubReg() == 5); 77 78 // Print a MachineOperand containing a SubReg. Here we check that without a 79 // TRI and IntrinsicInfo we can still print the subreg index. 80 std::string str; 81 raw_string_ostream OS(str); 82 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 83 ASSERT_TRUE(OS.str() == "%physreg1.subreg5"); 84 } 85 86 TEST(MachineOperandTest, PrintCImm) { 87 LLVMContext Context; 88 APInt Int(128, UINT64_MAX); 89 ++Int; 90 ConstantInt *CImm = ConstantInt::get(Context, Int); 91 // Create a MachineOperand with an Imm=(UINT64_MAX + 1) 92 MachineOperand MO = MachineOperand::CreateCImm(CImm); 93 94 // Checking some preconditions on the newly created 95 // MachineOperand. 96 ASSERT_TRUE(MO.isCImm()); 97 ASSERT_TRUE(MO.getCImm() == CImm); 98 ASSERT_TRUE(MO.getCImm()->getValue() == Int); 99 100 // Print a MachineOperand containing a SubReg. Here we check that without a 101 // TRI and IntrinsicInfo we can still print the subreg index. 102 std::string str; 103 raw_string_ostream OS(str); 104 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 105 ASSERT_TRUE(OS.str() == "i128 18446744073709551616"); 106 } 107 108 TEST(MachineOperandTest, PrintSubRegIndex) { 109 // Create a MachineOperand with an immediate and print it as a subreg index. 110 MachineOperand MO = MachineOperand::CreateImm(3); 111 112 // Checking some preconditions on the newly created 113 // MachineOperand. 114 ASSERT_TRUE(MO.isImm()); 115 ASSERT_TRUE(MO.getImm() == 3); 116 117 // Print a MachineOperand containing a SubRegIdx. Here we check that without a 118 // TRI and IntrinsicInfo we can print the operand as a subreg index. 119 std::string str; 120 raw_string_ostream OS(str); 121 ModuleSlotTracker DummyMST(nullptr); 122 MachineOperand::printSubregIdx(OS, MO.getImm(), nullptr); 123 ASSERT_TRUE(OS.str() == "%subreg.3"); 124 } 125 126 TEST(MachineOperandTest, PrintCPI) { 127 // Create a MachineOperand with a constant pool index and print it. 128 MachineOperand MO = MachineOperand::CreateCPI(0, 8); 129 130 // Checking some preconditions on the newly created 131 // MachineOperand. 132 ASSERT_TRUE(MO.isCPI()); 133 ASSERT_TRUE(MO.getIndex() == 0); 134 ASSERT_TRUE(MO.getOffset() == 8); 135 136 // Print a MachineOperand containing a constant pool index and a positive 137 // offset. 138 std::string str; 139 { 140 raw_string_ostream OS(str); 141 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 142 ASSERT_TRUE(OS.str() == "%const.0 + 8"); 143 } 144 145 str.clear(); 146 147 MO.setOffset(-12); 148 149 // Print a MachineOperand containing a constant pool index and a negative 150 // offset. 151 { 152 raw_string_ostream OS(str); 153 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 154 ASSERT_TRUE(OS.str() == "%const.0 - 12"); 155 } 156 } 157 158 TEST(MachineOperandTest, PrintTargetIndexName) { 159 // Create a MachineOperand with a target index and print it. 160 MachineOperand MO = MachineOperand::CreateTargetIndex(0, 8); 161 162 // Checking some preconditions on the newly created 163 // MachineOperand. 164 ASSERT_TRUE(MO.isTargetIndex()); 165 ASSERT_TRUE(MO.getIndex() == 0); 166 ASSERT_TRUE(MO.getOffset() == 8); 167 168 // Print a MachineOperand containing a target index and a positive offset. 169 std::string str; 170 { 171 raw_string_ostream OS(str); 172 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 173 ASSERT_TRUE(OS.str() == "target-index(<unknown>) + 8"); 174 } 175 176 str.clear(); 177 178 MO.setOffset(-12); 179 180 // Print a MachineOperand containing a target index and a negative offset. 181 { 182 raw_string_ostream OS(str); 183 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 184 ASSERT_TRUE(OS.str() == "target-index(<unknown>) - 12"); 185 } 186 } 187 188 TEST(MachineOperandTest, PrintJumpTableIndex) { 189 // Create a MachineOperand with a jump-table index and print it. 190 MachineOperand MO = MachineOperand::CreateJTI(3); 191 192 // Checking some preconditions on the newly created 193 // MachineOperand. 194 ASSERT_TRUE(MO.isJTI()); 195 ASSERT_TRUE(MO.getIndex() == 3); 196 197 // Print a MachineOperand containing a jump-table index. 198 std::string str; 199 raw_string_ostream OS(str); 200 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 201 ASSERT_TRUE(OS.str() == "%jump-table.3"); 202 } 203 204 TEST(MachineOperandTest, PrintExternalSymbol) { 205 // Create a MachineOperand with an external symbol and print it. 206 MachineOperand MO = MachineOperand::CreateES("foo"); 207 208 // Checking some preconditions on the newly created 209 // MachineOperand. 210 ASSERT_TRUE(MO.isSymbol()); 211 ASSERT_TRUE(MO.getSymbolName() == StringRef("foo")); 212 213 // Print a MachineOperand containing an external symbol and no offset. 214 std::string str; 215 { 216 raw_string_ostream OS(str); 217 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 218 ASSERT_TRUE(OS.str() == "$foo"); 219 } 220 221 str.clear(); 222 MO.setOffset(12); 223 224 // Print a MachineOperand containing an external symbol and a positive offset. 225 { 226 raw_string_ostream OS(str); 227 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 228 ASSERT_TRUE(OS.str() == "$foo + 12"); 229 } 230 231 str.clear(); 232 MO.setOffset(-12); 233 234 // Print a MachineOperand containing an external symbol and a negative offset. 235 { 236 raw_string_ostream OS(str); 237 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 238 ASSERT_TRUE(OS.str() == "$foo - 12"); 239 } 240 } 241 242 TEST(MachineOperandTest, PrintGlobalAddress) { 243 LLVMContext Ctx; 244 Module M("MachineOperandGVTest", Ctx); 245 M.getOrInsertGlobal("foo", Type::getInt32Ty(Ctx)); 246 247 GlobalValue *GV = M.getNamedValue("foo"); 248 249 // Create a MachineOperand with a global address and a positive offset and 250 // print it. 251 MachineOperand MO = MachineOperand::CreateGA(GV, 12); 252 253 // Checking some preconditions on the newly created 254 // MachineOperand. 255 ASSERT_TRUE(MO.isGlobal()); 256 ASSERT_TRUE(MO.getGlobal() == GV); 257 ASSERT_TRUE(MO.getOffset() == 12); 258 259 std::string str; 260 // Print a MachineOperand containing a global address and a positive offset. 261 { 262 raw_string_ostream OS(str); 263 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 264 ASSERT_TRUE(OS.str() == "@foo + 12"); 265 } 266 267 str.clear(); 268 MO.setOffset(-12); 269 270 // Print a MachineOperand containing a global address and a negative offset. 271 { 272 raw_string_ostream OS(str); 273 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 274 ASSERT_TRUE(OS.str() == "@foo - 12"); 275 } 276 } 277 278 TEST(MachineOperandTest, PrintRegisterLiveOut) { 279 // Create a MachineOperand with a register live out list and print it. 280 uint32_t Mask = 0; 281 MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask); 282 283 // Checking some preconditions on the newly created 284 // MachineOperand. 285 ASSERT_TRUE(MO.isRegLiveOut()); 286 ASSERT_TRUE(MO.getRegLiveOut() == &Mask); 287 288 std::string str; 289 // Print a MachineOperand containing a register live out list without a TRI. 290 raw_string_ostream OS(str); 291 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 292 ASSERT_TRUE(OS.str() == "liveout(<unknown>)"); 293 } 294 295 TEST(MachineOperandTest, PrintMetadata) { 296 LLVMContext Ctx; 297 Module M("MachineOperandMDNodeTest", Ctx); 298 NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd"); 299 ModuleSlotTracker DummyMST(&M); 300 Metadata *MDS = MDString::get(Ctx, "foo"); 301 MDNode *Node = MDNode::get(Ctx, MDS); 302 MD->addOperand(Node); 303 304 // Create a MachineOperand with a metadata and print it. 305 MachineOperand MO = MachineOperand::CreateMetadata(Node); 306 307 // Checking some preconditions on the newly created 308 // MachineOperand. 309 ASSERT_TRUE(MO.isMetadata()); 310 ASSERT_TRUE(MO.getMetadata() == Node); 311 312 std::string str; 313 // Print a MachineOperand containing a metadata node. 314 raw_string_ostream OS(str); 315 MO.print(OS, DummyMST, LLT{}, false, false, 0, /*TRI=*/nullptr, 316 /*IntrinsicInfo=*/nullptr); 317 ASSERT_TRUE(OS.str() == "!0"); 318 } 319 320 TEST(MachineOperandTest, PrintMCSymbol) { 321 MCAsmInfo MAI; 322 MCContext Ctx(&MAI, /*MRI=*/nullptr, /*MOFI=*/nullptr); 323 MCSymbol *Sym = Ctx.getOrCreateSymbol("foo"); 324 325 // Create a MachineOperand with a metadata and print it. 326 MachineOperand MO = MachineOperand::CreateMCSymbol(Sym); 327 328 // Checking some preconditions on the newly created 329 // MachineOperand. 330 ASSERT_TRUE(MO.isMCSymbol()); 331 ASSERT_TRUE(MO.getMCSymbol() == Sym); 332 333 std::string str; 334 // Print a MachineOperand containing a metadata node. 335 raw_string_ostream OS(str); 336 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 337 ASSERT_TRUE(OS.str() == "<mcsymbol foo>"); 338 } 339 340 TEST(MachineOperandTest, PrintCFI) { 341 // Create a MachineOperand with a CFI index but no function and print it. 342 MachineOperand MO = MachineOperand::CreateCFIIndex(8); 343 344 // Checking some preconditions on the newly created 345 // MachineOperand. 346 ASSERT_TRUE(MO.isCFIIndex()); 347 ASSERT_TRUE(MO.getCFIIndex() == 8); 348 349 std::string str; 350 // Print a MachineOperand containing a CFI Index node but no machine function 351 // attached to it. 352 raw_string_ostream OS(str); 353 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 354 ASSERT_TRUE(OS.str() == "<cfi directive>"); 355 } 356 357 TEST(MachineOperandTest, PrintIntrinsicID) { 358 // Create a MachineOperand with a generic intrinsic ID. 359 MachineOperand MO = MachineOperand::CreateIntrinsicID(Intrinsic::bswap); 360 361 // Checking some preconditions on the newly created 362 // MachineOperand. 363 ASSERT_TRUE(MO.isIntrinsicID()); 364 ASSERT_TRUE(MO.getIntrinsicID() == Intrinsic::bswap); 365 366 std::string str; 367 { 368 // Print a MachineOperand containing a generic intrinsic ID. 369 raw_string_ostream OS(str); 370 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 371 ASSERT_TRUE(OS.str() == "intrinsic(@llvm.bswap)"); 372 } 373 374 str.clear(); 375 // Set a target-specific intrinsic. 376 MO = MachineOperand::CreateIntrinsicID((Intrinsic::ID)-1); 377 { 378 // Print a MachineOperand containing a target-specific intrinsic ID but not 379 // IntrinsicInfo. 380 raw_string_ostream OS(str); 381 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 382 ASSERT_TRUE(OS.str() == "intrinsic(4294967295)"); 383 } 384 } 385 386 TEST(MachineOperandTest, PrintPredicate) { 387 // Create a MachineOperand with a generic intrinsic ID. 388 MachineOperand MO = MachineOperand::CreatePredicate(CmpInst::ICMP_EQ); 389 390 // Checking some preconditions on the newly created 391 // MachineOperand. 392 ASSERT_TRUE(MO.isPredicate()); 393 ASSERT_TRUE(MO.getPredicate() == CmpInst::ICMP_EQ); 394 395 std::string str; 396 // Print a MachineOperand containing a int predicate ICMP_EQ. 397 raw_string_ostream OS(str); 398 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 399 ASSERT_TRUE(OS.str() == "intpred(eq)"); 400 } 401 402 } // end namespace 403