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
|
#include "cps/CodeGen.h"
#include "llvm/IR/GlobalVariable.h"
using namespace cps;
using namespace llvm;
namespace {
bool isGlobalLiteral(ExprAST *Expr) {
if (dynamic_cast<IntegerExprAST*>(Expr) || dynamic_cast<RealExprAST*>(Expr) ||
dynamic_cast<CharExprAST*>(Expr) || dynamic_cast<StringExprAST*>(Expr) ||
dynamic_cast<BooleanExprAST*>(Expr)) return true;
auto *Unary = dynamic_cast<UnaryExprAST*>(Expr);
return Unary && Unary->getOp() == '-' &&
(dynamic_cast<IntegerExprAST*>(Unary->getOperand()) ||
dynamic_cast<RealExprAST*>(Unary->getOperand()));
}
}
void CodeGen::runGlobalPrePass(const SourceUnit &Unit, int Phase) {
for (const auto &Stmt : Unit.Statements) {
auto *Block = dynamic_cast<GlobalBlockAST*>(Stmt.get());
if (!Block) continue;
for (const auto &S : Block->getBody()) {
SaveAndRestore<int> Location(DiagnosticLine, S->getLine());
if (auto *Decl = dynamic_cast<DeclareStmtAST*>(S.get())) {
if (Phase != 0) continue;
const auto &Name = Decl->getName();
const auto &TypeName = Decl->getType();
if (Decl->hasParens() ||
!(sameIdentifier(TypeName, "INTEGER") || sameIdentifier(TypeName, "REAL") ||
sameIdentifier(TypeName, "CHAR") || sameIdentifier(TypeName, "STRING") ||
sameIdentifier(TypeName, "BOOLEAN"))) {
reportError("GLOBAL declarations require a primitive scalar type without constructor arguments");
continue;
}
if (Exports[CurrentUnit].count(Name) || Types->resolve(Name) ||
Types->lookupEnumConstant(Name) || FuncGen->hasFunction(Name) ||
isBuiltinName(Name)) {
reportError("Global %s conflicts with an existing definition", Name.c_str());
continue;
}
const TypeInfo *Type = resolveType(TypeName);
if (!Type) {
reportError("Unknown type %s", TypeName.c_str());
continue;
}
auto *Storage = new GlobalVariable(*TheModule, Types->getLLVMType(TypeName), false,
GlobalValue::InternalLinkage, Types->getZeroValue(TypeName), "__cps_global." + Name);
SymbolInfo Info{Storage, TypeName, false, nullptr, 0, false, true};
Exports[CurrentUnit].emplace(Name, Info);
if (Type->isString()) {
size_t Lifetime = registerStackObject(Storage, Type->Name, DiagnosticLine);
if (emitDefaultConstruct(Type->Name, Storage, DiagnosticLine)) activateStackObject(Lifetime);
}
} else if (auto *Assign = dynamic_cast<AssignStmtAST*>(S.get())) {
if (Phase != 1) continue;
const SymbolInfo *Info = getSymbolInfo(Assign->getName());
if (!Info || !Info->IsGlobal) {
reportError("GLOBAL initializer requires a declared global variable %s",
Assign->getName().c_str());
continue;
}
if (!isGlobalLiteral(Assign->getExpr())) {
reportError("GLOBAL initializer must be a literal");
continue;
}
if (const auto *Type = resolveType(Info->TypeName); Type && Type->isString()) {
emitAssignment({Info->Storage, Info->TypeName}, Assign->getExpr(), Info);
cleanupTemporaries();
continue;
}
auto *Value = dyn_cast_or_null<Constant>(
emitCoercedExpr(Assign->getExpr(), resolveType(Info->TypeName)));
if (!Value) {
reportError("GLOBAL initializer must be a constant scalar literal");
continue;
}
cast<GlobalVariable>(Info->Storage)->setInitializer(Value);
} else if (Phase == 0) {
reportError("GLOBAL blocks allow only primitive DECLARE statements and literal initializers");
}
}
}
}
|