forked from llvm-mirror/llvm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce bitset metadata format and bitset lowering pass.
This patch introduces a new mechanism that allows IR modules to co-operatively build pointer sets corresponding to addresses within a given set of globals. One particular use case for this is to allow a C++ program to efficiently verify (at each call site) that a vtable pointer is in the set of valid vtable pointers for the class or its derived classes. One way of doing this is for a toolchain component to build, for each class, a bit set that maps to the memory region allocated for the vtables, such that each 1 bit in the bit set maps to a valid vtable for that class, and lay out the vtables next to each other, to minimize the total size of the bit sets. The patch introduces a metadata format for representing pointer sets, an '@llvm.bitset.test' intrinsic and an LTO lowering pass that lays out the globals and builds the bitsets, and documents the new feature. Differential Revision: http://reviews.llvm.org/D7288 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230054 91177308-0d34-0410-b5e6-96231b3b80d8
- Loading branch information
Showing
21 changed files
with
1,014 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
======= | ||
Bitsets | ||
======= | ||
|
||
This is a mechanism that allows IR modules to co-operatively build pointer | ||
sets corresponding to addresses within a given set of globals. One example | ||
of a use case for this is to allow a C++ program to efficiently verify (at | ||
each call site) that a vtable pointer is in the set of valid vtable pointers | ||
for the type of the class or its derived classes. | ||
|
||
To use the mechanism, a client creates a global metadata node named | ||
``llvm.bitsets``. Each element is a metadata node with three elements: | ||
the first is a metadata string containing an identifier for the bitset, | ||
the second is a global variable and the third is a byte offset into the | ||
global variable. | ||
|
||
This will cause a link-time optimization pass to generate bitsets from the | ||
memory addresses referenced from the elements of the bitset metadata. The pass | ||
will lay out the referenced globals consecutively, so their definitions must | ||
be available at LTO time. An intrinsic, :ref:`llvm.bitset.test <bitset.test>`, | ||
generates code to test whether a given pointer is a member of a bitset. | ||
|
||
:Example: | ||
|
||
:: | ||
|
||
target datalayout = "e-p:32:32" | ||
|
||
@a = internal global i32 0 | ||
@b = internal global i32 0 | ||
@c = internal global i32 0 | ||
@d = internal global [2 x i32] [i32 0, i32 0] | ||
|
||
!llvm.bitsets = !{!0, !1, !2, !3, !4} | ||
|
||
!0 = !{!"bitset1", i32* @a, i32 0} | ||
!1 = !{!"bitset1", i32* @b, i32 0} | ||
!2 = !{!"bitset2", i32* @b, i32 0} | ||
!3 = !{!"bitset2", i32* @c, i32 0} | ||
!4 = !{!"bitset2", i32* @d, i32 4} | ||
|
||
declare i1 @llvm.bitset.test(i8* %ptr, metadata %bitset) nounwind readnone | ||
|
||
define i1 @foo(i32* %p) { | ||
%pi8 = bitcast i32* %p to i8* | ||
%x = call i1 @llvm.bitset.test(i8* %pi8, metadata !"bitset1") | ||
ret i1 %x | ||
} | ||
|
||
define i1 @bar(i32* %p) { | ||
%pi8 = bitcast i32* %p to i8* | ||
%x = call i1 @llvm.bitset.test(i8* %pi8, metadata !"bitset2") | ||
ret i1 %x | ||
} | ||
|
||
define void @main() { | ||
%a1 = call i1 @foo(i32* @a) ; returns 1 | ||
%b1 = call i1 @foo(i32* @b) ; returns 1 | ||
%c1 = call i1 @foo(i32* @c) ; returns 0 | ||
%a2 = call i1 @bar(i32* @a) ; returns 0 | ||
%b2 = call i1 @bar(i32* @b) ; returns 1 | ||
%c2 = call i1 @bar(i32* @c) ; returns 1 | ||
%d02 = call i1 @bar(i32* getelementptr ([2 x i32]* @d, i32 0, i32 0)) ; returns 0 | ||
%d12 = call i1 @bar(i32* getelementptr ([2 x i32]* @d, i32 0, i32 1)) ; returns 1 | ||
ret void | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
//===- LowerBitSets.h - Bitset lowering pass --------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file defines parts of the bitset lowering pass implementation that may | ||
// be usefully unit tested. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_TRANSFORMS_IPO_LOWERBITSETS_H | ||
#define LLVM_TRANSFORMS_IPO_LOWERBITSETS_H | ||
|
||
#include "llvm/ADT/DenseMap.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
|
||
#include <stdint.h> | ||
#include <limits> | ||
#include <vector> | ||
|
||
namespace llvm { | ||
|
||
class DataLayout; | ||
class GlobalVariable; | ||
class Value; | ||
|
||
struct BitSetInfo { | ||
// The actual bitset. | ||
std::vector<uint8_t> Bits; | ||
|
||
// The byte offset into the combined global represented by the bitset. | ||
uint64_t ByteOffset; | ||
|
||
// The size of the bitset in bits. | ||
uint64_t BitSize; | ||
|
||
// Log2 alignment of the bit set relative to the combined global. | ||
// For example, a log2 alignment of 3 means that bits in the bitset | ||
// represent addresses 8 bytes apart. | ||
unsigned AlignLog2; | ||
|
||
bool isSingleOffset() const { | ||
return Bits.size() == 1 && Bits[0] == 1; | ||
} | ||
|
||
bool containsGlobalOffset(uint64_t Offset) const; | ||
|
||
bool containsValue(const DataLayout *DL, | ||
const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout, | ||
Value *V, uint64_t COffset = 0) const; | ||
|
||
}; | ||
|
||
struct BitSetBuilder { | ||
SmallVector<uint64_t, 16> Offsets; | ||
uint64_t Min, Max; | ||
|
||
BitSetBuilder() : Min(std::numeric_limits<uint64_t>::max()), Max(0) {} | ||
|
||
void addOffset(uint64_t Offset) { | ||
if (Min > Offset) | ||
Min = Offset; | ||
if (Max < Offset) | ||
Max = Offset; | ||
|
||
Offsets.push_back(Offset); | ||
} | ||
|
||
BitSetInfo build(); | ||
}; | ||
|
||
} // namespace llvm | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.