blob: 08b1aeacff81bad1542f9a09a9d17939395b5e43 [file] [edit]
// Copyright 2022 The Clspv Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "llvm/IR/Constants.h"
#include "llvm/IR/Operator.h"
#include "AnnotationToMetadataPass.h"
#include "Constants.h"
using namespace llvm;
PreservedAnalyses
clspv::AnnotationToMetadataPass::run(Module &M, ModuleAnalysisManager &) {
for (auto &GV : M.globals()) {
if (GV.getName() == "llvm.global.annotations") {
// metadata node to write to
auto &context = M.getContext();
NamedMDNode *md_node =
M.getOrInsertNamedMetadata(clspv::EntryPointAttributesMetadataName());
// list of processed strings to delete at the end
SmallPtrSet<GlobalValue *, 4> to_erase;
SmallPtrSet<Constant *, 4> addrspacecast_to_erase;
ConstantArray *annotations_array =
dyn_cast<ConstantArray>(GV.getOperand(0));
for (auto &annotation_entry : annotations_array->operands()) {
ConstantStruct *annotation_struct =
dyn_cast<ConstantStruct>(annotation_entry.get());
auto op0 = annotation_struct->getOperand(0);
if (isa<AddrSpaceCastOperator>(op0)) {
// We need to make sure to erase those to avoid keeping a reference on
// functions preventing them from being removed
addrspacecast_to_erase.insert(op0);
}
Function *entry_point = dyn_cast<Function>(op0->stripPointerCasts());
auto op1 = annotation_struct->getOperand(1);
GlobalVariable *annotation_gv = dyn_cast<GlobalVariable>(op1);
StringRef annotation =
dyn_cast<ConstantDataArray>(annotation_gv->getInitializer())
->getAsCString();
const auto entry_point_name_md =
MDString::get(context, entry_point->getName());
const auto attrs_md = MDString::get(context, annotation);
MDTuple *entry =
MDTuple::get(M.getContext(), {entry_point_name_md, attrs_md});
md_node->addOperand(entry);
// clean up annotations so other passes don't try to use the value
to_erase.insert(annotation_gv);
// this isn't used so also clean up
auto op2 = annotation_struct->getOperand(2);
GlobalVariable *filename_gv = dyn_cast<GlobalVariable>(op2);
to_erase.insert(filename_gv);
}
GV.eraseFromParent();
for (auto gv : to_erase) {
gv->eraseFromParent();
}
for (auto as : addrspacecast_to_erase) {
as->destroyConstant();
}
break;
}
}
return PreservedAnalyses::none();
}