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