-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathCheckedLoadStore.cpp
More file actions
86 lines (79 loc) · 2.63 KB
/
CheckedLoadStore.cpp
File metadata and controls
86 lines (79 loc) · 2.63 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
//===-- CheckLoadStore.cpp - Check addresses before loads/stores ----------===//
//
// 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 2026 Leaning Technologies
//
//===----------------------------------------------------------------------===//
#include "llvm/InitializePasses.h"
#include "llvm/Cheerp/CheckedLoadStore.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
using namespace llvm;
namespace cheerp
{
bool CheckLoadStore::runOnFunction(Module& M, Function& F)
{
// Inject the cheerp_checked_load and cheerp_checked_store intrinsics
// in place of all plain loads and stores. The backend will insert
// conditional calls to imported helpers to access memory mapped
// in the negative space.
std::vector<Instruction*> toDelete;
for ( BasicBlock & BB : F )
{
// Be mindful of the manual increment of the iterator
for ( BasicBlock::iterator it = BB.begin(); it != BB.end(); ++it)
{
Instruction* I = &*it;
if(LoadInst* LI = dyn_cast<LoadInst>(I))
{
if(LI->isAtomic())
continue;
// Constant pointers, including globals, can never be mapped
Value* pointerOperand = LI->getPointerOperand();
if(isa<Constant>(pointerOperand))
continue;
Type* loadType = LI->getType();
Function* checkedLoad = Intrinsic::getDeclaration(&M, Intrinsic::cheerp_checked_load, loadType);
CallInst* CI = CallInst::Create(checkedLoad, { pointerOperand, pointerOperand }, "", LI);
LI->replaceAllUsesWith(CI);
toDelete.push_back(LI);
}
else if(StoreInst* SI = dyn_cast<StoreInst>(I))
{
if(SI->isAtomic())
continue;
// Constant pointers, including globals, can never be mapped
Value* pointerOperand = SI->getPointerOperand();
if(isa<Constant>(pointerOperand))
continue;
Type* storeType = SI->getValueOperand()->getType();
Function* checkedStore = Intrinsic::getDeclaration(&M, Intrinsic::cheerp_checked_store, { storeType, storeType });
CallInst::Create(checkedStore, { pointerOperand, pointerOperand, SI->getValueOperand(), SI->getValueOperand() }, "", SI);
// No need to replace users, stores are void
toDelete.push_back(SI);
}
}
}
for(Instruction* I : toDelete)
{
I->eraseFromParent();
}
return false;
}
llvm::PreservedAnalyses CheckLoadStorePass::run(llvm::Module& M, llvm::ModuleAnalysisManager& MAM)
{
CheckLoadStore inner;
for (Function &F : M)
{
if(F.empty() || F.getSection() != "asmjs")
continue;
inner.runOnFunction(M, F);
}
return PreservedAnalyses::all();
}
}