1 | //===- llvm/unittest/IR/AsmWriter.cpp - AsmWriter 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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | #include "llvm/BinaryFormat/Dwarf.h" |
9 | #include "llvm/IR/DebugInfoMetadata.h" |
10 | #include "llvm/IR/Function.h" |
11 | #include "llvm/IR/IRBuilder.h" |
12 | #include "llvm/IR/LLVMContext.h" |
13 | #include "llvm/IR/MDBuilder.h" |
14 | #include "llvm/IR/Module.h" |
15 | #include "gmock/gmock.h" |
16 | #include "gtest/gtest.h" |
17 | |
18 | using namespace llvm; |
19 | using ::testing::HasSubstr; |
20 | |
21 | namespace { |
22 | |
23 | TEST(AsmWriterTest, DebugPrintDetachedInstruction) { |
24 | |
25 | // PR24852: Ensure that an instruction can be printed even when it |
26 | // has metadata attached but no parent. |
27 | LLVMContext Ctx; |
28 | auto Ty = Type::getInt32Ty(C&: Ctx); |
29 | auto Poison = PoisonValue::get(T: Ty); |
30 | std::unique_ptr<BinaryOperator> Add(BinaryOperator::CreateAdd(V1: Poison, V2: Poison)); |
31 | Add->setMetadata( |
32 | Kind: "" , Node: MDNode::get(Context&: Ctx, MDs: {ConstantAsMetadata::get(C: ConstantInt::get(Ty, V: 1))})); |
33 | std::string S; |
34 | raw_string_ostream OS(S); |
35 | Add->print(O&: OS); |
36 | EXPECT_THAT(OS.str(), |
37 | HasSubstr("<badref> = add i32 poison, poison, !<empty" )); |
38 | } |
39 | |
40 | TEST(AsmWriterTest, DebugPrintDetachedArgument) { |
41 | LLVMContext Ctx; |
42 | auto Ty = Type::getInt32Ty(C&: Ctx); |
43 | auto Arg = new Argument(Ty); |
44 | |
45 | std::string S; |
46 | raw_string_ostream OS(S); |
47 | Arg->print(O&: OS); |
48 | EXPECT_EQ(S, "i32 <badref>" ); |
49 | delete Arg; |
50 | } |
51 | |
52 | TEST(AsmWriterTest, DumpDIExpression) { |
53 | LLVMContext Ctx; |
54 | uint64_t Ops[] = { |
55 | dwarf::DW_OP_constu, 4, |
56 | dwarf::DW_OP_minus, |
57 | dwarf::DW_OP_deref, |
58 | }; |
59 | DIExpression *Expr = DIExpression::get(Context&: Ctx, Elements: Ops); |
60 | std::string S; |
61 | raw_string_ostream OS(S); |
62 | Expr->print(OS); |
63 | EXPECT_EQ("!DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_deref)" , |
64 | OS.str()); |
65 | } |
66 | |
67 | TEST(AsmWriterTest, PrintAddrspaceWithNullOperand) { |
68 | LLVMContext Ctx; |
69 | Module M("test module" , Ctx); |
70 | SmallVector<Type *, 3> FArgTypes; |
71 | FArgTypes.push_back(Elt: Type::getInt64Ty(C&: Ctx)); |
72 | FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Ctx), Params: FArgTypes, isVarArg: false); |
73 | Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "" , M: &M); |
74 | Argument *Arg0 = F->getArg(i: 0); |
75 | Value *Args[] = {Arg0}; |
76 | std::unique_ptr<CallInst> Call(CallInst::Create(Func: F, Args)); |
77 | // This will make Call's operand null. |
78 | Call->dropAllReferences(); |
79 | |
80 | std::string S; |
81 | raw_string_ostream OS(S); |
82 | Call->print(O&: OS); |
83 | EXPECT_THAT(OS.str(), HasSubstr("<cannot get addrspace!>" )); |
84 | } |
85 | |
86 | TEST(AsmWriterTest, PrintNullOperandBundle) { |
87 | LLVMContext C; |
88 | Type *Int32Ty = Type::getInt32Ty(C); |
89 | FunctionType *FnTy = FunctionType::get(Result: Int32Ty, Params: Int32Ty, /*isVarArg=*/false); |
90 | Value *Callee = Constant::getNullValue(Ty: PointerType::getUnqual(C)); |
91 | Value *Args[] = {ConstantInt::get(Ty: Int32Ty, V: 42)}; |
92 | std::unique_ptr<BasicBlock> NormalDest(BasicBlock::Create(Context&: C)); |
93 | std::unique_ptr<BasicBlock> UnwindDest(BasicBlock::Create(Context&: C)); |
94 | OperandBundleDef Bundle("bundle" , UndefValue::get(T: Int32Ty)); |
95 | std::unique_ptr<InvokeInst> Invoke( |
96 | InvokeInst::Create(Ty: FnTy, Func: Callee, IfNormal: NormalDest.get(), IfException: UnwindDest.get(), Args, |
97 | Bundles: Bundle, NameStr: "result" )); |
98 | // Makes the operand bundle null. |
99 | Invoke->dropAllReferences(); |
100 | Invoke->setNormalDest(NormalDest.get()); |
101 | Invoke->setUnwindDest(UnwindDest.get()); |
102 | |
103 | std::string S; |
104 | raw_string_ostream OS(S); |
105 | Invoke->print(O&: OS); |
106 | EXPECT_THAT(OS.str(), HasSubstr("<null operand bundle!>" )); |
107 | } |
108 | } |
109 | |