-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtype.c
More file actions
213 lines (196 loc) · 5.86 KB
/
type.c
File metadata and controls
213 lines (196 loc) · 5.86 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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "rvcc.h"
// (Type){...}构造了一个复合字面量,相当于Type的匿名变量。
Type *TyVoid = &(Type){TY_VOID, 1, 1};
Type *TyBool = &(Type){TY_BOOL, 1, 1};
Type *TyChar = &(Type){TY_CHAR, 1, 1};
Type *TyShort = &(Type){TY_SHORT, 2, 2};
Type *TyInt = &(Type){TY_INT, 4, 4};
Type *TyLong = &(Type){TY_LONG, 8, 8};
static Type *newType(TypeKind Kind, int Size, int Align) {
Type *Ty = calloc(1, sizeof(Type));
Ty->Kind = Kind;
Ty->Size = Size;
Ty->Align = Align;
return Ty;
}
// 判断Type是否为整数
bool isInteger(Type *Ty) {
TypeKind K = Ty->Kind;
return K == TY_BOOL || K == TY_CHAR || K == TY_SHORT || K == TY_INT ||
K == TY_LONG || K == TY_ENUM;
}
// 复制类型
Type *copyType(Type *Ty) {
Type *Ret = calloc(1, sizeof(Type));
*Ret = *Ty;
return Ret;
}
// 指针类型,并且指向基类
Type *pointerTo(Type *Base) {
Type *Ty = newType(TY_PTR, 8, 8);
Ty->Base = Base;
return Ty;
}
// 函数类型,并赋返回类型
Type *funcType(Type *ReturnTy) {
Type *Ty = calloc(1, sizeof(Type));
Ty->Kind = TY_FUNC;
Ty->ReturnTy = ReturnTy;
return Ty;
}
// 构造数组类型, 传入 数组基类, 元素个数
Type *arrayOf(Type *Base, int Len) {
Type *Ty = newType(TY_ARRAY, Base->Size * Len, Base->Align);
Ty->Base = Base;
Ty->ArrayLen = Len;
return Ty;
}
// 构造枚举类型
Type *enumType(void) { return newType(TY_ENUM, 4, 4); }
// 构造结构体类型
Type *structType(void) { return newType(TY_STRUCT, 0, 1); }
// 获取容纳左右部的类型
static Type *getCommonType(Type *Ty1, Type *Ty2) {
if (Ty1->Base) return pointerTo(Ty1->Base);
if (Ty1->Size == 8 || Ty2->Size == 8) return TyLong;
return TyInt;
}
// 进行常规的算术转换(算数中的隐式转换)
static void usualArithConv(Node **LHS, Node **RHS) {
Type *Ty = getCommonType((*LHS)->Ty, (*RHS)->Ty);
// 将左右部转换到兼容的类型
*LHS = newCast(*LHS, Ty);
*RHS = newCast(*RHS, Ty);
}
// 为节点内的所有节点添加类型
//进行运算中隐式的类型转换
//转换为int后的长度适配(long,int选择)
void addType(Node *Nd) {
// 判断 节点是否为空 或者 节点类型已经有值,那么就直接返回
if (!Nd || Nd->Ty) return;
// 递归访问所有节点以增加类型
addType(Nd->LHS);
addType(Nd->RHS);
addType(Nd->Cond);
addType(Nd->Then);
addType(Nd->Els);
addType(Nd->Init);
addType(Nd->Inc);
// 访问链表内的所有节点以增加类型
for (Node *N = Nd->Body; N; N = N->Next) addType(N);
// 访问链表内的所有参数节点以增加类型
for (Node *N = Nd->Args; N; N = N->Next) addType(N);
switch (Nd->Kind) {
// 判断是否Val强制转换为int后依然完整,完整则用int否则用long
case ND_NUM:
Nd->Ty = (Nd->Val == (int)Nd->Val) ? TyInt : TyLong;
return;
// 将节点类型设为 节点左部的类型
case ND_ADD:
case ND_SUB:
case ND_MUL:
case ND_DIV:
case ND_MOD:
case ND_BITAND:
case ND_BITOR:
case ND_BITXOR:
// 对左右部转换
usualArithConv(&Nd->LHS, &Nd->RHS);
Nd->Ty = Nd->LHS->Ty;
return;
case ND_NEG: {
// 对左部转换
Type *Ty = getCommonType(TyInt, Nd->LHS->Ty);
Nd->LHS = newCast(Nd->LHS, Ty);
Nd->Ty = Ty;
return;
}
// 将节点类型设为 节点左部的类型
// 左部不能是数组节点
case ND_ASSIGN:
if (Nd->LHS->Ty->Kind == TY_ARRAY)
errorTok(Nd->LHS->Tok, "not an lvalue");
if (Nd->LHS->Ty->Kind != TY_STRUCT)
// 对右部转换
Nd->RHS = newCast(Nd->RHS, Nd->LHS->Ty);
Nd->Ty = Nd->LHS->Ty;
return;
// 将节点类型设为 int
case ND_EQ:
case ND_NE:
case ND_LT:
case ND_LE:
// 对左右部转换
usualArithConv(&Nd->LHS, &Nd->RHS);
Nd->Ty = TyInt;
return;
case ND_FUNCALL:
Nd->Ty = Nd->FuncType->ReturnTy;
return;
//将节点类型设置为int
case ND_NOT:
case ND_LOGOR:
case ND_LOGAND:
Nd->Ty = TyInt;
return;
// 将节点类型设为 左部的类型
case ND_BITNOT:
case ND_SHL:
case ND_SHR:
Nd->Ty = Nd->LHS->Ty;
return;
// 将节点类型设为 变量的类型
case ND_VAR:
Nd->Ty = Nd->Var->Ty;
return;
// 如果:左或右部为void则为void,否则为二者兼容的类型
case ND_COND:
if (Nd->Then->Ty->Kind == TY_VOID || Nd->Els->Ty->Kind == TY_VOID) {
Nd->Ty = TyVoid;
} else {
usualArithConv(&Nd->Then, &Nd->Els);
Nd->Ty = Nd->Then->Ty;
}
return;
// 将节点类型设为 右部的类型
case ND_COMMA:
Nd->Ty = Nd->RHS->Ty;
return;
// 将节点类型设为 成员的类型
case ND_MEMBER:
Nd->Ty = Nd->Mem->Ty;
return;
// 将节点类型设为 指针,并指向左部的类型
case ND_ADDR: {
Type *Ty = Nd->LHS->Ty;
// 左部如果是数组, 则为指向数组基类的指针
if (Ty->Kind == TY_ARRAY)
Nd->Ty = pointerTo(Ty->Base);
else
Nd->Ty = pointerTo(Ty);
return;
}
// 节点类型:如果解引用指向的是指针,则为指针指向的类型;否则报错
case ND_DEREF:
// 如果不存在基类, 则无法解引用
if (!Nd->LHS->Ty->Base) errorTok(Nd->Tok, "invalid pointer dereference");
if (Nd->LHS->Ty->Base->Kind == TY_VOID)
errorTok(Nd->Tok, "dereferencing a void pointer");
Nd->Ty = Nd->LHS->Ty->Base;
return;
// 节点类型为 最后的表达式语句的类型
case ND_STMT_EXPR:
if (Nd->Body) {
Node *Stmt = Nd->Body;
while (Stmt->Next) Stmt = Stmt->Next;
if (Stmt->Kind == ND_EXPR_STMT) {
Nd->Ty = Stmt->LHS->Ty;
return;
}
}
errorTok(Nd->Tok, "statement expression returning void is not supported");
return;
default:
break;
}
}