Skip to content

Commit 3084f8d

Browse files
committed
Adds support for if and while statements
1 parent 97b49cf commit 3084f8d

13 files changed

+2695
-2315
lines changed

compiler/smmlexer.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static const char* tokenTypeToString[] = {
2222
"int", "uint", "float", "bool",
2323
"char", "string",
2424
"->", "return",
25+
"if", "then", "else", "while", "do",
2526
"eof"
2627
};
2728

@@ -129,7 +130,9 @@ static void initSymTableWithKeywords(PPrivLexer lex) {
129130
static struct Symbol keywords[] = {
130131
{ "div", tkSmmIntDiv },{ "mod", tkSmmIntMod },{ "not", tkSmmNot },
131132
{ "and", tkSmmAndOp },{ "or", tkSmmOrOp },{ "xor", tkSmmXorOp },
132-
{ "return", tkSmmReturn },{ "false", tkSmmBool },{ "true", tkSmmBool },
133+
{ "return", tkSmmReturn },{ "while", tkSmmWhile },{ "do", tkSmmDo },
134+
{ "if", tkSmmIf },{ "then", tkSmmThen },{ "else", tkSmmElse },
135+
{ "false", tkSmmBool },{ "true", tkSmmBool },
133136
};
134137

135138
int count = sizeof(keywords) / sizeof(struct Symbol);

compiler/smmlexer.h

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef enum {
3131
tkSmmInt, tkSmmUInt, tkSmmFloat, tkSmmBool,
3232
tkSmmChar, tkSmmString,
3333
tkSmmRArrow, tkSmmReturn,
34+
tkSmmIf, tkSmmThen, tkSmmElse, tkSmmWhile, tkSmmDo,
3435
tkSmmEof
3536
} SmmTokenKind;
3637

compiler/smmllvmcodegen.c

+89-23
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct LogicalExprData {
2727
typedef struct LogicalExprData* PLogicalExprData;
2828

2929
static LLVMValueRef processExpression(PSmmLLVMCodeGenData data, PSmmAstNode expr, PIbsAllocator a);
30+
static void processBlock(PSmmLLVMCodeGenData data, PSmmAstBlockNode block, PIbsAllocator a);
31+
static void processStatement(PSmmLLVMCodeGenData data, PSmmAstNode stmt, PIbsAllocator a);
3032

3133
static LLVMTypeRef getLLVMType(PSmmTypeInfo type) {
3234
if (!type) return LLVMVoidType();
@@ -296,32 +298,96 @@ static void processReturn(PSmmLLVMCodeGenData data, PSmmAstNode stmt, PIbsAlloca
296298
} else LLVMBuildRetVoid(data->builder);
297299
}
298300

301+
static void processIf(PSmmLLVMCodeGenData data, PSmmAstIfWhileNode stmt, PIbsAllocator a) {
302+
LLVMBasicBlockRef trueBlock = LLVMAppendBasicBlock(data->curFunc, "if.then");
303+
LLVMBasicBlockRef falseBlock;
304+
LLVMBasicBlockRef endBlock;
305+
if (stmt->elseBody) {
306+
falseBlock = LLVMAppendBasicBlock(data->curFunc, "if.else");
307+
endBlock = LLVMAppendBasicBlock(data->curFunc, "if.end");
308+
} else {
309+
falseBlock = LLVMAppendBasicBlock(data->curFunc, "if.end");
310+
endBlock = falseBlock;
311+
}
312+
LLVMValueRef res;
313+
data->endBlock = trueBlock;
314+
if (stmt->cond->kind == nkSmmAndOp || stmt->cond->kind == nkSmmOrOp) {
315+
struct LogicalExprData logicalExprData = { data, data->endBlock };
316+
res = processAndOrInstr(&logicalExprData, stmt->cond, trueBlock, falseBlock, a);
317+
} else {
318+
res = processExpression(data, stmt->cond, a);
319+
}
320+
data->endBlock = NULL;
321+
LLVMBuildCondBr(data->builder, res, trueBlock, falseBlock);
322+
323+
LLVMPositionBuilderAtEnd(data->builder, trueBlock);
324+
325+
processStatement(data, stmt->body, a);
326+
LLVMBuildBr(data->builder, falseBlock);
327+
LLVMPositionBuilderAtEnd(data->builder, falseBlock);
328+
if (stmt->elseBody) {
329+
processStatement(data, stmt->elseBody, a);
330+
LLVMBuildBr(data->builder, endBlock);
331+
LLVMPositionBuilderAtEnd(data->builder, endBlock);
332+
}
333+
}
334+
335+
static void processWhile(PSmmLLVMCodeGenData data, PSmmAstIfWhileNode stmt, PIbsAllocator a) {
336+
LLVMBasicBlockRef condBlock = LLVMAppendBasicBlock(data->curFunc, "while.cond");
337+
LLVMBasicBlockRef trueBlock = LLVMAppendBasicBlock(data->curFunc, "while.body");
338+
LLVMBasicBlockRef falseBlock = LLVMAppendBasicBlock(data->curFunc, "while.end");
339+
LLVMBuildBr(data->builder, condBlock);
340+
LLVMPositionBuilderAtEnd(data->builder, condBlock);
341+
LLVMValueRef res;
342+
data->endBlock = trueBlock; // We initialize data.endBlock with new block
343+
if (stmt->cond->kind == nkSmmAndOp || stmt->cond->kind == nkSmmOrOp) {
344+
struct LogicalExprData logicalExprData = { data, data->endBlock };
345+
res = processAndOrInstr(&logicalExprData, stmt->cond, trueBlock, falseBlock, a);
346+
} else {
347+
res = processExpression(data, stmt->cond, a);
348+
}
349+
data->endBlock = NULL;
350+
LLVMBuildCondBr(data->builder, res, trueBlock, falseBlock);
351+
352+
LLVMPositionBuilderAtEnd(data->builder, trueBlock);
353+
354+
processStatement(data, stmt->body, a);
355+
LLVMBuildBr(data->builder, condBlock);
356+
LLVMPositionBuilderAtEnd(data->builder, falseBlock);
357+
}
358+
359+
static void processStatement(PSmmLLVMCodeGenData data, PSmmAstNode stmt, PIbsAllocator a) {
360+
switch (stmt->kind) {
361+
case nkSmmBlock:
362+
{
363+
PSmmAstBlockNode newBlock = (PSmmAstBlockNode)stmt;
364+
processLocalSymbols(data, newBlock->scope->decls, a);
365+
processBlock(data, newBlock, a);
366+
break;
367+
}
368+
case nkSmmAssignment: processAssignment(data, stmt, a); break;
369+
case nkSmmIf: processIf(data, &stmt->asIfWhile, a); break;
370+
case nkSmmWhile: processWhile(data, &stmt->asIfWhile, a); break;
371+
case nkSmmDecl:
372+
if (stmt->left->left->asIdent.level == 0) {
373+
LLVMTypeRef type = getLLVMType(stmt->left->type);
374+
LLVMValueRef globalVar = LLVMAddGlobal(data->llvmModule, type, stmt->left->left->token->repr);
375+
LLVMSetGlobalConstant(globalVar, false);
376+
LLVMSetInitializer(globalVar, processExpression(data, stmt->left->right, a));
377+
} else {
378+
processAssignment(data, stmt->left, a);
379+
}
380+
break;
381+
case nkSmmReturn: processReturn(data, stmt, a); break;
382+
default:
383+
processExpression(data, stmt, a); break;
384+
}
385+
}
386+
299387
static void processBlock(PSmmLLVMCodeGenData data, PSmmAstBlockNode block, PIbsAllocator a) {
300388
PSmmAstNode stmt = block->stmts;
301389
while (stmt) {
302-
switch (stmt->kind) {
303-
case nkSmmBlock:
304-
{
305-
PSmmAstBlockNode newBlock = (PSmmAstBlockNode)stmt;
306-
processLocalSymbols(data, newBlock->scope->decls, a);
307-
processBlock(data, newBlock, a);
308-
break;
309-
}
310-
case nkSmmAssignment: processAssignment(data, stmt, a); break;
311-
case nkSmmDecl:
312-
if (stmt->left->left->asIdent.level == 0) {
313-
LLVMTypeRef type = getLLVMType(stmt->left->type);
314-
LLVMValueRef globalVar = LLVMAddGlobal(data->llvmModule, type, stmt->left->left->token->repr);
315-
LLVMSetGlobalConstant(globalVar, false);
316-
LLVMSetInitializer(globalVar, processExpression(data, stmt->left->right, a));
317-
} else {
318-
processAssignment(data, stmt->left, a);
319-
}
320-
break;
321-
case nkSmmReturn: processReturn(data, stmt, a); break;
322-
default:
323-
processExpression(data, stmt, a); break;
324-
}
390+
processStatement(data, stmt, a);
325391
stmt = stmt->next;
326392
}
327393
}

compiler/smmparser.c

+25
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const char* nodeKindToString[] = {
2222
"cast", "param", "call", "return",
2323
"and", "xor" , "or",
2424
"==", "!=", ">", ">=", "<", "<=", "not",
25+
"if", "while",
2526
};
2627

2728
struct SmmTypeInfo builtInTypes[] = {
@@ -787,6 +788,29 @@ static PSmmAstNode parseExpressionStmt(PSmmParser parser) {
787788
return lval;
788789
}
789790

791+
static PSmmAstNode parseIfWhileStmt(PSmmParser parser) {
792+
PSmmToken iftoken = parser->curToken;
793+
SmmAstNodeKind kind = nkSmmIf;
794+
int condTerm = tkSmmThen;
795+
if (iftoken->kind == tkSmmWhile) {
796+
kind = nkSmmWhile;
797+
condTerm = tkSmmDo;
798+
}
799+
getNextToken(parser);
800+
PSmmAstNode cond = parseExpression(parser);
801+
expect(parser, condTerm);
802+
PSmmAstNode body = parseStatement(parser);
803+
PSmmAstIfWhileNode ifstmt = smmNewAstNode(nkSmmIf, parser->a);
804+
ifstmt->body = body;
805+
ifstmt->cond = cond;
806+
ifstmt->token = iftoken;
807+
if (parser->curToken->kind == tkSmmElse) {
808+
getNextToken(parser);
809+
ifstmt->elseBody = parseStatement(parser);
810+
}
811+
return (PSmmAstNode)ifstmt;
812+
}
813+
790814
static PSmmAstNode parseStatement(PSmmParser parser) {
791815
switch (parser->curToken->kind) {
792816
case tkSmmReturn:
@@ -796,6 +820,7 @@ static PSmmAstNode parseStatement(PSmmParser parser) {
796820
case tkSmmIdent: case '(': case '-': case '+': case tkSmmNot:
797821
case tkSmmInt: case tkSmmFloat: case tkSmmBool:
798822
return parseExpressionStmt(parser);
823+
case tkSmmIf: case tkSmmWhile: return parseIfWhileStmt(parser);
799824
case tkSmmErr:
800825
if (findToken(parser, ';')) getNextToken(parser);
801826
return NULL;

compiler/smmparser.h

+13
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef struct SmmAstBlockNode* PSmmAstBlockNode;
3434
typedef struct SmmAstParamNode* PSmmAstParamNode;
3535
typedef struct SmmAstFuncDefNode* PSmmAstFuncDefNode;
3636
typedef struct SmmAstCallNode* PSmmAstCallNode;
37+
typedef struct SmmAstIfWhileNode* PSmmAstIfWhileNode;
3738

3839
struct SmmParser {
3940
PSmmLexer lex;
@@ -62,6 +63,7 @@ typedef enum {
6263
nkSmmCast, nkSmmParam, nkSmmCall, nkSmmReturn,
6364
nkSmmAndOp, nkSmmXorOp, nkSmmOrOp,
6465
nkSmmEq, nkSmmNotEq, nkSmmGt, nkSmmGtEq, nkSmmLt, nkSmmLtEq, nkSmmNot,
66+
nkSmmIf, nkSmmWhile,
6567

6668
nkSmmTerminator,
6769

@@ -181,6 +183,16 @@ struct SmmAstCallNode {
181183
PSmmAstNode args;
182184
};
183185

186+
struct SmmAstIfWhileNode {
187+
SmmAstNodeKind kind;
188+
uint32_t isIdent : 1;
189+
PSmmToken token;
190+
PSmmAstNode cond;
191+
PSmmAstNode next;
192+
PSmmAstNode body;
193+
PSmmAstNode elseBody;
194+
};
195+
184196
union SmmAstNode {
185197
struct {
186198
SmmAstNodeKind kind;
@@ -200,6 +212,7 @@ union SmmAstNode {
200212
struct SmmAstParamNode asParam;
201213
struct SmmAstFuncDefNode asFunc;
202214
struct SmmAstCallNode asCall;
215+
struct SmmAstIfWhileNode asIfWhile;
203216
};
204217

205218
PSmmAstNode smmGetZeroValNode(struct SmmFilePos filePos, PSmmTypeInfo varType, PIbsAllocator a);

compiler/smmsempass.c

+44-29
Original file line numberDiff line numberDiff line change
@@ -226,37 +226,52 @@ static void processLocalSymbols(PSmmAstDeclNode decl, PSmmMsgs msgs, PIbsAllocat
226226
}
227227
}
228228

229-
static void processBlock(PSmmAstBlockNode block, PSmmMsgs msgs, PIbsAllocator a) {
230-
PSmmAstNode* stmtField = &block->stmts;
231-
PSmmAstNode stmt = block->stmts;
232-
while (stmt) {
233-
switch (stmt->kind) {
234-
case nkSmmBlock:
235-
{
236-
PSmmAstBlockNode newBlock = (PSmmAstBlockNode)stmt;
237-
processLocalSymbols(newBlock->scope->decls, msgs, a);
238-
processBlock(newBlock, msgs, a);
239-
break;
240-
}
241-
case nkSmmAssignment:
242-
assert(stmt->type == stmt->left->type);
243-
processExpression(&stmt->right, stmt->type, false, msgs, a);
244-
break;
245-
case nkSmmDecl:
246-
assert(stmt->left->kind == nkSmmAssignment);
247-
assert(stmt->left->type == stmt->left->left->type);
248-
processExpression(&stmt->left->right, stmt->left->type, false, msgs, a);
249-
break;
250-
case nkSmmReturn:
251-
if (stmt->left) processExpression(&stmt->left, stmt->type, false, msgs, a);
229+
static void processBlock(PSmmAstBlockNode block, PSmmMsgs msgs, PIbsAllocator a);
230+
static void processStatement(PSmmAstNode* stmtField, PSmmMsgs msgs, PIbsAllocator a);
231+
232+
static void processIfWhile(PSmmAstIfWhileNode stmt, PSmmMsgs msgs, PIbsAllocator a) {
233+
processExpression(&stmt->cond, &builtInTypes[tiSmmBool], false, msgs, a);
234+
processStatement(&stmt->body, msgs, a);
235+
if (stmt->elseBody) {
236+
processStatement(&stmt->elseBody, msgs, a);
237+
}
238+
}
239+
240+
static void processStatement(PSmmAstNode* stmtField, PSmmMsgs msgs, PIbsAllocator a) {
241+
PSmmAstNode stmt = *stmtField;
242+
switch (stmt->kind) {
243+
case nkSmmBlock:
244+
{
245+
PSmmAstBlockNode newBlock = (PSmmAstBlockNode)stmt;
246+
processLocalSymbols(newBlock->scope->decls, msgs, a);
247+
processBlock(newBlock, msgs, a);
252248
break;
253-
default:
254-
// We treat softFloat as float32
255-
if (stmt->type->kind == tiSmmSoftFloat64) stmt->type -= 2;
256-
processExpression(stmtField, stmt->type, stmt->kind == nkSmmCast, msgs, a); break;
257249
}
258-
stmtField = &stmt->next;
259-
stmt = stmt->next;
250+
case nkSmmAssignment:
251+
assert(stmt->type == stmt->left->type);
252+
processExpression(&stmt->right, stmt->type, false, msgs, a);
253+
break;
254+
case nkSmmIf: case nkSmmWhile: processIfWhile((PSmmAstIfWhileNode)stmt, msgs, a); break;
255+
case nkSmmDecl:
256+
assert(stmt->left->kind == nkSmmAssignment);
257+
assert(stmt->left->type == stmt->left->left->type);
258+
processExpression(&stmt->left->right, stmt->left->type, false, msgs, a);
259+
break;
260+
case nkSmmReturn:
261+
if (stmt->left) processExpression(&stmt->left, stmt->type, false, msgs, a);
262+
break;
263+
default:
264+
// We treat softFloat as float32
265+
if (stmt->type->kind == tiSmmSoftFloat64) stmt->type -= 2;
266+
processExpression(stmtField, stmt->type, stmt->kind == nkSmmCast, msgs, a); break;
267+
}
268+
}
269+
270+
static void processBlock(PSmmAstBlockNode block, PSmmMsgs msgs, PIbsAllocator a) {
271+
PSmmAstNode* stmtField = &block->stmts;
272+
while (*stmtField) {
273+
processStatement(stmtField, msgs, a);
274+
stmtField = &(*stmtField)->next;
260275
}
261276
}
262277

0 commit comments

Comments
 (0)