LLVM积累
官网介绍:llvm
github源码:llvm-project
RTTI
阅读:How to set up LLVM-style RTTI for your class hierarchy
llvm有这些RTTI接口可以使用isa<>
、dyn_cast<>
、cast<>
等等。
使用这些接口,父类和子列有这些要求:
- 父类:定义Kind枚举,且构造函数用Kind做入参
- 子列:构造函数指定kind,且定义classof接口
使用时如果入参可能是空指针,则需要调用dyn_cast_or_null<>
转换。
范例如下:
#include "llvm/Support/Casting.h"
class Shape {
public:
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum ShapeKind {
SK_Square,
SK_Circle
};
private:
const ShapeKind Kind;
public:
ShapeKind getKind() const { return Kind; }
Shape(ShapeKind K) : Kind(K) {}
virtual double computeArea() = 0;
};
class Square : public Shape {
double SideLength;
public:
Square(double S) : Shape(SK_Square), SideLength(S) {}
double computeArea() override;
static bool classof(const Shape *S) {
return S->getKind() == SK_Square;
}
};
class Circle : public Shape {
double Radius;
public:
Circle(double R) : Shape(SK_Circle), Radius(R) {}
double computeArea() override;
static bool classof(const Shape *S) {
return S->getKind() == SK_Circle;
}
};
使用参考如下:
Shape *S = ...;
if (isa<Circle>(S)) {
/* do something ... */
}
数据结构
ArrayRef
头文件include/llvm/ADT/ArrayRef.h
,对常量数组的引用,但不包含数组本身。
定义如下:
template<typename T>
class ArrayRef {
private:
/// The start of the array, in an external buffer.
const T *Data = nullptr;
/// The number of elements.
size_type Length = 0;
public:
/// Construct an ArrayRef from a pointer and length.
ArrayRef(const T *data, size_t length)
: Data(data), Length(length) {}
/// Construct an ArrayRef from a range.
ArrayRef(const T *begin, const T *end)
: Data(begin), Length(end - begin) {}
iterator begin() const { return Data; }
iterator end() const { return Data + Length; }
/// empty - Check if the array is empty.
bool empty() const { return Length == 0; }
const T *data() const { return Data; }
/// size - Get the array size.
size_t size() const { return Length; }
const T &operator[](size_t Index) const {
assert(Index < Length && "Invalid index!");
return Data[Index];
}
std::vector<T> vec() const {
return std::vector<T>(Data, Data+Length);
}
operator std::vector<T>() const {
return std::vector<T>(Data, Data+Length);
}
......
};
可以看出它其实和std::vector
功能类似,只是它不包含数据。
在很多数据传递的场景中,可以避免数据的反复拷贝。
StringRef
头文件include/llvm/ADT/StringRef.h
,定义如下:
class StringRef {
private:
/// The start of the string, in an external buffer.
const char *Data = nullptr;
/// The length of the string.
size_t Length = 0;
public:
/// Construct a string ref from a cstring.
constexpr StringRef(const char *Str)
: Data(Str), Length(Str ? strLen(Str) : 0) {}
/// Construct a string ref from a pointer and length.
constexpr StringRef(const char *data, size_t length)
: Data(data), Length(length) {}
/// Construct a string ref from an std::string.
StringRef(const std::string &Str)
: Data(Str.data()), Length(Str.length()) {}
std::string str() const;
explicit operator std::string() const { return str(); }
char operator[](size_t Index) const;
bool startswith(StringRef Prefix) const;
bool endswith(StringRef Suffix) const;
std::string lower() const;
std::string upper() const;
StringRef trim(StringRef Chars = " \t\n\v\f\r") const;
......
与std::string功能类似,但不包含数据。
SmallVector
头文件llvm-project/llvm/include/llvm/ADT/SmallVector.h
,定义如下:
template <typename T, unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> {
public:
SmallVector() : SmallVectorImpl<T>(N) {}
~SmallVector() {
// Destroy the constructed elements in the vector.
this->destroy_range(this->begin(), this->end());
}
explicit SmallVector(size_t Size, const T &Value = T())
: SmallVectorImpl<T>(N) {
this->assign(Size, Value);
}
......
与std:vector功能类似,但是固定元素个数。在确定元素个数很少的情况下很有用。
DenseMap
与std::unordered_map功能一致,但是这有些区别:
翻译自这篇回答llvm::DenseMap and std::map
- unordered_map每个value都单独申请内存保存,DenseMap的key和value使用一整块内存
- DenseMap默认就申请64对Key/Value空间
- DenseMap的iterators在插入操作后全部会失效
总体来说DenseMap的效率比较高,使用优先级高于unordered_map
遍历
for (auto it : llvm::zip(headBlock->getArguments(), operands))
std::get<0>(it).replaceAllUsesWith(std::get<1>(it));
for (const auto &it : llvm::enumerate(returnOp.getOperands()))
valuesToRepl[it.index()].replaceAllUsesWith(it.value());
贡献代码
参考链接Phabricator
-
使用以下方式之一创建patch:
git show HEAD -U999999 > mypatch.patch git diff -U999999 @{u} > mypatch.patch git diff HEAD~1 -U999999 > mypatch.patch
-
在https://reviews.llvm.org/differential页面点击
Create Diff
,然后upload patch,Repository选择rG LLVM Github Monorepo
,Visible To选择Public
,然后选择Reviewers -
如果有检视意见需要更新代码,则在旁边按钮点击
Update Diff
更新,然后再点击Add Action
选择Review
。 -
初次提交没有合入代码权限,需要在comment中请帮忙合入,参考https://reviews.llvm.org/D150757。多次提交后可以发邮件申请代码合入权限。