Skip to content

Commit

Permalink
feature: &&、||
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingtous committed Feb 12, 2021
1 parent 85ac224 commit f39546e
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 66 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ LLVM框架语言:LLVM 11.1.0
目前还不完善,支持简单的:

- 函数定义
- 参数
- 参数
- 二元表达式
- &&、||
- +、-、*、/、%
- 函数调用
- 条件分支关键字
- if
Expand All @@ -22,6 +24,7 @@ LLVM框架语言:LLVM 11.1.0
- break
- continue
- 函数返回 return

- 全局、局部变量
- 数组
- 全局、局部数组/多维数组
Expand Down
129 changes: 104 additions & 25 deletions ast/NodeAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ llvm::Value *BinaryExprAST::codegen() {
// 逻辑值bool
if (type == BinaryType::AND) {
//

return this->codeGenAnd(LEA, REA);
} else if (type == BinaryType::OR) {
//
//
return this->codeGenOr(LEA, REA);
} else {
llvm::Value *L = LEA->codegen();
llvm::Value *R = REA->codegen();
Expand Down Expand Up @@ -113,18 +114,83 @@ Value *BinaryExprAST::codeGenAnd(NodeAST *l, NodeAST *r) {
}
auto func = Builder.GetInsertBlock()->getParent();
if (func == NIL) {
return LogErrorV("&&需要在函数环境下使用");
}
auto bbCond1 = BasicBlock::Create(TheContext, "and_1", func);
auto bbCond2 = BasicBlock::Create(TheContext, "and_2", func);
auto bbEndCond = BasicBlock::Create(TheContext, "and_end", func);
// TODO

return nullptr;
return LogErrorV("&&需要在函数环境下使用,建议在函数中使用");
}
// BasicBlock* condTrue = NIL;
// BasicBlock* condEnd = NIL;
// if (LOCALS->contextType == CodeGenBlockContextType::IF){
// condTrue = LOCALS->context.ifCodeGenBlockContext->bbTrue;
// condEnd = LOCALS->context.ifCodeGenBlockContext->bbElse == NIL ? LOCALS->context.ifCodeGenBlockContext->bbEndIf : LOCALS->context.ifCodeGenBlockContext->bbElse;
// } else if (LOCALS->contextType == CodeGenBlockContextType::FOR){
// condTrue = LOCALS->context.forCodeGenBlockContext->bbBody;
// condEnd = LOCALS->context.forCodeGenBlockContext->bbEndFor;
// } else {
// return LogErrorV("不能将二元操作符应用于");
// }
auto bbCond1 = Builder.GetInsertBlock();
auto bbCond2 = BasicBlock::Create(TheContext, "and_right");
auto bbCondEnd = BasicBlock::Create(TheContext, "and_end");
auto cond1V = l->codegen();
cond1V = Builder.CreateICmpSGT(cond1V, ConstantInt::get(cond1V->getType(), 0));
bbCond1 = Builder.GetInsertBlock();
Builder.CreateCondBr(cond1V, bbCond2, bbCondEnd); // 如果为true的话接着判断cond2,
func->getBasicBlockList().push_back(bbCond2);
Builder.SetInsertPoint(bbCond2);
auto cond2V = r->codegen();
cond2V = Builder.CreateICmpSGT(cond2V, ConstantInt::get(cond2V->getType(), 0));
// 要考虑嵌套
bbCond2 = Builder.GetInsertBlock();
Builder.CreateBr(bbCondEnd);
func->getBasicBlockList().push_back(bbCondEnd);
Builder.SetInsertPoint(bbCondEnd);
auto phi = Builder.CreatePHI(getTypeFromStr("bool"), 2);
phi->addIncoming(cond1V, bbCond1);
phi->addIncoming(cond2V, bbCond2);
return phi;
}

