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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
//===- CheckTypes.h - Verify PNaCl ABI rules --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Common type-checking code for module and function-level passes
//
//
//===----------------------------------------------------------------------===//
#ifndef LIB_ANALYSIS_NACL_CHECKTYPES_H
#define LIB_ANALYSIS_NACL_CHECKTYPES_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/raw_ostream.h"
class TypeChecker {
public:
bool isValidType(const llvm::Type *Ty) {
if (VisitedTypes.count(Ty))
return VisitedTypes[Ty];
unsigned Width;
bool Valid = false;
switch (Ty->getTypeID()) {
// Allowed primitive types
case llvm::Type::VoidTyID:
case llvm::Type::FloatTyID:
case llvm::Type::DoubleTyID:
case llvm::Type::LabelTyID:
case llvm::Type::MetadataTyID:
Valid = true;
break;
// Disallowed primitive types
case llvm::Type::HalfTyID:
case llvm::Type::X86_FP80TyID:
case llvm::Type::FP128TyID:
case llvm::Type::PPC_FP128TyID:
case llvm::Type::X86_MMXTyID:
Valid = false;
break;
// Derived types
case llvm::Type::VectorTyID:
Valid = false;
break;
case llvm::Type::IntegerTyID:
Width = llvm::cast<const llvm::IntegerType>(Ty)->getBitWidth();
Valid = (Width == 1 || Width == 8 || Width == 16 ||
Width == 32 || Width == 64);
break;
case llvm::Type::FunctionTyID:
case llvm::Type::StructTyID:
case llvm::Type::ArrayTyID:
case llvm::Type::PointerTyID:
// These types are valid if their contained or pointed-to types are
// valid. Since struct/pointer subtype relationships may be circular,
// mark the current type as valid to avoid infinite recursion
Valid = true;
VisitedTypes[Ty] = true;
for (llvm::Type::subtype_iterator I = Ty->subtype_begin(),
E = Ty->subtype_end(); I != E; ++I)
Valid &= isValidType(*I);
break;
// Handle NumTypeIDs, and no default case,
// so we get a warning if new types are added
case llvm::Type::NumTypeIDs:
Valid = false;
break;
}
VisitedTypes[Ty] = Valid;
return Valid;
}
// If the value contains an invalid type, return a pointer to the type.
// Return null if there are no invalid types.
llvm::Type *checkTypesInValue(const llvm::Value *V) {
// TODO: Checking types in values probably belongs in its
// own value checker which also handles the various types of
// constexpr (in particular, blockaddr constexprs cause this code
// to assert rather than go off and try to verify the BBs of a function)
// But this code is in a good consistent checkpoint-able state.
assert(llvm::isa<llvm::Constant>(V));
if (VisitedConstants.count(V))
return VisitedConstants[V];
if (!isValidType(V->getType())) {
VisitedConstants[V] = V->getType();
return V->getType();
}
// Operand values must also be valid. Values may be circular, so
// mark the current value as valid to avoid infinite recursion.
VisitedConstants[V] = NULL;
const llvm::User *U = llvm::cast<llvm::User>(V);
for (llvm::Constant::const_op_iterator I = U->op_begin(),
E = U->op_end(); I != E; ++I) {
llvm::Type *Invalid = checkTypesInValue(*I);
if (Invalid) {
VisitedConstants[V] = Invalid;
return Invalid;
}
}
VisitedConstants[V] = NULL;
return NULL;
}
// There's no built-in way to get the name of a type, so use a
// string ostream to print it.
static std::string getTypeName(const llvm::Type *T) {
std::string TypeName;
llvm::raw_string_ostream N(TypeName);
T->print(N);
return N.str();
}
private:
// To avoid walking constexprs and types multiple times, keep a cache of
// what we have seen. This is also used to prevent infinite recursion e.g.
// in case of structures like linked lists with pointers to themselves.
llvm::DenseMap<const llvm::Value*, llvm::Type*> VisitedConstants;
llvm::DenseMap<const llvm::Type*, bool> VisitedTypes;
};
#endif // LIB_ANALYSIS_NACL_CHECKTYPES_H
|