1*8dbe44cbSFlorian Hahn //===-- Annotation2Metadata.cpp - Add !annotation metadata. ---------------===//
2*8dbe44cbSFlorian Hahn //
3*8dbe44cbSFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*8dbe44cbSFlorian Hahn // See https://llvm.org/LICENSE.txt for license information.
5*8dbe44cbSFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*8dbe44cbSFlorian Hahn //
7*8dbe44cbSFlorian Hahn //===----------------------------------------------------------------------===//
8*8dbe44cbSFlorian Hahn //
9*8dbe44cbSFlorian Hahn // Add !annotation metadata for entries in @llvm.global.anotations, generated
10*8dbe44cbSFlorian Hahn // using __attribute__((annotate("_name"))) on functions in Clang.
11*8dbe44cbSFlorian Hahn //
12*8dbe44cbSFlorian Hahn //===----------------------------------------------------------------------===//
13*8dbe44cbSFlorian Hahn 
14*8dbe44cbSFlorian Hahn #include "llvm/Transforms/IPO/Annotation2Metadata.h"
15*8dbe44cbSFlorian Hahn #include "llvm/Analysis/OptimizationRemarkEmitter.h"
16*8dbe44cbSFlorian Hahn #include "llvm/IR/Constants.h"
17*8dbe44cbSFlorian Hahn #include "llvm/IR/Function.h"
18*8dbe44cbSFlorian Hahn #include "llvm/IR/InstIterator.h"
19*8dbe44cbSFlorian Hahn #include "llvm/IR/Module.h"
20*8dbe44cbSFlorian Hahn #include "llvm/InitializePasses.h"
21*8dbe44cbSFlorian Hahn #include "llvm/Pass.h"
22*8dbe44cbSFlorian Hahn #include "llvm/Transforms/IPO.h"
23*8dbe44cbSFlorian Hahn 
24*8dbe44cbSFlorian Hahn using namespace llvm;
25*8dbe44cbSFlorian Hahn 
26*8dbe44cbSFlorian Hahn #define DEBUG_TYPE "annotation2metadata"
27*8dbe44cbSFlorian Hahn 
convertAnnotation2Metadata(Module & M)28*8dbe44cbSFlorian Hahn static bool convertAnnotation2Metadata(Module &M) {
29*8dbe44cbSFlorian Hahn   // Only add !annotation metadata if the corresponding remarks pass is also
30*8dbe44cbSFlorian Hahn   // enabled.
31*8dbe44cbSFlorian Hahn   if (!OptimizationRemarkEmitter::allowExtraAnalysis(M.getContext(),
32*8dbe44cbSFlorian Hahn                                                      "annotation-remarks"))
33*8dbe44cbSFlorian Hahn     return false;
34*8dbe44cbSFlorian Hahn 
35*8dbe44cbSFlorian Hahn   auto *Annotations = M.getGlobalVariable("llvm.global.annotations");
36*8dbe44cbSFlorian Hahn   auto *C = dyn_cast_or_null<Constant>(Annotations);
37*8dbe44cbSFlorian Hahn   if (!C || C->getNumOperands() != 1)
38*8dbe44cbSFlorian Hahn     return false;
39*8dbe44cbSFlorian Hahn 
40*8dbe44cbSFlorian Hahn   C = cast<Constant>(C->getOperand(0));
41*8dbe44cbSFlorian Hahn 
42*8dbe44cbSFlorian Hahn   // Iterate over all entries in C and attach !annotation metadata to suitable
43*8dbe44cbSFlorian Hahn   // entries.
44*8dbe44cbSFlorian Hahn   for (auto &Op : C->operands()) {
45*8dbe44cbSFlorian Hahn     // Look at the operands to check if we can use the entry to generate
46*8dbe44cbSFlorian Hahn     // !annotation metadata.
47*8dbe44cbSFlorian Hahn     auto *OpC = dyn_cast<ConstantStruct>(&Op);
48*8dbe44cbSFlorian Hahn     if (!OpC || OpC->getNumOperands() != 4)
49*8dbe44cbSFlorian Hahn       continue;
50*8dbe44cbSFlorian Hahn     auto *StrGEP = dyn_cast<ConstantExpr>(OpC->getOperand(1));
51*8dbe44cbSFlorian Hahn     if (!StrGEP || StrGEP->getNumOperands() < 2)
52*8dbe44cbSFlorian Hahn       continue;
53*8dbe44cbSFlorian Hahn     auto *StrC = dyn_cast<GlobalValue>(StrGEP->getOperand(0));
54*8dbe44cbSFlorian Hahn     if (!StrC)
55*8dbe44cbSFlorian Hahn       continue;
56*8dbe44cbSFlorian Hahn     auto *StrData = dyn_cast<ConstantDataSequential>(StrC->getOperand(0));
57*8dbe44cbSFlorian Hahn     if (!StrData)
58*8dbe44cbSFlorian Hahn       continue;
59*8dbe44cbSFlorian Hahn     // Look through bitcast.
60*8dbe44cbSFlorian Hahn     auto *Bitcast = dyn_cast<ConstantExpr>(OpC->getOperand(0));
61*8dbe44cbSFlorian Hahn     if (!Bitcast || Bitcast->getOpcode() != Instruction::BitCast)
62*8dbe44cbSFlorian Hahn       continue;
63*8dbe44cbSFlorian Hahn     auto *Fn = dyn_cast<Function>(Bitcast->getOperand(0));
64*8dbe44cbSFlorian Hahn     if (!Fn)
65*8dbe44cbSFlorian Hahn       continue;
66*8dbe44cbSFlorian Hahn 
67*8dbe44cbSFlorian Hahn     // Add annotation to all instructions in the function.
68*8dbe44cbSFlorian Hahn     for (auto &I : instructions(Fn))
69*8dbe44cbSFlorian Hahn       I.addAnnotationMetadata(StrData->getAsCString());
70*8dbe44cbSFlorian Hahn   }
71*8dbe44cbSFlorian Hahn   return true;
72*8dbe44cbSFlorian Hahn }
73*8dbe44cbSFlorian Hahn 
74*8dbe44cbSFlorian Hahn namespace {
75*8dbe44cbSFlorian Hahn struct Annotation2MetadataLegacy : public ModulePass {
76*8dbe44cbSFlorian Hahn   static char ID;
77*8dbe44cbSFlorian Hahn 
Annotation2MetadataLegacy__anon9b1343c30111::Annotation2MetadataLegacy78*8dbe44cbSFlorian Hahn   Annotation2MetadataLegacy() : ModulePass(ID) {
79*8dbe44cbSFlorian Hahn     initializeAnnotation2MetadataLegacyPass(*PassRegistry::getPassRegistry());
80*8dbe44cbSFlorian Hahn   }
81*8dbe44cbSFlorian Hahn 
runOnModule__anon9b1343c30111::Annotation2MetadataLegacy82*8dbe44cbSFlorian Hahn   bool runOnModule(Module &M) override { return convertAnnotation2Metadata(M); }
83*8dbe44cbSFlorian Hahn 
getAnalysisUsage__anon9b1343c30111::Annotation2MetadataLegacy84*8dbe44cbSFlorian Hahn   void getAnalysisUsage(AnalysisUsage &AU) const override {
85*8dbe44cbSFlorian Hahn     AU.setPreservesAll();
86*8dbe44cbSFlorian Hahn   }
87*8dbe44cbSFlorian Hahn };
88*8dbe44cbSFlorian Hahn 
89*8dbe44cbSFlorian Hahn } // end anonymous namespace
90*8dbe44cbSFlorian Hahn 
91*8dbe44cbSFlorian Hahn char Annotation2MetadataLegacy::ID = 0;
92*8dbe44cbSFlorian Hahn 
93*8dbe44cbSFlorian Hahn INITIALIZE_PASS_BEGIN(Annotation2MetadataLegacy, DEBUG_TYPE,
94*8dbe44cbSFlorian Hahn                       "Annotation2Metadata", false, false)
95*8dbe44cbSFlorian Hahn INITIALIZE_PASS_END(Annotation2MetadataLegacy, DEBUG_TYPE,
96*8dbe44cbSFlorian Hahn                     "Annotation2Metadata", false, false)
97*8dbe44cbSFlorian Hahn 
createAnnotation2MetadataLegacyPass()98*8dbe44cbSFlorian Hahn ModulePass *llvm::createAnnotation2MetadataLegacyPass() {
99*8dbe44cbSFlorian Hahn   return new Annotation2MetadataLegacy();
100*8dbe44cbSFlorian Hahn }
101*8dbe44cbSFlorian Hahn 
run(Module & M,ModuleAnalysisManager & AM)102*8dbe44cbSFlorian Hahn PreservedAnalyses Annotation2MetadataPass::run(Module &M,
103*8dbe44cbSFlorian Hahn                                                ModuleAnalysisManager &AM) {
104*8dbe44cbSFlorian Hahn   convertAnnotation2Metadata(M);
105*8dbe44cbSFlorian Hahn   return PreservedAnalyses::all();
106*8dbe44cbSFlorian Hahn }
107