350 lines · cpp
1//===- llvm/unittest/IR/ValueTest.cpp - Value unit tests ------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/Value.h"10#include "llvm-c/Core.h"11#include "llvm/AsmParser/Parser.h"12#include "llvm/IR/Function.h"13#include "llvm/IR/IntrinsicInst.h"14#include "llvm/IR/LLVMContext.h"15#include "llvm/IR/Module.h"16#include "llvm/IR/ModuleSlotTracker.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Support/Compiler.h"19#include "llvm/Support/SourceMgr.h"20#include "gtest/gtest.h"21using namespace llvm;22 23namespace {24 25TEST(ValueTest, UsedInBasicBlock) {26 LLVMContext C;27 28 const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"29 "bb0:\n"30 " %y1 = add i32 %y, 1\n"31 " %y2 = add i32 %y, 1\n"32 " %y3 = add i32 %y, 1\n"33 " %y4 = add i32 %y, 1\n"34 " %y5 = add i32 %y, 1\n"35 " %y6 = add i32 %y, 1\n"36 " %y7 = add i32 %y, 1\n"37 " %y8 = add i32 %x, 1\n"38 " ret void\n"39 "}\n";40 SMDiagnostic Err;41 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);42 43 Function *F = M->getFunction("f");44 45 EXPECT_FALSE(F->isUsedInBasicBlock(&F->front()));46 EXPECT_TRUE(std::next(F->arg_begin())->isUsedInBasicBlock(&F->front()));47 EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(&F->front()));48}49 50TEST(GlobalTest, CreateAddressSpace) {51 LLVMContext Ctx;52 std::unique_ptr<Module> M(new Module("TestModule", Ctx));53 Type *Int8Ty = Type::getInt8Ty(Ctx);54 Type *Int32Ty = Type::getInt32Ty(Ctx);55 56 GlobalVariable *Dummy057 = new GlobalVariable(*M,58 Int32Ty,59 true,60 GlobalValue::ExternalLinkage,61 Constant::getAllOnesValue(Int32Ty),62 "dummy",63 nullptr,64 GlobalVariable::NotThreadLocal,65 1);66 67 const Align kMaxAlignment(Value::MaximumAlignment);68 EXPECT_TRUE(kMaxAlignment.value() == 4294967296ULL);69 Dummy0->setAlignment(kMaxAlignment);70 EXPECT_TRUE(Dummy0->getAlign());71 EXPECT_EQ(*Dummy0->getAlign(), kMaxAlignment);72 73 // Make sure the address space isn't dropped when returning this.74 Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);75 EXPECT_EQ(Dummy0, Dummy1);76 EXPECT_EQ(1u, Dummy1->getType()->getPointerAddressSpace());77 78 79 // This one requires a bitcast, but the address space must also stay the same.80 GlobalVariable *DummyCast081 = new GlobalVariable(*M,82 Int32Ty,83 true,84 GlobalValue::ExternalLinkage,85 Constant::getAllOnesValue(Int32Ty),86 "dummy_cast",87 nullptr,88 GlobalVariable::NotThreadLocal,89 1);90 91 // Make sure the address space isn't dropped when returning this.92 Constant *DummyCast1 = M->getOrInsertGlobal("dummy_cast", Int8Ty);93 EXPECT_EQ(DummyCast0, DummyCast1);94 EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());95}96 97#ifdef GTEST_HAS_DEATH_TEST98#ifndef NDEBUG99 100TEST(GlobalTest, AlignDeath) {101 LLVMContext Ctx;102 std::unique_ptr<Module> M(new Module("TestModule", Ctx));103 Type *Int32Ty = Type::getInt32Ty(Ctx);104 GlobalVariable *Var =105 new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage,106 Constant::getAllOnesValue(Int32Ty), "var", nullptr,107 GlobalVariable::NotThreadLocal, 1);108 109 EXPECT_DEATH(Var->setAlignment(Align(8589934592ULL)),110 "Alignment is greater than MaximumAlignment");111}112#endif113#endif114 115TEST(ValueTest, printSlots) {116 // Check that Value::print() and Value::printAsOperand() work with and117 // without a slot tracker.118 LLVMContext C;119 120 const char *ModuleString = "@g0 = external global %500\n"121 "@g1 = external global %900\n"122 "\n"123 "%900 = type { i32, i32 }\n"124 "%500 = type { i32 }\n"125 "\n"126 "define void @f(i32 %x, i32 %y) {\n"127 "entry:\n"128 " %0 = add i32 %y, 1\n"129 " %1 = add i32 %y, 1\n"130 " ret void\n"131 "}\n";132 SMDiagnostic Err;133 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);134 135 Function *F = M->getFunction("f");136 ASSERT_TRUE(F);137 ASSERT_FALSE(F->empty());138 BasicBlock &BB = F->getEntryBlock();139 ASSERT_EQ(3u, BB.size());140 141 Instruction *I0 = &*BB.begin();142 ASSERT_TRUE(I0);143 Instruction *I1 = &*++BB.begin();144 ASSERT_TRUE(I1);145 146 GlobalVariable *G0 = M->getGlobalVariable("g0");147 ASSERT_TRUE(G0);148 GlobalVariable *G1 = M->getGlobalVariable("g1");149 ASSERT_TRUE(G1);150 151 ModuleSlotTracker MST(M.get());152 153#define CHECK_PRINT(INST, STR) \154 do { \155 { \156 std::string S; \157 raw_string_ostream OS(S); \158 INST->print(OS); \159 EXPECT_EQ(STR, S); \160 } \161 { \162 std::string S; \163 raw_string_ostream OS(S); \164 INST->print(OS, MST); \165 EXPECT_EQ(STR, S); \166 } \167 } while (false)168 CHECK_PRINT(I0, " %0 = add i32 %y, 1");169 CHECK_PRINT(I1, " %1 = add i32 %y, 1");170#undef CHECK_PRINT171 172#define CHECK_PRINT_AS_OPERAND(INST, TYPE, STR) \173 do { \174 { \175 std::string S; \176 raw_string_ostream OS(S); \177 INST->printAsOperand(OS, TYPE); \178 EXPECT_EQ(StringRef(STR), StringRef(S)); \179 } \180 { \181 std::string S; \182 raw_string_ostream OS(S); \183 INST->printAsOperand(OS, TYPE, MST); \184 EXPECT_EQ(StringRef(STR), StringRef(S)); \185 } \186 } while (false)187 CHECK_PRINT_AS_OPERAND(I0, false, "%0");188 CHECK_PRINT_AS_OPERAND(I1, false, "%1");189 CHECK_PRINT_AS_OPERAND(I0, true, "i32 %0");190 CHECK_PRINT_AS_OPERAND(I1, true, "i32 %1");191 CHECK_PRINT_AS_OPERAND(G0, true, "ptr @g0");192 CHECK_PRINT_AS_OPERAND(G1, true, "ptr @g1");193#undef CHECK_PRINT_AS_OPERAND194}195 196TEST(ValueTest, getLocalSlots) {197 // Verify that the getLocalSlot method returns the correct slot numbers.198 LLVMContext C;199 const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"200 "entry:\n"201 " %0 = add i32 %y, 1\n"202 " %1 = add i32 %y, 1\n"203 " br label %2\n"204 "\n"205 " ret void\n"206 "}\n";207 SMDiagnostic Err;208 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);209 210 Function *F = M->getFunction("f");211 ASSERT_TRUE(F);212 ASSERT_FALSE(F->empty());213 BasicBlock &EntryBB = F->getEntryBlock();214 ASSERT_EQ(3u, EntryBB.size());215 BasicBlock *BB2 = &*++F->begin();216 ASSERT_TRUE(BB2);217 218 Instruction *I0 = &*EntryBB.begin();219 ASSERT_TRUE(I0);220 Instruction *I1 = &*++EntryBB.begin();221 ASSERT_TRUE(I1);222 223 ModuleSlotTracker MST(M.get());224 MST.incorporateFunction(*F);225 EXPECT_EQ(MST.getLocalSlot(I0), 0);226 EXPECT_EQ(MST.getLocalSlot(I1), 1);227 EXPECT_EQ(MST.getLocalSlot(&EntryBB), -1);228 EXPECT_EQ(MST.getLocalSlot(BB2), 2);229}230 231#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)232TEST(ValueTest, getLocalSlotDeath) {233 LLVMContext C;234 const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"235 "entry:\n"236 " %0 = add i32 %y, 1\n"237 " %1 = add i32 %y, 1\n"238 " br label %2\n"239 "\n"240 " ret void\n"241 "}\n";242 SMDiagnostic Err;243 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);244 245 Function *F = M->getFunction("f");246 ASSERT_TRUE(F);247 ASSERT_FALSE(F->empty());248 BasicBlock *BB2 = &*++F->begin();249 ASSERT_TRUE(BB2);250 251 ModuleSlotTracker MST(M.get());252 EXPECT_DEATH(MST.getLocalSlot(BB2), "No function incorporated");253}254#endif255 256TEST(ValueTest, replaceUsesOutsideBlock) {257 // Check that Value::replaceUsesOutsideBlock(New, BB) replaces uses outside258 // BB, including DbgVariableRecords.259 const auto *IR = R"(260 define i32 @f() !dbg !6 {261 entry:262 %a = add i32 0, 1, !dbg !15263 %b = add i32 0, 2, !dbg !15264 %c = add i32 %a, 2, !dbg !15265 call void @llvm.dbg.value(metadata i32 %a, metadata !9, metadata !DIExpression()), !dbg !15266 br label %exit, !dbg !15267 268 exit:269 call void @llvm.dbg.value(metadata i32 %a, metadata !11, metadata !DIExpression()), !dbg !16270 ret i32 %a, !dbg !16271 }272 273 declare void @llvm.dbg.value(metadata, metadata, metadata)274 275 !llvm.dbg.cu = !{!0}276 !llvm.module.flags = !{!5}277 278 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)279 !1 = !DIFile(filename: "test.ll", directory: "/")280 !2 = !{}281 !5 = !{i32 2, !"Debug Info Version", i32 3}282 !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)283 !7 = !DISubroutineType(types: !2)284 !8 = !{!9, !11}285 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)286 !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed)287 !11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !12)288 !12 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_signed)289 !15 = !DILocation(line: 1, column: 1, scope: !6)290 !16 = !DILocation(line: 5, column: 1, scope: !6)291 )";292 LLVMContext Ctx;293 SMDiagnostic Err;294 std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx);295 if (!M)296 Err.print("ValueTest", errs());297 298 auto GetNext = [](auto *I) { return &*++I->getIterator(); };299 300 Function *F = M->getFunction("f");301 // Entry.302 BasicBlock *Entry = &F->front();303 Instruction *A = &Entry->front();304 Instruction *B = GetNext(A);305 Instruction *C = GetNext(B);306 Instruction *Branch = GetNext(C);307 // Exit.308 BasicBlock *Exit = GetNext(Entry);309 Instruction *Ret = &Exit->front();310 311 EXPECT_TRUE(Branch->hasDbgRecords());312 EXPECT_TRUE(Ret->hasDbgRecords());313 314 DbgVariableRecord *DVR1 =315 cast<DbgVariableRecord>(&*Branch->getDbgRecordRange().begin());316 DbgVariableRecord *DVR2 =317 cast<DbgVariableRecord>(&*Ret->getDbgRecordRange().begin());318 319 A->replaceUsesOutsideBlock(B, Entry);320 // These users are in Entry so shouldn't be changed.321 EXPECT_TRUE(DVR1->getVariableLocationOp(0) == cast<Value>(A));322 // These users are outside Entry so should be changed.323 EXPECT_TRUE(DVR2->getVariableLocationOp(0) == cast<Value>(B));324}325 326TEST(GlobalTest, Initializer) {327 LLVMContext Ctx;328 Module M("test", Ctx);329 Type *Int8Ty = Type::getInt8Ty(Ctx);330 Constant *Int8Null = Constant::getNullValue(Int8Ty);331 332 GlobalVariable *GV = new GlobalVariable(333 M, Int8Ty, false, GlobalValue::ExternalLinkage, nullptr, "GV");334 335 EXPECT_FALSE(GV->hasInitializer());336 GV->setInitializer(Int8Null);337 EXPECT_TRUE(GV->hasInitializer());338 EXPECT_EQ(GV->getInitializer(), Int8Null);339 GV->setInitializer(nullptr);340 EXPECT_FALSE(GV->hasInitializer());341 342 EXPECT_EQ(LLVMGetInitializer(wrap(GV)), nullptr);343 LLVMSetInitializer(wrap(GV), wrap(Int8Null));344 EXPECT_EQ(LLVMGetInitializer(wrap(GV)), wrap(Int8Null));345 LLVMSetInitializer(wrap(GV), nullptr);346 EXPECT_EQ(LLVMGetInitializer(wrap(GV)), nullptr);347}348 349} // end anonymous namespace350