Value *BinaryExprAST::codeGenOr(NodeAST *l, NodeAST *r) {
return nullptr;
if (Builder.GetInsertBlock() == NIL) {
return LogErrorV("当前需要一个Basic Block来开始or环境");
}
auto func = Builder.GetInsertBlock()->getParent();
if (func == NIL) {
return LogErrorV("||需要在函数环境下使用");
}
// BasicBlock* condTrue = NIL;
// BasicBlock* condEnd = NIL;
// if (LOCALS->contextType == CodeGenBlockContextType::IF){
// condTrue = LOCALS->context.ifCodeGenBlockContext->bbTrue;
// condEnd = LOCALS->context.ifCodeGenBlockContext->bbElse == NIL ? LOCALS->context.ifCodeGenBlockContext->bbEndIf : LOCALS->context.ifCodeGenBlockContext->bbElse;
// } else if (LOCALS->contextType == CodeGenBlockContextType::FOR){
// condTrue = LOCALS->context.forCodeGenBlockContext->bbBody;
// condEnd = LOCALS->context.forCodeGenBlockContext->bbEndFor;
// } else {
// return LogErrorV("不能将二元操作符应用于");
// }
auto bbCond1 = Builder.GetInsertBlock();
auto bbCond2 = BasicBlock::Create(TheContext, "or_right");
auto bbCondEnd = BasicBlock::Create(TheContext, "or_end");
// TODO
Builder.SetInsertPoint(bbCond1);
auto cond1V = l->codegen();
cond1V = Builder.CreateICmpNE(cond1V, ConstantInt::get(cond1V->getType(), 0));
bbCond1 = Builder.GetInsertBlock();
Builder.CreateCondBr(cond1V, bbCondEnd, bbCond2);

func->getBasicBlockList().push_back(bbCond2);
Builder.SetInsertPoint(bbCond2);
auto cond2V = r->codegen();
cond2V = Builder.CreateICmpNE(cond2V, ConstantInt::get(cond2V->getType(), 0));
// 要考虑嵌套,更新当前bb
bbCond2 = Builder.GetInsertBlock();
Builder.CreateBr(bbCondEnd);
func->getBasicBlockList().push_back(bbCondEnd);
Builder.SetInsertPoint(bbCondEnd);
auto phi = Builder.CreatePHI(getTypeFromStr("bool"), 2);
phi->addIncoming(cond1V, bbCond1);
phi->addIncoming(cond2V, bbCond2);
return phi;
}

