brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.3 KiB · 4d28fe0 Raw
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