-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathLowerGlobalDestructors.cpp
More file actions
92 lines (75 loc) · 2.64 KB
/
LowerGlobalDestructors.cpp
File metadata and controls
92 lines (75 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//===-- ThreadLocalLowering.h - Cheerp helper -------------------------===//
//
// Cheerp: The C++ compiler for the Web
//
// This file is distributed under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE.TXT for details.
//
// Copyright 2025 Leaning Technologies
//
//===----------------------------------------------------------------------===//
#include <unordered_set>
#include "llvm/Cheerp/LowerGlobalDestructors.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/LowerGlobalDtors.h"
using namespace llvm;
namespace cheerp
{
void LowerGlobalDestructorsPass::filterGenericJSDestructors(Module& M)
{
GlobalVariable* var = M.getGlobalVariable("llvm.global_dtors");
if (!var || !var->hasInitializer())
return;
ConstantArray* initList = dyn_cast<ConstantArray>(var->getInitializer());
if (!initList)
return;
GlobalValue::LinkageTypes linkageTypes = var->getLinkage();
SmallVector<Constant*, 8> validDestructors;
Type* elementType = nullptr;
// Loop over the global destructors, put all the ones tagged asmjs into a new list.
for (Value* O: initList->operands())
{
ConstantStruct* CS = dyn_cast<ConstantStruct>(O);
if (!CS)
continue;
Constant* destructor = CS->getOperand(1);
if (destructor->isNullValue())
break;
elementType = O->getType();
Function* destructorFunc = dyn_cast<Function>(destructor);
assert(destructorFunc);
if (destructorFunc->getSection() == "asmjs")
validDestructors.push_back(cast<Constant>(O));
}
var->eraseFromParent();
uint32_t numElements = validDestructors.size();
// If there are no valid destructors, don't create a new global.
if (numElements == 0)
return;
ArrayType* arrayType = ArrayType::get(elementType, numElements);
Constant* newInitList = ConstantArray::get(arrayType, validDestructors);
new GlobalVariable(M, arrayType, true, linkageTypes, newInitList, "llvm.global_dtors");
}
PreservedAnalyses LowerGlobalDestructorsPass::run(Module& M, ModuleAnalysisManager& MAM)
{
ModulePassManager MPM;
MPM.addPass(LowerGlobalDtorsPass());
// Collect all currently existing functions in a set.
std::unordered_set<Function*> functionsBeforePass;
for (Function& F: M.getFunctionList())
functionsBeforePass.insert(&F);
// Remove the destructors that aren't tagged asmjs.
filterGenericJSDestructors(M);
// Run the LowerGlobalDtorsPass.
PreservedAnalyses PA = MPM.run(M, MAM);
// The functions that weren't in the list before are the new functions
// created by the LowerGlobalDtorsPass. Tag them asmjs.
for (Function& F: M.getFunctionList())
{
if (!functionsBeforePass.count(&F))
F.setSection("asmjs");
}
return PA;
}
}