llvm::Value *CallExprAST::codegen() {
Expand Down Expand Up @@ -172,18 +238,25 @@ Value *ConditionAST::codegen() {
return LogErrorV("if parse error");
}
// 创建一条 icnp ne指令,用于if的比较,由于是bool比较,此处直接与0比较。
ifCondV = Builder.CreateICmpNE(ifCondV, ConstantInt::get(getTypeFromStr("bool"),0), "neuq_jintao_ifcond");
ifCondV = Builder.CreateICmpNE(ifCondV, ConstantInt::get(getTypeFromStr("bool"), 0), "neuq_jintao_ifcond");
// 获取if里面的函数体,准备创建基础块
auto theFunction = Builder.GetInsertBlock()->getParent();
if (!theFunction) {
return LogErrorV("if没在函数体内使用");
}
// 创建三个basic block,先添加IfTrue至函数体里面
BasicBlock *bbIfTrue = BasicBlock::Create(TheContext, "neuq_jintao_if_true", theFunction);
BasicBlock *bbElse = BasicBlock::Create(TheContext, "neuq_jintao_else");
BasicBlock *bbElse = else_stmt == NIL ? NIL : BasicBlock::Create(TheContext, "neuq_jintao_else");
BasicBlock *bbIfEnd = BasicBlock::Create(TheContext, "neuq_jintao_if_end");
LOCALS->setContextType(CodeGenBlockContextType::IF);
LOCALS->context.ifCodeGenBlockContext = new IfCodeGenBlockContext(Builder.GetInsertBlock(), bbIfEnd, bbIfTrue,
bbElse);
// 创建条件分支,createCondBr(条件结果,为true的basic block,为false的basic block)
Builder.CreateCondBr(ifCondV, bbIfTrue, bbElse);
if (bbElse == NIL) {
Builder.CreateCondBr(ifCondV, bbIfTrue, bbIfEnd);
} else {
Builder.CreateCondBr(ifCondV, bbIfTrue, bbElse);
}
// 开启往Basic Block中塞入代码
Builder.SetInsertPoint(bbIfTrue);
Value *ifTrueV = if_stmt->codegen();
Expand All @@ -197,19 +270,21 @@ Value *ConditionAST::codegen() {
// 将插入if内容时,可能会有循环嵌套,需要更新嵌套最底层的insertBlock
bbIfTrue = Builder.GetInsertBlock();
// 塞入else
theFunction->getBasicBlockList().push_back(bbElse);
Builder.SetInsertPoint(bbElse);
Value *elseV = nullptr;
if (else_stmt) {
elseV = else_stmt->codegen();
if (!elseV) {
return LogErrorV("else里面内容有误");
if (bbElse != NIL) {
theFunction->getBasicBlockList().push_back(bbElse);
Builder.SetInsertPoint(bbElse);
Value *elseV = nullptr;
if (else_stmt) {
elseV = else_stmt->codegen();
if (!elseV) {
return LogErrorV("else里面内容有误");
}
}
if (Builder.GetInsertBlock()->empty() || !(*Builder.GetInsertBlock()->rbegin()).isTerminator()) {
Builder.CreateBr(bbIfEnd);
}
bbElse = Builder.GetInsertBlock();
}
if (Builder.GetInsertBlock()->empty() || !(*Builder.GetInsertBlock()->rbegin()).isTerminator()) {
Builder.CreateBr(bbIfEnd);
}
bbElse = Builder.GetInsertBlock();
// 创建末尾结点
theFunction->getBasicBlockList().push_back(bbIfEnd);
Builder.SetInsertPoint(bbIfEnd);
Expand Down Expand Up @@ -447,6 +522,10 @@ llvm::Value *VariableDeclarationAST::codegen() {
// auto mem = Builder.CreateAlloca(getTypeFromStr(type),)
if (expr != nullptr) {
auto v = expr->codegen();
if (v->getType()->isIntegerTy() && v->getType() != getTypeFromStr(type)) {
// 不同,尝试进行修剪
v = Builder.CreateZExtOrTrunc(v, getTypeFromStr(type));
}
Builder.CreateStore(v, ret);
}
INSERTLOCAL(identifier->identifier, ret);
Expand Down
9 changes: 4 additions & 5 deletions codegen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ void CodeGenBlock::setContextType(CodeGenBlockContextType contextType) {
CodeGenBlock::contextType = contextType;
}

IfCodeGenBlockContext::IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEnd, BasicBlock *bbStep,
BasicBlock *bbBody, BasicBlock *bbEndFor) : bbCond(bbCond), bbEnd(bbEnd),
bbStep(bbStep), bbBody(bbBody),
bbEndFor(bbEndFor) {}

ForCodeGenBlockContext::ForCodeGenBlockContext(BasicBlock *bbStart, BasicBlock *bbCond, BasicBlock *bbStep,
BasicBlock *bbBody, BasicBlock *bbEndFor) : bbStart(bbStart),
bbCond(bbCond),
Expand All @@ -99,3 +94,7 @@ ForCodeGenBlockContext::ForCodeGenBlockContext(BasicBlock *bbStart, BasicBlock *

WhileCodeGenBlockContext::WhileCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbBody, BasicBlock *bbEndWhile)
: bbCond(bbCond), bbBody(bbBody), bbEndWhile(bbEndWhile) {}

IfCodeGenBlockContext::IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEndIf, BasicBlock *bbTrue,
BasicBlock *bbElse) : bbCond(bbCond), bbEndIf(bbEndIf), bbTrue(bbTrue),
bbElse(bbElse) {}
10 changes: 4 additions & 6 deletions codegen/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ typedef struct ForCodeGenBlockContext {

typedef struct IfCodeGenBlockContext {
BasicBlock *bbCond;
BasicBlock *bbEnd;
BasicBlock *bbStep;
BasicBlock *bbBody;
BasicBlock *bbEndFor;
BasicBlock *bbEndIf;
BasicBlock *bbTrue;
BasicBlock *bbElse;

IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEnd, BasicBlock *bbStep, BasicBlock *bbBody,
BasicBlock *bbEndFor);
IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEndIf, BasicBlock *bbTrue, BasicBlock *bbElse);
} IfCodeGenBlockContext;

typedef struct WhileCodeGenBlockContext {
Expand Down
26 changes: 9 additions & 17 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@
int param = 100;
int nums[10][10][10][10];
// 求[1,param)整数和
int getNum(int param){
int cnt = 0;
for(int index=0; index<param; index=index+1){
if (index % 2 == 0){
if (index % 3 == 0){
cnt = cnt + index;
while (cnt > 0) {
cnt = cnt - 1;
while (cnt < 0) {
return 0;
}
break;
}
}
}
continue;



int getNum() {
int a = 0;
int b = 1;
for (int i = 0; i < a && b; i = i + 1) {
a = a + 1;
}
return cnt;
return a;
}
12 changes: 0 additions & 12 deletions test/test.cpp

This file was deleted.

19 changes: 19 additions & 0 deletions test/test1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Created by bytedance on 2021/2/1.
//
#include <stdio.h>

extern "C" {
int getNum();
}

int getNum2() {
int a = 0;
int b = 1;
int c = a || b && a;
return c;
}

int main() {
printf("num is %d", getNum());
}

0 comments on commit f39546e

Please sign in to comment.