没有合适的资源?快使用搜索试试~ 我知道了~
首页LLVM 程序员手册 —— LLVM 4.0 文档 - 可译网
LLVM 程序员手册 —— LLVM 4.0 文档 - 可译网
需积分: 45 90 下载量 23 浏览量
更新于2023-05-21
评论 1
收藏 1.09MB PDF 举报
LLVM 程序员手册 —— LLVM 4.0 文档LLVMLLVMLLVMLLVM
资源详情
资源评论
资源推荐
2017/5/17 Ӥ܌9)50LLVM ᑕଧާಋٙ —— LLVM 4.0 - ݢᦲᗑ
ᒫ 1 ᶭҁو 41 ᶭ҂https://coyee.com/article/compare/10594-llvm-programmer-s-manual-llvm-4-0-documentation
Ḓᶭ ଠ࣋ ஙᦲ ޑ~ ӝۜ
ᔱᒍ
"
+
ጭ୯ጭ୯ ےفݢᦲᗑےفݢᦲᗑ
LLVM ᑕଧާಋٙᑕଧާಋٙ —— LLVM 4.0 [૪ᘉᦲ૪ᘉᦲ]
LLVM Programmer’s Manual — LLVM 4.0 documentation
ܻ ᦲ ֢
Introduction
This document is meant to highlight some of the important classes
and interfaces available in the LLVM source-base. This manual is not
intended to explain what LLVM is, how it works, and what LLVM code
looks like. It assumes that you know the basics of LLVM and are
interested in writing transformations or otherwise analyzing or
manipulating the code.
This document should get you oriented so that you can find your way
in the continuously growing source code that makes up the LLVM
infrastructure. Note that this manual is not intended to serve as a
replacement for reading the source code, so if you think there should
be a method in one of these classes to do something, but it’s not
listed, check the source. Links to the doxygensources are provided to
make this as easy as possible.
ڹڹ
ࣁՕᕨLLVMӾӞԶ᯿ᥝጱᔄളݗӧᓒՕᕨՋԍฎ
LLVM҅LLVMฎই֜ૡ֢ጱ҅ᬮํLLVMጱդᎱړຉᦡ֦૪ᕪ
LLVMํጱԧᥴ҅ଚഘ҅ᘏړຉᖌಷٌӾጱդᎱఽي᪁
տᕳ֦ොݻ҅ᦏ֦ݢզࣁӧෙᳩጱLLVMຝӾጱդᎱӾ҅
ತک֦ጱොݻ᧗ဳ҅ᴅଚӧᚆ๊դLLVMრդᎱጱᴅ҅ಅ
զইຎ֦మັತԶᔄᚆ؉ԶՋԍ҅ଚӧᚆࢧᒼ֦ᬯӻᳯ҅ಅ
զ֦ᬮฎັತრᎱզӥᬯӻ᱾ളฎLLVMጱdoxygen҅ݢզො
ጱᦏ֦ັತమᥝጱӳᥜ
ᔿྋᘉᦲᔿྋᘉᦲ
The first section of this document describes general information that
is useful to know when working in the LLVM infrastructure, and the
second describes the Core LLVM classes. In the future this manual
will be extended with information describing how to use extension
libraries, such as dominator information, CFG traversal routines, and
useful utilities like the InstVisitor(doxygen) template.
General Information
This section contains general information that is useful if you are
working in the LLVM source-base, but that isn’t specific to any
particular API.
ᒫӞ᮱ړՕᕨֵአLLVMᬦᑕӾ҅ӞԶଉአጱᎣᦩᅩ҅ᒫԫ᮱ړտ
Օᕨ҅LLVMጱ໐ஞᔄࣁ෭ݸጱಋٙӾ҅տᖀᖅᦖᥴইֵ֜
አಘପֺ҅ইdominator҅CFG ഴګၞ҅ᬮํӞԶํአጱૡֺٍ҅
ই InstVisitor(doxygen)ཛྷᇇ
מ௳מ௳
ᒍᜓ۱ތֵአLLVMᬦᑕӾ҅ଉአጱמ௳҅֕ฎଚ๚ࣁAPIӾڜ
ڊ
ᔿྋᘉᦲᔿྋᘉᦲ
The C++ Standard Template Library
LLVM makes heavy use of the C++ Standard Template Library (STL),
perhaps much more than you are used to, or have seen before.
Because of this, you might want to do a little background reading in
the techniques used and capabilities of the library. There are many
good pages that discuss the STL, and several books on the subject
that you can get, so it will not be discussed in this document.
Here are some useful links:
1. cppreference.com - an excellent reference for the STL and
other parts of the standard C++ library.
2. C++ In a Nutshell - This is an O’Reilly book in the making. It
has a decent Standard Library Reference that rivals
Dinkumware’s, and is unfortunately no longer free since the
book has been published.
3. C++ Frequently Asked Questions.
4. SGI’s STL Programmer’s Guide - Contains a useful Introduction
to the STL.
5. Bjarne Stroustrup’s C++ Page.
6. Bruce Eckel’s Thinking in C++, 2nd ed. Volume 2 Revision 4.0
(even better, get the book).
C++ ຽٵཛྷᇇପຽٵཛྷᇇପ
LLVMጱդᎱӾᶋଉׁᩢC++ጱຽٵཛྷᇇପ(STL), ֵአጱහᰁݢᚆྲ֦አ
ጱᬮಅզ֦҅ᴅڹ֦҅ᵱᥝSTLํጱԧᥴ҅ᬯᚆԧ
ᥴکጱದૣପጱۑᚆᗑӤ૪ᕪํᶋଉӿጱᩒාᬮํԡᔁ
ᦖᥴSTL֦҅ݢզ݇ᘍইӥጱᩒා҅ӧٚᩣᬿ
1. cppreference.com - ᶋଉ༉ጱSTLಋٙ҅ᬮํӞԶٌ՜C++ጱପ
ጱಋٙ
2. C++ In a Nutshell - ᬯฎӞO’ReillyڊᇇጱԡᔁԡӾၿ݊ጱฎ
๋ෛጱପ֕ฎᬯԡ૪ᕪݎᤈ҅ಅզӧٚعᩇӥ
3. C++ Frequently Asked Questions.
4. SGI’s STL Programmer’s Guide - STLํᧇᕡጱՕᕨ.
5. Bjarne Stroustrup’s C++ Page.
6. Bruce Eckel’s Thinking in C++, 2nd ed. Volume 2 Revision 4.0
(even better, get the book).
ᔿྋᘉᦲᔿྋᘉᦲ
You are also encouraged to take a look at the LLVM Coding
Standards guide which focuses on how to write maintainable code
more than where to put your curly braces.
Other useful references
1. Using static and shared libraries across platforms
Important and useful LLVM APIs
ᬮἩۜັLLVMᖫᎱຽٵܖ҅ᧆܖጱ᯿ᅩฎই֜ᖫٟݢᖌಷጱդ
Ꮁ҅ᘒӧฎጱೡݩනࣁߺ᯾
ٌ՜ํአጱ݇ᘍٌ՜ํአጱ݇ᘍ
1. ଘݣֵአᶉாوՁପ
᯿ᥝํአጱ᯿ᥝํአጱLLVM API
ᔿྋᘉᦲᔿྋᘉᦲ
!
2017/5/17 Ӥ܌9)50LLVM ᑕଧާಋٙ —— LLVM 4.0 - ݢᦲᗑ
ᒫ 2 ᶭҁو 41 ᶭ҂https://coyee.com/article/compare/10594-llvm-programmer-s-manual-llvm-4-0-documentation
Here we highlight some LLVM APIs that are generally useful and
good to know about when writing transformations.
The isa<>, cast<> and dyn_cast<> templates
The LLVM source-base makes extensive use of a custom form of
RTTI. These templates have many similarities to the
C++ dynamic_cast<> operator, but they don’t have some
drawbacks (primarily stemming from the fact
that dynamic_cast<> only works on classes that have a v-table).
Because they are used so often, you must know what they do and
how they work. All of these templates are defined in
the llvm/Support/Casting.h (doxygen) file (note that you very
rarely have to include this file directly).
ࣁᬯ᯾҅౯ժ୩᧣ӞԶLLVM API҅ժ᭗ଉฎํአጱ҅ଚӬ୮֦ᖫٟ
ഘ๋অԧᥴӞӥ
The isa<>, cast<> and dyn_cast<> templates
LLVMრդᎱପଠာֵአԧӞᐿᛔԎ୵ୗጱRTTI ᬯԶཛྷӨC ++
dynamic_cast <>֢ᒧํᦜፘ֒ԏ҅֕ժဌํӞԶᗌᅩҁԆᥝრ
ᛔdynamic_cast <>Րᭇአԭٍํv-tableጱᔄ҂ ࢩԅժᕪଉᤩֵ
አ֦҅ᶳᎣ᭲՜ժ؉Ջԍզ݊ժই֜ૡ֢ ಅํᬯԶཛྷ᮷
ࣁllvm/Support/Casting.h (doxygen)կӾԎҁ᧗ဳ҅உ
ᵱᥝፗള۱ތྌկ҂
isa<>:
The isa<> operator works exactly like the Java “instanceof”
operator. It returns true or false depending on whether a reference or
pointer points to an instance of the specified class. This can be very
useful for constraint checking of various sorts (example below).
cast<>:
The cast<> operator is a “checked cast” operation. It converts a
pointer or reference from a base class to a derived class, causing an
assertion failure if it is not really an instance of the right type. This
should be used in cases where you have some information that
makes you believe that something is of the right type. An example of
the isa<> and cast<> template is:
isa<>:
isa<> ֢ᒧ؟Javaጱ"instanceof"֢ᒧ.ೲᆙӞӻአᰒฎވ
ݻӞӻᇙᔄጱֺᬬࢧฎވ.ᬯӻ֢ᒧࣁݱᐿᕅ༄ັӾஉํአ
(ӥᶎํֺৼ).
cast<>:
cast<> ֢ᒧฎӞӻ"༄ັᬦጱഘ"֢.Ӟӻᰒአᔄ
ഘکၝኞᔄ, ইຎᔄࣳᲙݎෙᲙ.ᬯଫᧆࣁ୮֦ፘמֺጱᔄࣳ
ֵአ. Ӟӻisa<> cast<> ཛྷጱֺৼฎ:
ᔿྋᘉᦲᔿྋᘉᦲ
Note that you should not use an isa<> test followed by a cast<>,
for that use the dyn_cast<> operator.
dyn_cast<>:
The dyn_cast<> operator is a “checking cast” operation. It checks
to see if the operand is of the specified type, and if so, returns a
pointer to it (this operator does not work with references). If the
operand is not of the correct type, a null pointer is returned. Thus,
this works very much like the dynamic_cast<> operator in C++, and
should be used in the same circumstances. Typically,
the dyn_cast<> operator is used in an if statement or some other
flow control statement like this:
᧗ဳ҅ӧଫᧆࣁݸᶎ᪙፳Ӟӻcast <>ֵአisa <>ၥᦶ҅ԭᮎᐿ
ఘ٭ֵአdyn_cast <>ᬩᓒᒧ
dyn_cast<>:
dyn_cast <>֢ᒧฎӞӻ“༄ັഘҁchecking cast҂”֢ ༄ັ
֢හฎވฎጱᔄࣳ҅ইຎฎᬯ҅ᬬࢧӞӻݻጱᰒҁᧆ
֢ᒧӧᭇአԭአ҂ ইຎ֢හӧฎྋᏟጱᔄࣳ҅ڞᬬࢧᑮᰒ ࢩ
ྌ҅ᬯ؉ᶋଉ؟C++Ӿጱdynamic_cast <>ᬩᓒᒧ҅ଚӬଫᧆࣁፘݶጱ
ఘ٭ӥֵአ ᭗ଉ҅dyn_cast <>ᬩᓒᒧአԭifݙٌ՜ӞԶၞᑕഴګ
ݙ҅ইӥಅᐏғ
ᔿྋᘉᦲᔿྋᘉᦲ
This form of the if statement effectively combines together a call
to isa<> and a call to cast<> into one statement, which is very
convenient.
Note that the dyn_cast<> operator, like C++’s dynamic_cast<> or
Java’s instanceof operator, can be abused. In particular, you
should not use big chained if/then/else blocks to check for lots
of different variants of classes. If you find yourself wanting to do this,
it is much cleaner and more efficient to use the InstVisitor class
to dispatch over the instruction type directly.
ᬯᐿ୵ୗጱifݙํපࣈᕟݳԧ᧣አisa <>᧣አcast <>کӞӻݙӾ҅
ᬯฎᶋଉොጱ
᧗ဳ҅dyn_cast <>ᬩᓒᒧ҅ইC++ጱdynamic_cast <>Javaጱ
instanceofᬩᓒᒧ҅ݢᚆտᤩᄂአ ᇙڦฎ҅ӧଫᧆֵአӞᔮ
ڜif/then/else ࣘ༄ັᦜӧݶᔄጱݒ֛ ইຎݎሿᛔ૩మᥝᬯ
؉ֵ҅አInstVisitorᔄፗളݎڊեᔄࣳๅԅႴ၄Ԟๅํප
ᔿྋᘉᦲᔿྋᘉᦲ
cast_or_null<>:
The cast_or_null<> operator works just like the cast<> operator,
except that it allows for a null pointer as an argument (which it then
propagates). This can sometimes be useful, allowing you to combine
several null checks into one.
dyn_cast_or_null<>:
cast_or_null<>:
cast_or_null <>֢ᒧӨcast <>֢ᒧᔄ֒҅ݝฎ꧋ᦜӞӻᑮᰒ֢
ԅ݇හҁᆐݸփඎ҂ ᬯํݢᚆฎํአጱ҅꧋ᦜپӻᑮ༄ັݳଚ
ԅӞӻ
dyn_cast_or_null<>:
ᔿྋᘉᦲᔿྋᘉᦲ
static bool isLoopInvariant(const Value *V, const Loop *L) {
if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
return true;
// Otherwise, it must be an instruction...
return !L->contains(cast<Instruction>(V)->getParent());
}
static bool isLoopInvariant(const Value *V, const Loop *L) {
if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
return true;
// Otherwise, it must be an instruction...
return !L->contains(cast<Instruction>(V)->getParent());
}
if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) {
// ...
}
if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) {
// ...
}
2017/5/17 Ӥ܌9)50LLVM ᑕଧާಋٙ —— LLVM 4.0 - ݢᦲᗑ
ᒫ 3 ᶭҁو 41 ᶭ҂https://coyee.com/article/compare/10594-llvm-programmer-s-manual-llvm-4-0-documentation
The dyn_cast_or_null<> operator works just like
the dyn_cast<> operator, except that it allows for a null pointer as
an argument (which it then propagates). This can sometimes be
useful, allowing you to combine several null checks into one.
These five templates can be used with any classes, whether they
have a v-table or not. If you want to add support for these templates,
see the document How to set up LLVM-style RTTI for your class
hierarchy
dyn_cast_or_null <>֢ᒧӨdyn_cast <>ᬩᓒᒧᔄ֒҅ݝӧᬦ꧋ᦜӞ
ӻᑮᰒ֢ԅ݇හҁᆐݸփඎ҂ ᬯํݢᚆฎํአጱ҅꧋ᦜپӻ
ᑮ༄ັݳଚԅӞӻ
ᬯԲӻཛྷݢզӨձ֜ᔄӞֵ᩸አ҅෫ᦞժฎވٍํᡦᤒҁv-
table҂ ইຎᥝႲےᬯԶཛྷጱඪ೮҅᧗݇ᴅই֜ԅᔄེᕮ
ᦡᗝLLVM໒ጱRTTI
Passing strings (the StringRef and Twine classes)
Although LLVM generally does not do much string manipulation, we
do have several important APIs which take strings. Two important
examples are the Value class – which has names for instructions,
functions, etc. – and the StringMap class which is used extensively
in LLVM and Clang.
These are generic classes, and they need to be able to accept
strings which may have embedded null characters. Therefore, they
cannot simply take a const char *, and taking
a conststd::string& requires clients to perform a heap allocation
which is usually unnecessary. Instead, many LLVM APIs use
a StringRef or a const Twine& for passing strings efficiently.
փ᭓ᒧԀҁփ᭓ᒧԀҁStringRefTwineᔄ҂ᔄ҂
ᡱᆐLLVM᭗ଉဌํ؉ጱᒧԀ֢҅֕౯ժᏟํپӻቘᒧԀ
ጱ᯿ᥝAPI ӷӻ᯿ᥝጱֺৼฎValueᔄ - ํե҅ڍහᒵጱݷᑍզ݊
ࣁLLVMClangӾଠာֵአጱStringMapᔄ
ᬯԶฎ᭗አᔄ҅ժᵱᥝᚆളݑݢᚆ۱ތᑮᒧጱᒧԀ ࢩྌ҅
ժӧᚆᓌܔࣈֵአconst char *҅ଚӬֵአconststd :: stringѿᥝಁ
ᒒಗᤈ᭗ଉӧᥝጱړᯈ ፘݍ҅ᦜLLVM APIֵአStringRef
const Twineѿํපࣈփ᭓ᒧԀ
ᔿྋᘉᦲᔿྋᘉᦲ
The StringRef class
The StringRef data type represents a reference to a constant string
(a character array and a length) and supports the common operations
available on std::string, but does not require heap allocation.
It can be implicitly constructed using a C style null-terminated string,
an std::string, or explicitly with a character pointer and length.
For example, the StringRef find function is declared as:
iterator find(StringRef Key);
and clients can call it using any one of:
Map.find("foo"); // Lookup "foo"
Map.find(std::string("bar")); // Lookup "bar"
Map.find(StringRef("\0baz", 4)); // Lookup "\0baz"
StringRefᔄᔄ
StringRefහഝᔄࣳᤒᐏଉᰁᒧԀҁᒧහᕟᳩଶ҂ጱአ҅ଚඪ
೮std :: stringӤݢአጱଉአ֢҅֕ӧᵱᥝړᯈ
ݢզᵌୗࣈֵአC໒ጱզnullᕮጱᒧԀ҅std :: string҅ดୗࣈ
ֵአᒧᰒᳩଶ᭜ ֺই҅StringRef findڍහกԅғ
iterator find(StringRef Key);
ಁᒒݢզֵአզӥձ֜Ӟᐿ᧣አғ
Map.find("foo"); // Lookup "foo"
Map.find(std::string("bar")); // Lookup "bar"
Map.find(StringRef("\0baz", 4)); // Lookup "\0baz"
ᔿྋᘉᦲᔿྋᘉᦲ
Similarly, APIs which need to return a string may return
a StringRef instance, which can be used directly or converted to
an std::string using the str member function.
Seellvm/ADT/StringRef.h (doxygen) for more information.
You should rarely use the StringRef class directly, because it
contains pointers to external memory it is not generally safe to store
an instance of the class (unless you know that the external storage
will not be freed). StringRef is small and pervasive enough in LLVM
that it should always be passed by value.
The Twine class
The Twine (doxygen) class is an efficient way for APIs to accept
concatenated strings. For example, a common LLVM paradigm is to
name one instruction based on the name of another instruction with
a suffix, for example:
ᔄ֒ࣈ҅ᵱᥝᬬࢧᒧԀጱAPIݢᚆտᬬࢧӞӻStringRefֺ҅ݢզፗ
ളֵአᘏֵአstr౮ާڍහഘԅstd :: string ݇
ᴅllvm/ADT/StringRef.h (doxygen)឴ݐๅמ௳
உፗളֵአStringRefᔄ҅ࢩԅ۱ތݻ᮱ٖጱᰒؙ҅ᧆ
ᔄጱֺ᭗ଉฎӧقጱҁᴻᶋᎣ᭲᮱ؙӧտᤩ᯽න҂
StringRefࣁLLVMӾฎᘒฦ᭭ጱ҅ଫᧆতᕣฎೲ꧊փ᭓
Twineᔄᔄ
Twine (doxygen) ᔄAPI᧔ฎӞᐿളݑᬳളᒧԀጱํපොୗ ֺ
ই҅ӞӻଉᥠጱLLVMֺฎ໑ഝٍํݸᖗጱݚӞӻեጱݷᑍݷӞӻ
եֺ҅ইғ
ᔿྋᘉᦲᔿྋᘉᦲ
New = CmpInst::Create(..., SO->getName() + ".cmp");
The Twine class is effectively a lightweight rope which points to
temporary (stack allocated) objects. Twines can be implicitly
constructed as the result of the plus operator applied to strings (i.e.,
a C strings, an std::string, or a StringRef). The twine delays the
actual concatenation of strings until it is actually required, at which
point it can be efficiently rendered directly into a character array.
This avoids unnecessary heap allocation involved in constructing the
temporary results of string concatenation.
See llvm/ADT/Twine.h (doxygen) and here for more information.
New = CmpInst::Create(..., SO->getName() + ".cmp");
TwineᔄᴬӤฎݻԁҁړᯈ҂ጱᰁᕆropeҁᦲဳғrope
ԅӞᐿහഝᕮ҂ ֢ԅଫአԭᒧԀጱےݩᬩᓒᒧҁܨCᒧԀ҅std
:: stringStringRef҂ጱᕮຎ҅ݢզᵌୗ᭜Twines twineݢզ᬴
ᒧԀጱᴬᬳളፗکժᴬᵱᥝ҅ྌݢզፗളํපࣈວک
ᒧහᕟӾ ᬯعԧୌᒧԀᬳളጱԁᕮຎၿ݊ጱӧᥝጱړ
ᯈ ᧗݇ᴅllvm/ADT/Twine.h (doxygen)҅ᬯ᯾ํๅጱמ௳
ᔿྋᘉᦲᔿྋᘉᦲ
As with a StringRef, Twine objects point to external memory and
should almost never be stored or mentioned directly. They are
ӨStringRefӞ҅Twineݻ᮱ٖ҅پԒӧտፗളؙ
݊ ժՐአԭԎଫᧆᚆํපളතᬳളᒧԀጱڍහ
ᔿྋᘉᦲᔿྋᘉᦲ
2017/5/17 Ӥ܌9)50LLVM ᑕଧާಋٙ —— LLVM 4.0 - ݢᦲᗑ
ᒫ 4 ᶭҁو 41 ᶭ҂https://coyee.com/article/compare/10594-llvm-programmer-s-manual-llvm-4-0-documentation
intended solely for use when defining a function which should be
able to efficiently accept concatenated strings.
Error handling
Proper error handling helps us identify bugs in our code, and helps
end-users understand errors in their tool usage. Errors fall into two
broad categories: programmatic and recoverable, with different
strategies for handling and reporting.
Programmatic Errors
Programmatic errors are violations of program invariants or API
contracts, and represent bugs within the program itself. Our aim is to
document invariants, and to abort quickly at the point of failure
(providing some basic diagnostic) when invariants are broken at
runtime.
ᲙቘᲙቘ
ྋᏟጱᲙቘํۗԭ౯ժᦩڦդᎱӾጱᲙ҅ଚଆ๋ۗᕣአಁԧᥴٌ
ૡֵٍአӾጱᲙ Კړԅӷᔄғ
ᖫᑕ
ݢ௩
҅ժٍํӧ
ݶጱቘಸޞᒽኼ
ᖫᑕᲙᖫᑕᲙ
ᖫᑕᲙฎᬲݍᑕଧጱӧݒᰁAPIᕅ҅ଚᤒሿࣁᑕଧࣁᲙ
౯ժጱፓጱฎᦕ୯ӧݒᰁ҅ଚӬ୮ᬩᤈӧݒᰁݎኞදݒ҅ࣁඳ
ᵑᅩҁ׀ӞԶෙ҂ள᭛Ӿෙ
The fundamental tools for handling programmatic errors are
assertions and the llvm_unreachable function. Assertions are used to
express invariant conditions, and should include a message
describing the invariant:
The llvm_unreachable function can be used to document areas of
control flow that should never be entered if the program invariants
hold:
enum { Foo, Bar, Baz } X = foo();
switch (X) {
case Foo: /* Handle Foo */; break;
case Bar: /* Handle Bar */; break;
default:
llvm_unreachable("X should be Foo or Bar here");
}
ቘᖫᑕᲙጱૡٍฎෙllvm_unreachableڍහ ෙአԭᤒ
ᐏӧݒկ҅ଚଫ۱ೡൈᬿӧݒᰁጱၾ௳ғ
llvm_unreachableڍහݢአԭᦕ୯ᮎԶӧଫᧆᤩᬰفҁইຎᑕଧӧݒᰁ
ތํ҂ጱഴګၞᑕ܄ғ
enum { Foo, Bar, Baz } X = foo();
switch (X) {
case Foo: /* Handle Foo */; break;
case Bar: /* Handle Bar */; break;
default:
llvm_unreachable("X should be Foo or Bar here");
}
ᔿྋᘉᦲᔿྋᘉᦲ
Recoverable Errors
Recoverable errors represent an error in the program’s environment,
for example a resource failure (a missing file, a dropped network
connection, etc.), or malformed input. These errors should be
detected and communicated to a level of the program where they
can be handled appropriately. Handling the error may be as simple as
reporting the issue to the user, or it may involve attempts at recovery.
Recoverable errors are modeled using LLVM’s Error scheme. This
scheme represents errors using function return values, similar to
classic C integer error codes, or C++’s std::error_code. However,
the Error class is actually a lightweight wrapper for user-defined
error types, allowing arbitrary information to be attached to describe
the error. This is similar to the way C++ exceptions allow throwing of
user-defined types.
ݢ௩ጱᲙݢ௩ጱᲙ
ݢ௩ጱᲙᤒᐏᑕଧሾӾጱᲙֺ҅ইᩒრඳᵑҁᗌկ҅Ӷ
ጱᗑᕶᬳളᒵ҂໒ୗᲙጱᬌف ଫᧆ༄ၥᬯԶᲙଚٌփ᭓کᖫ
ᑕᕆڦ҅զ՜ժکᭇ୮ጱቘቘᲙݢզ؟ݻአಁಸޞᳯӞ
ᓌܔ҅Ԟݢᚆၿ݊ᦶ௩
ݢ௩ጱᲙֵአLLVMጱᲙҁError҂ොໜᬰᤈୌཛྷ ᧆොໜᤒᐏֵ
አڍහᬬࢧ꧊ጱᲙ҅ᔄ֒ԭᕪَጱCෆහᲙդᎱ҅C++ጱstd ::
error_code ֕ฎ҅Error ᔄᴬӤฎአಁԎጱᲙᔄࣳጱᰁᕆ۱
ᤰ҅꧋ᦜᴫےձמ௳ൈᬿᲙ ᬯӨC++ଉ꧋ᦜಲڊአಁᛔԎ
ᔄࣳጱොୗᔄ֒
ᔿྋᘉᦲᔿྋᘉᦲ
Success values are created by calling Error::success():
Error foo() {
// Do something.
// Return success.
return Error::success();
}
Success values are very cheap to construct and return - they have
minimal impact on program performance.
Failure values are constructed using make_error<T>, where T is any
class that inherits from the ErrorInfo utility:
᭗ᬦ᧣አError :: successҁ҂ڠୌsuccess꧊ғ
Error foo() {
// Do something.
// Return success.
return Error::success();
}
Success꧊ԭୌᬬࢧጱᲀஉ - ժᑕଧᚆߥ๋
Failure꧊ֵአmake_error <T>ୌٌ҅ӾTฎErrorInfoአᑕଧᖀಥ
ጱձ֜ᔄғ
ᔿྋᘉᦲᔿྋᘉᦲ
assert(isPhysReg(R) && "All virt regs should have been allocated already."
assert(isPhysReg(R) && "All virt regs should have been allocated already."
class MyError : public ErrorInfo<MyError> {
public:
MyError(std::string Msg) : Msg(Msg) {}
void log(OStream &OS) const override { OS << "MyError - "
static char ID;
private:
std::string Msg;
};
char MyError::ID = 0; // In MyError.cpp
Error bar() {
class MyError : public ErrorInfo<MyError> {
public:
MyError(std::string Msg) : Msg(Msg) {}
void log(OStream &OS) const override { OS << "MyError - "
static char ID;
private:
std::string Msg;
};
char MyError::ID = 0; // In MyError.cpp
Error bar() {
if (checkErrorCondition)
return make_error<MyError>("Error condition detected"
2017/5/17 Ӥ܌9)50LLVM ᑕଧާಋٙ —— LLVM 4.0 - ݢᦲᗑ
ᒫ 5 ᶭҁو 41 ᶭ҂https://coyee.com/article/compare/10594-llvm-programmer-s-manual-llvm-4-0-documentation
Error values can be implicitly converted to bool: true for error, false
for success, enabling the following idiom:
Error mayFail();
Error foo() {
if (auto Err = mayFail())
return Err;
// Success! We can proceed.
...
For functions that can fail but need to return a value
the Expected<T> utility can be used. Values of this type can be
constructed with either a T, or a Error. Expected<T> values are also
implicitly convertible to boolean, but with the opposite convention to
Error: true for success, false for error. If success, the T value can be
accessed via the dereference operator. If failure, the Error value can
be extracted using the takeError() method. Idiomatic usage looks
like:
Error꧊ݢզᵌୗഘԅboolғtrueԅerror҅falseԅsuccess҅ԟబֵአ
զӥොୗғ
Error mayFail();
Error foo() {
if (auto Err = mayFail())
return Err;
// Success! We can proceed.
...
ԭݢᚆᨳ֕ᵱᥝᬬࢧ꧊ጱۑᚆ҅ݢզֵአExpected <T>አᑕଧ
ᬯᐿᔄࣳጱ꧊ݢզአTᘏError᭜ ᶼ๗ጱ<T>꧊Ԟݢզᵌୗഘ
ԅ꧊҅֕ӨErrorጱᕅፘݍғtrueአԭsuccess҅falseԅerrorই
ຎ౮ۑ҅ݢզ᭗ᬦᥴአᬩᓒᒧᦢᳯT꧊ ইຎᨳ҅ڞݢզֵአ
takeError()ොဩݐᲙ꧊ ԟబአဩইӥғ
ᔿྋᘉᦲᔿྋᘉᦲ
Expected<float> parseAndSquareRoot(IStream &IS) {
float f;
OS >> f;
if (f < 0)
return make_error<FloatingPointError>(...);
return sqrt(f);
}
Error foo(IStream &IS) {
if (auto SqrtOrErr = parseAndSquartRoot(IS)) {
float Sqrt = *SqrtOrErr;
// ...
} else
return SqrtOrErr.takeError();
}
All Error instances, whether success or failure, must be either
checked or moved from (via std::move or a return) before they are
destructed. Accidentally discarding an unchecked error will cause a
program abort at the point where the unchecked value’s destructor is
run, making it easy to identify and fix violations of this rule.
Expected<float> parseAndSquareRoot(IStream &IS) {
float f;
OS >> f;
if (f < 0)
return make_error<FloatingPointError>(...);
return sqrt(f);
}
Error foo(IStream &IS) {
if (auto SqrtOrErr = parseAndSquartRoot(IS)) {
float Sqrt = *SqrtOrErr;
// ...
} else
return SqrtOrErr.takeError();
}
ಅํError ֺҁ෫ᦞ౮ۑᨳ҂҅᮷ᶳࣁᤩᲀྪԏڹҁ᭗ᬦstd ::
movereturn҂༄ັᑏۖ Ӷ๚ᕪ༄ັጱᲙᛘᑕଧࣁ๚
༄ັ꧊ጱຉڍහᬩᤈጱࣈොӾྊ҅ᘒฃԭᦩڦץᬲݍྌᥢڞጱ
ᤈԅ
ᔿྋᘉᦲᔿྋᘉᦲ
Success values are considered checked once they have been tested
(by invoking the boolean conversion operator):
In contrast, the following code will always cause an abort, regardless
of the return value of foo:
Failure values are considered checked once a handler for the error
type has been activated:
Success ꧊Ӟ෮ᤩၥᦶݸᦊԅฎᕪᬦ༄ັጱҁ᭗ᬦ᧣አഘᬩᓒ
ᒧ҂ғ
ፘݍ҅զӥդᎱฎᛘӾྊ҅෫ᦞfooጱᬬࢧ꧊ই֜ғ
Ӟ෮Კᔄࣳጱቘᑕଧᤩᄶၚ҅տᘍᡤ༄ັFailure ꧊ғ
ᔿྋᘉᦲᔿྋᘉᦲ
if (checkErrorCondition)
return make_error<MyError>("Error condition detected"
// No error - proceed with bar.
// Return success value.
return Error::success();
}
// No error - proceed with bar.
// Return success value.
return Error::success();
}
if (auto Err = canFail(...))
return Err; // Failure value - move error to caller.
// Safe to continue: Err was checked.
canFail();
// Program will always abort here, even if canFail() returns Success, since
// the value is not checked.
auto Err = canFail(...);
if (auto Err2 =
handleErrors(std::move(Err),
[](std::unique_ptr<MyError> M) {
// Try to handle 'M'. If successful, return a success value from
// the handler.
if (tryToHandle(M))
return Error::success();
// We failed to handle 'M' - return it from the handler.
// This value will be passed back from catchErrors and
// wind up in Err2, where it will be returned from this function.
return Error(std::move(M));
})))
return Err2;
if (auto Err = canFail(...))
return Err; // Failure value - move error to caller.
// Safe to continue: Err was checked.
canFail();
// Program will always abort here, even if canFail() returns Success, since
// the value is not checked.
auto Err = canFail(...);
if (auto Err2 =
handleErrors(std::move(Err),
[](std::unique_ptr<MyError> M) {
// Try to handle 'M'. If successful, return a success value from
// the handler.
if (tryToHandle(M))
return Error::success();
// We failed to handle 'M' - return it from the handler.
// This value will be passed back from catchErrors and
// wind up in Err2, where it will be returned from this function.
return Error(std::move(M));
})))
return Err2;
剩余40页未读,继续阅读
wobuhuihuang
- 粉丝: 0
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- zigbee-cluster-library-specification
- JSBSim Reference Manual
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0