brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · cfd99ed Raw
201 lines · cpp
1//===- llvm/unittest/IR/IntrinsicsTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/Intrinsics.h"10#include "llvm/ADT/SmallVector.h"11#include "llvm/IR/Constant.h"12#include "llvm/IR/IRBuilder.h"13#include "llvm/IR/IntrinsicInst.h"14#include "llvm/IR/IntrinsicsAArch64.h"15#include "llvm/IR/IntrinsicsAMDGPU.h"16#include "llvm/IR/IntrinsicsARM.h"17#include "llvm/IR/IntrinsicsBPF.h"18#include "llvm/IR/IntrinsicsDirectX.h"19#include "llvm/IR/IntrinsicsHexagon.h"20#include "llvm/IR/IntrinsicsLoongArch.h"21#include "llvm/IR/IntrinsicsMips.h"22#include "llvm/IR/IntrinsicsNVPTX.h"23#include "llvm/IR/IntrinsicsPowerPC.h"24#include "llvm/IR/IntrinsicsRISCV.h"25#include "llvm/IR/IntrinsicsS390.h"26#include "llvm/IR/IntrinsicsX86.h"27#include "llvm/IR/Module.h"28#include "gtest/gtest.h"29 30using namespace llvm;31 32namespace {33 34class IntrinsicsTest : public ::testing::Test {35  LLVMContext Context;36  std::unique_ptr<Module> M;37  BasicBlock *BB = nullptr;38 39  void TearDown() override { M.reset(); }40 41  void SetUp() override {42    M = std::make_unique<Module>("Test", Context);43    auto F = M->getOrInsertFunction(44        "test", FunctionType::get(Type::getVoidTy(Context), false));45    BB = BasicBlock::Create(Context, "", cast<Function>(F.getCallee()));46    EXPECT_NE(BB, nullptr);47  }48 49public:50  Instruction *makeIntrinsic(Intrinsic::ID ID) const {51    IRBuilder<> Builder(BB);52    SmallVector<Value *, 4> ProcessedArgs;53    auto *Decl = Intrinsic::getOrInsertDeclaration(M.get(), ID);54    for (auto *Ty : Decl->getFunctionType()->params()) {55      auto *Val = Constant::getNullValue(Ty);56      ProcessedArgs.push_back(Val);57    }58    return Builder.CreateCall(Decl, ProcessedArgs);59  }60  template <typename T> void checkIsa(const Instruction &I) {61    EXPECT_TRUE(isa<T>(I));62  }63};64 65TEST(IntrinsicNameLookup, Basic) {66  using namespace Intrinsic;67  EXPECT_EQ(Intrinsic::memcpy, lookupIntrinsicID("llvm.memcpy"));68 69  // Partial, either between dots or not the last dot are not intrinsics.70  EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.mem"));71  EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.gc"));72 73  // Look through intrinsic names with internal dots.74  EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline"));75 76  // Check that overloaded names are mapped to the underlying ID.77  EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i8"));78  EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i32"));79  EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i64"));80  EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i1024"));81}82 83TEST(IntrinsicNameLookup, NonNullterminatedStringRef) {84  using namespace Intrinsic;85  // This reproduces an issue where lookupIntrinsicID() can access memory beyond86  // the bounds of the passed in StringRef. For ASAN to catch this as an error,87  // create a StringRef using heap allocated memory and make it not null88  // terminated.89 90  // ASAN will report a "AddressSanitizer: heap-buffer-overflow" error in91  // `lookupLLVMIntrinsicByName` when LLVM is built with these options:92  //  -DCMAKE_BUILD_TYPE=Debug93  //  -DLLVM_USE_SANITIZER=Address94  //  -DLLVM_OPTIMIZE_SANITIZED_BUILDS=OFF95 96  // Make an intrinsic name "llvm.memcpy.inline" on the heap.97  std::string Name = "llvm.memcpy.inline";98  assert(Name.size() == 18);99  // Create a StringRef backed by heap allocated memory such that OOB access100  // in that StringRef can be flagged by asan. Here, the String `S` is of size101  // 18, and backed by a heap allocated buffer `Data`, so access to S[18] will102  // be flagged bby asan.103  auto Data = std::make_unique<char[]>(Name.size());104  std::strncpy(Data.get(), Name.data(), Name.size());105  StringRef S(Data.get(), Name.size());106  EXPECT_EQ(memcpy_inline, lookupIntrinsicID(S));107}108 109// Tests to verify getIntrinsicForClangBuiltin.110TEST(IntrinsicNameLookup, ClangBuiltinLookup) {111  using namespace Intrinsic;112  static constexpr std::tuple<StringRef, StringRef, ID> ClangTests[] = {113      {"__builtin_adjust_trampoline", "", adjust_trampoline},114      {"__builtin_trap", "", trap},115      {"__builtin_arm_chkfeat", "aarch64", aarch64_chkfeat},116      {"__builtin_amdgcn_alignbyte", "amdgcn", amdgcn_alignbyte},117      {"__builtin_amdgcn_workgroup_id_z", "amdgcn", amdgcn_workgroup_id_z},118      {"__builtin_arm_cdp", "arm", arm_cdp},119      {"__builtin_bpf_preserve_type_info", "bpf", bpf_preserve_type_info},120      {"__builtin_HEXAGON_A2_tfr", "hexagon", hexagon_A2_tfr},121      {"__builtin_lasx_xbz_w", "loongarch", loongarch_lasx_xbz_w},122      {"__builtin_mips_bitrev", "mips", mips_bitrev},123      {"__nvvm_add_rn_d", "nvvm", nvvm_add_rn_d},124      {"__builtin_altivec_dss", "ppc", ppc_altivec_dss},125      {"__builtin_riscv_sha512sum1r", "riscv", riscv_sha512sum1r},126      {"__builtin_tend", "s390", s390_tend},127      {"__builtin_ia32_pause", "x86", x86_sse2_pause},128 129      {"__does_not_exist", "", not_intrinsic},130      {"__does_not_exist", "arm", not_intrinsic},131      {"__builtin_arm_cdp", "", not_intrinsic},132      {"__builtin_arm_cdp", "x86", not_intrinsic},133  };134 135  for (const auto &[Builtin, Target, ID] : ClangTests)136    EXPECT_EQ(ID, getIntrinsicForClangBuiltin(Target, Builtin));137}138 139// Tests to verify getIntrinsicForMSBuiltin.140TEST(IntrinsicNameLookup, MSBuiltinLookup) {141  using namespace Intrinsic;142  static constexpr std::tuple<StringRef, StringRef, ID> MSTests[] = {143      {"__dmb", "aarch64", aarch64_dmb},144      {"__dmb", "arm", arm_dmb},145      {"__dmb", "", not_intrinsic},146      {"__does_not_exist", "", not_intrinsic},147      {"__does_not_exist", "arm", not_intrinsic},148  };149  for (const auto &[Builtin, Target, ID] : MSTests)150    EXPECT_EQ(ID, getIntrinsicForMSBuiltin(Target, Builtin));151}152 153TEST_F(IntrinsicsTest, InstrProfInheritance) {154  auto isInstrProfInstBase = [](const Instruction &I) {155    return isa<InstrProfInstBase>(I);156  };157#define __ISA(TYPE, PARENT)                                                    \158  auto is##TYPE = [&](const Instruction &I) -> bool {                          \159    return isa<TYPE>(I) && is##PARENT(I);                                      \160  }161  __ISA(InstrProfCntrInstBase, InstrProfInstBase);162  __ISA(InstrProfCoverInst, InstrProfCntrInstBase);163  __ISA(InstrProfIncrementInst, InstrProfCntrInstBase);164  __ISA(InstrProfIncrementInstStep, InstrProfIncrementInst);165  __ISA(InstrProfCallsite, InstrProfCntrInstBase);166  __ISA(InstrProfTimestampInst, InstrProfCntrInstBase);167  __ISA(InstrProfValueProfileInst, InstrProfCntrInstBase);168  __ISA(InstrProfMCDCBitmapInstBase, InstrProfInstBase);169  __ISA(InstrProfMCDCBitmapParameters, InstrProfMCDCBitmapInstBase);170  __ISA(InstrProfMCDCTVBitmapUpdate, InstrProfMCDCBitmapInstBase);171#undef __ISA172 173  std::vector<174      std::pair<Intrinsic::ID, std::function<bool(const Instruction &)>>>175      LeafIDs = {176          {Intrinsic::instrprof_cover, isInstrProfCoverInst},177          {Intrinsic::instrprof_increment, isInstrProfIncrementInst},178          {Intrinsic::instrprof_increment_step, isInstrProfIncrementInstStep},179          {Intrinsic::instrprof_callsite, isInstrProfCallsite},180          {Intrinsic::instrprof_mcdc_parameters,181           isInstrProfMCDCBitmapParameters},182          {Intrinsic::instrprof_mcdc_tvbitmap_update,183           isInstrProfMCDCTVBitmapUpdate},184          {Intrinsic::instrprof_timestamp, isInstrProfTimestampInst},185          {Intrinsic::instrprof_value_profile, isInstrProfValueProfileInst}};186  for (const auto &[ID, Checker] : LeafIDs) {187    auto *Intr = makeIntrinsic(ID);188    EXPECT_TRUE(Checker(*Intr));189  }190}191 192// Check that getFnAttributes for intrinsics that do not have any function193// attributes correcty returns an empty set.194TEST(IntrinsicAttributes, TestGetFnAttributesBug) {195  using namespace Intrinsic;196  LLVMContext Context;197  AttributeSet AS = getFnAttributes(Context, experimental_guard);198  EXPECT_FALSE(AS.hasAttributes());199}200} // end namespace201