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/MCAsmInfo.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/Support/LowLevelTypeImpl.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 MachineOperand::printSubRegIdx(OS, MO.getImm(), nullptr); 122 ASSERT_TRUE(OS.str() == "%subreg.3"); 123 } 124 125 TEST(MachineOperandTest, PrintCPI) { 126 // Create a MachineOperand with a constant pool index and print it. 127 MachineOperand MO = MachineOperand::CreateCPI(0, 8); 128 129 // Checking some preconditions on the newly created 130 // MachineOperand. 131 ASSERT_TRUE(MO.isCPI()); 132 ASSERT_TRUE(MO.getIndex() == 0); 133 ASSERT_TRUE(MO.getOffset() == 8); 134 135 // Print a MachineOperand containing a constant pool index and a positive 136 // offset. 137 std::string str; 138 { 139 raw_string_ostream OS(str); 140 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 141 ASSERT_TRUE(OS.str() == "%const.0 + 8"); 142 } 143 144 str.clear(); 145 146 MO.setOffset(-12); 147 148 // Print a MachineOperand containing a constant pool index and a negative 149 // offset. 150 { 151 raw_string_ostream OS(str); 152 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 153 ASSERT_TRUE(OS.str() == "%const.0 - 12"); 154 } 155 } 156 157 TEST(MachineOperandTest, PrintTargetIndexName) { 158 // Create a MachineOperand with a target index and print it. 159 MachineOperand MO = MachineOperand::CreateTargetIndex(0, 8); 160 161 // Checking some preconditions on the newly created 162 // MachineOperand. 163 ASSERT_TRUE(MO.isTargetIndex()); 164 ASSERT_TRUE(MO.getIndex() == 0); 165 ASSERT_TRUE(MO.getOffset() == 8); 166 167 // Print a MachineOperand containing a target index and a positive offset. 168 std::string str; 169 { 170 raw_string_ostream OS(str); 171 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 172 ASSERT_TRUE(OS.str() == "target-index(<unknown>) + 8"); 173 } 174 175 str.clear(); 176 177 MO.setOffset(-12); 178 179 // Print a MachineOperand containing a target index and a negative offset. 180 { 181 raw_string_ostream OS(str); 182 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 183 ASSERT_TRUE(OS.str() == "target-index(<unknown>) - 12"); 184 } 185 } 186 187 TEST(MachineOperandTest, PrintJumpTableIndex) { 188 // Create a MachineOperand with a jump-table index and print it. 189 MachineOperand MO = MachineOperand::CreateJTI(3); 190 191 // Checking some preconditions on the newly created 192 // MachineOperand. 193 ASSERT_TRUE(MO.isJTI()); 194 ASSERT_TRUE(MO.getIndex() == 3); 195 196 // Print a MachineOperand containing a jump-table index. 197 std::string str; 198 raw_string_ostream OS(str); 199 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 200 ASSERT_TRUE(OS.str() == "%jump-table.3"); 201 } 202 203 TEST(MachineOperandTest, PrintExternalSymbol) { 204 // Create a MachineOperand with an external symbol and print it. 205 MachineOperand MO = MachineOperand::CreateES("foo"); 206 207 // Checking some preconditions on the newly created 208 // MachineOperand. 209 ASSERT_TRUE(MO.isSymbol()); 210 ASSERT_TRUE(MO.getSymbolName() == StringRef("foo")); 211 212 // Print a MachineOperand containing an external symbol and no offset. 213 std::string str; 214 { 215 raw_string_ostream OS(str); 216 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 217 ASSERT_TRUE(OS.str() == "&foo"); 218 } 219 220 str.clear(); 221 MO.setOffset(12); 222 223 // Print a MachineOperand containing an external symbol and a positive offset. 224 { 225 raw_string_ostream OS(str); 226 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 227 ASSERT_TRUE(OS.str() == "&foo + 12"); 228 } 229 230 str.clear(); 231 MO.setOffset(-12); 232 233 // Print a MachineOperand containing an external symbol and a negative offset. 234 { 235 raw_string_ostream OS(str); 236 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 237 ASSERT_TRUE(OS.str() == "&foo - 12"); 238 } 239 } 240 241 TEST(MachineOperandTest, PrintGlobalAddress) { 242 LLVMContext Ctx; 243 Module M("MachineOperandGVTest", Ctx); 244 M.getOrInsertGlobal("foo", Type::getInt32Ty(Ctx)); 245 246 GlobalValue *GV = M.getNamedValue("foo"); 247 248 // Create a MachineOperand with a global address and a positive offset and 249 // print it. 250 MachineOperand MO = MachineOperand::CreateGA(GV, 12); 251 252 // Checking some preconditions on the newly created 253 // MachineOperand. 254 ASSERT_TRUE(MO.isGlobal()); 255 ASSERT_TRUE(MO.getGlobal() == GV); 256 ASSERT_TRUE(MO.getOffset() == 12); 257 258 std::string str; 259 // Print a MachineOperand containing a global address and a positive offset. 260 { 261 raw_string_ostream OS(str); 262 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 263 ASSERT_TRUE(OS.str() == "@foo + 12"); 264 } 265 266 str.clear(); 267 MO.setOffset(-12); 268 269 // Print a MachineOperand containing a global address and a negative offset. 270 { 271 raw_string_ostream OS(str); 272 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 273 ASSERT_TRUE(OS.str() == "@foo - 12"); 274 } 275 } 276 277 TEST(MachineOperandTest, PrintRegisterLiveOut) { 278 // Create a MachineOperand with a register live out list and print it. 279 uint32_t Mask = 0; 280 MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask); 281 282 // Checking some preconditions on the newly created 283 // MachineOperand. 284 ASSERT_TRUE(MO.isRegLiveOut()); 285 ASSERT_TRUE(MO.getRegLiveOut() == &Mask); 286 287 std::string str; 288 // Print a MachineOperand containing a register live out list without a TRI. 289 raw_string_ostream OS(str); 290 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 291 ASSERT_TRUE(OS.str() == "liveout(<unknown>)"); 292 } 293 294 TEST(MachineOperandTest, PrintMetadata) { 295 LLVMContext Ctx; 296 Module M("MachineOperandMDNodeTest", Ctx); 297 NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd"); 298 ModuleSlotTracker MST(&M); 299 Metadata *MDS = MDString::get(Ctx, "foo"); 300 MDNode *Node = MDNode::get(Ctx, MDS); 301 MD->addOperand(Node); 302 303 // Create a MachineOperand with a metadata and print it. 304 MachineOperand MO = MachineOperand::CreateMetadata(Node); 305 306 // Checking some preconditions on the newly created 307 // MachineOperand. 308 ASSERT_TRUE(MO.isMetadata()); 309 ASSERT_TRUE(MO.getMetadata() == Node); 310 311 std::string str; 312 // Print a MachineOperand containing a metadata node. 313 raw_string_ostream OS(str); 314 MO.print(OS, MST, LLT{}, /*OpIdx*/~0U, /*PrintDef=*/false, /*IsStandalone=*/false, 315 /*ShouldPrintRegisterTies=*/false, 0, /*TRI=*/nullptr, 316 /*IntrinsicInfo=*/nullptr); 317 ASSERT_TRUE(OS.str() == "!0"); 318 } 319 320 TEST(MachineOperandTest, PrintMCSymbol) { 321 MCAsmInfo MAI; 322 Triple T = Triple("unknown-unknown-unknown"); 323 MCContext Ctx(T, &MAI, /*MRI=*/nullptr, /*MSTI=*/nullptr); 324 MCSymbol *Sym = Ctx.getOrCreateSymbol("foo"); 325 326 // Create a MachineOperand with a metadata and print it. 327 MachineOperand MO = MachineOperand::CreateMCSymbol(Sym); 328 329 // Checking some preconditions on the newly created 330 // MachineOperand. 331 ASSERT_TRUE(MO.isMCSymbol()); 332 ASSERT_TRUE(MO.getMCSymbol() == Sym); 333 334 std::string str; 335 // Print a MachineOperand containing a metadata node. 336 raw_string_ostream OS(str); 337 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 338 ASSERT_TRUE(OS.str() == "<mcsymbol foo>"); 339 } 340 341 TEST(MachineOperandTest, PrintCFI) { 342 // Create a MachineOperand with a CFI index but no function and print it. 343 MachineOperand MO = MachineOperand::CreateCFIIndex(8); 344 345 // Checking some preconditions on the newly created 346 // MachineOperand. 347 ASSERT_TRUE(MO.isCFIIndex()); 348 ASSERT_TRUE(MO.getCFIIndex() == 8); 349 350 std::string str; 351 // Print a MachineOperand containing a CFI Index node but no machine function 352 // attached to it. 353 raw_string_ostream OS(str); 354 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 355 ASSERT_TRUE(OS.str() == "<cfi directive>"); 356 } 357 358 TEST(MachineOperandTest, PrintIntrinsicID) { 359 // Create a MachineOperand with a generic intrinsic ID. 360 MachineOperand MO = MachineOperand::CreateIntrinsicID(Intrinsic::bswap); 361 362 // Checking some preconditions on the newly created 363 // MachineOperand. 364 ASSERT_TRUE(MO.isIntrinsicID()); 365 ASSERT_TRUE(MO.getIntrinsicID() == Intrinsic::bswap); 366 367 std::string str; 368 { 369 // Print a MachineOperand containing a generic intrinsic ID. 370 raw_string_ostream OS(str); 371 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 372 ASSERT_TRUE(OS.str() == "intrinsic(@llvm.bswap)"); 373 } 374 375 str.clear(); 376 // Set a target-specific intrinsic. 377 MO = MachineOperand::CreateIntrinsicID((Intrinsic::ID)-1); 378 { 379 // Print a MachineOperand containing a target-specific intrinsic ID but not 380 // IntrinsicInfo. 381 raw_string_ostream OS(str); 382 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 383 ASSERT_TRUE(OS.str() == "intrinsic(4294967295)"); 384 } 385 } 386 387 TEST(MachineOperandTest, PrintPredicate) { 388 // Create a MachineOperand with a generic intrinsic ID. 389 MachineOperand MO = MachineOperand::CreatePredicate(CmpInst::ICMP_EQ); 390 391 // Checking some preconditions on the newly created 392 // MachineOperand. 393 ASSERT_TRUE(MO.isPredicate()); 394 ASSERT_TRUE(MO.getPredicate() == CmpInst::ICMP_EQ); 395 396 std::string str; 397 // Print a MachineOperand containing a int predicate ICMP_EQ. 398 raw_string_ostream OS(str); 399 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 400 ASSERT_TRUE(OS.str() == "intpred(eq)"); 401 } 402 403 TEST(MachineOperandTest, HashValue) { 404 char SymName1[] = "test"; 405 char SymName2[] = "test"; 406 MachineOperand MO1 = MachineOperand::CreateES(SymName1); 407 MachineOperand MO2 = MachineOperand::CreateES(SymName2); 408 ASSERT_NE(SymName1, SymName2); 409 ASSERT_EQ(hash_value(MO1), hash_value(MO2)); 410 ASSERT_TRUE(MO1.isIdenticalTo(MO2)); 411 } 412 413 } // end namespace 414