Compare commits

..

No commits in common. 'lab2' and 'master' have entirely different histories.
lab2 ... master

@ -20,7 +20,100 @@
如果希望进一步参考编译相关项目和往届优秀实现,可以查看编译比赛官网的技术支持栏目:<https://compiler.educg.net/#/index?TYPE=26COM>。其中的“备赛推荐”整理了一些编译相关项目,也能看到往届优秀作品的开源实现,这些内容都很值得参考。
## 3. 头歌平台协作流程
头歌平台的代码托管方式与 GitHub/Gitee 类似。如果你希望基于当前仓库快速开始协作,可以参考下面这套流程。
### 3.1 组长 fork 课程仓库
组长打开课程仓库页面,点击右上角的 `Fork`,创建你们小组自己的仓库副本。后续组内开发统一基于这个 fork 后的仓库进行。
![组长 fork 课程仓库](doc/images/01.png)
### 3.2 组长邀请组员加入仓库
fork 完成后,组长进入自己的仓库页面,在右侧可以看到邀请码。把邀请码发给组员即可,组员不需要再 fork 课程仓库。
![组长查看邀请码](doc/images/02.png)
### 3.3 组员申请加入,组长审批通过
组员拿到邀请码后,可以在页面右上角的 `+` 菜单里选择 `加入项目`,然后提交加入申请。
![组员加入项目入口](doc/images/03.png)
申请发出后,组长到个人主页的待办事项中审批成员申请,同意后组员就可以正常参与仓库协作。
![组长审批组员申请](doc/images/04.png)
### 3.4 在本地克隆小组仓库并配置远端
组长和组员在成功加入小组仓库后,就可以从仓库页面复制 HTTPS 地址,在本地克隆代码:
![复制仓库 HTTPS 地址](doc/images/05.png)
下面示例使用 HTTPS 方式:
```bash
git clone <仓库 HTTPS 地址>
cd nudt-compiler-cpp
```
如果希望后续同步课程仓库更新,可以额外把课程主仓库配置为 `upstream`
```bash
git remote add upstream https://bdgit.educoder.net/NUDT-compiler/nudt-compiler-cpp.git
git remote -v
```
配置完成后,常见的远端分工如下:
- `origin`:你们小组 fork 后的仓库,日常提交代码、推送分支都使用这个远端。
- `upstream`:课程主仓库,通常用于查看或同步课程团队发布的更新。
如果后续需要同步主仓库更新,可以先抓取远端信息:
```bash
git fetch upstream
```
### 3.5 提交与协作建议
借助 Git 进行协作开发,是当前软件开发中非常常见的一种工作方式,也是这门课程里需要大家掌握的基本能力。如果你对 Git 还不太熟悉,可以先看一下网络上的 Git 教程,例如:<https://liaoxuefeng.com/books/git/introduction/index.html>
当然也没有必要一开始学得特别深入,只需要记住常见操作即可,例如 `clone`、`status`、`add`、`commit`、`pull`、`push`、分支切换与合并。遇到具体报错或不会处理的冲突时,可以把现象和命令发给大模型帮你分析。
Git Commit 提交的信息建议尽量写清楚,推荐使用下面的格式:
```text
<type>(<scope>): <subject>
```
常见的 `type` 有:
- `feat`:新增功能
- `fix`:修复 bug
- `refactor`:重构但不改变外部行为
- `docs`:文档修改
- `test`:测试相关
- `chore`:杂项维护
`scope` 用来说明改动的大致范围,例如 `frontend`、`irgen`、`backend`、`test`、`doc`。
`subject` 用一句简短的话说明“这次改了什么”。
例如:
```text
feat(irgen): 支持一元表达式生成
fix(frontend): 修复空语句解析错误
docs(doc): 补充实验环境配置说明
```
除了提交代码本身,也推荐大家把头歌平台上的协作功能真正用起来:
- `Issue` 适合用来拆分任务、记录 bug、整理讨论结果和跟踪待办。
- `PR` / `Merge Request` 适合用来做分支合并和代码评审。比较推荐的流程是:每个人在自己的分支上开发,完成一个相对独立的小功能后提交 PR再由组内其他同学帮忙检查实现思路、代码质量和测试结果。
## 4. 实验环境配置

@ -48,14 +48,11 @@ class IRGenImpl final : public SysYBaseVisitor {
ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_ = nullptr;
ir::Function* func_;
ir::IRBuilder builder_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
// 修复点:添加缺失的函数返回类型标记
bool current_func_void_ = false;
};
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);
const SemanticContext& sema);

@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
# 生成ANTLR解析器代码
echo "生成ANTLR解析器代码..."
java -jar "$ROOT/third_party/antlr-4.13.2-complete.jar" -Dlanguage=Cpp -visitor -o "$ROOT/build/generated/antlr4" "$ROOT/src/antlr4/SysY.g4"
# 构建项目
echo "构建项目..."
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
echo "恭喜通关"

@ -1,5 +1,15 @@
// SysY 子集语法:支持形如
// int main() { int a = 1; int b = 2; return a + b; }
// 的最小返回表达式编译。
// 后续需要自行添加
grammar SysY;
/*===-------------------------------------------===*/
/* Lexer rules */
/*===-------------------------------------------===*/
INT: 'int';
RETURN: 'return';
@ -19,25 +29,70 @@ WS: [ \t\r\n] -> skip;
LINECOMMENT: '//' ~[\r\n]* -> skip;
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
compUnit : funcDef EOF ;
decl : btype varDef SEMICOLON ;
btype : INT ;
varDef : lValue (ASSIGN initValue)? ;
initValue : exp ;
funcDef : funcType ID LPAREN RPAREN blockStmt ;
funcType : INT ;
blockStmt : LBRACE blockItem* RBRACE ;
blockItem : decl | stmt ;
/*===-------------------------------------------===*/
/* Syntax rules */
/*===-------------------------------------------===*/
compUnit
: funcDef EOF
;
decl
: btype varDef SEMICOLON
;
stmt : returnStmt ;
returnStmt : RETURN exp SEMICOLON ;
btype
: INT
;
exp : LPAREN exp RPAREN # parenExp
varDef
: lValue (ASSIGN initValue)?
;
initValue
: exp
;
funcDef
: funcType ID LPAREN RPAREN blockStmt
;
funcType
: INT
;
blockStmt
: LBRACE blockItem* RBRACE
;
blockItem
: decl
| stmt
;
stmt
: returnStmt
;
returnStmt
: RETURN exp SEMICOLON
;
exp
: LPAREN exp RPAREN # parenExp
| var # varExp
| number # numberExp
| exp ADD exp # additiveExp
;
var : ID ;
lValue : ID ;
number : ILITERAL ;
var
: ID
;
lValue
: ID
;
number
: ILITERAL
;

@ -15,7 +15,3 @@ file(GLOB_RECURSE ANTLR4_GENERATED_SOURCES CONFIGURE_DEPENDS
if(ANTLR4_GENERATED_SOURCES)
target_sources(frontend PRIVATE ${ANTLR4_GENERATED_SOURCES})
endif()
if(TARGET antlr4_generate)
add_dependencies(frontend antlr4_generate)
endif()

@ -1,50 +1,39 @@
#include "irgen/IRGen.h"
#include <any>
#include <stdexcept>
#include "RuleContext.h"
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
// 语句生成当前只实现了最小子集。
// 目前支持:
// - return <exp>;
//
// 还未支持:
// - 赋值语句
// - if / while 等控制流
// - 空语句、块语句嵌套分发之外的更多语句形态
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句"));
}
if (auto* r = dynamic_cast<SysYParser::ReturnStmtContext*>(ctx->returnStmt())) {
return visitReturnStmt(r);
}
// 兼容不同 ANTLR 版本的遍历兜底
for (auto* ch : ctx->children) {
if (auto* rs = dynamic_cast<SysYParser::ReturnStmtContext*>(
dynamic_cast<antlr4::RuleContext*>(ch))) {
return visitReturnStmt(rs);
}
if (ctx->returnStmt()) {
return ctx->returnStmt()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句"));
return {};
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少 return"));
throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
}
if (current_func_void_) {
if (ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "void return 带值"));
}
// 修复点:原版的 CreateRetVoid() 名字错了,正确的 API 是 CreateRet()
builder_.CreateRet(nullptr);
} else {
if (!ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "return 缺表达式"));
}
ir::Value* v = EvalExpr(*ctx->exp());
builder_.CreateRet(v);
if (!ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
}
return std::any(BlockFlow::Terminated);
}
ir::Value* v = EvalExpr(*ctx->exp());
builder_.CreateRet(v);
return BlockFlow::Terminated;
}

@ -1,110 +1,110 @@
int A[1024][1024];
int B[1024][1024];
int C[1024][1024];
int main() {
int T = getint(); // 矩阵规模
int R = getint(); // 重复次数
int i = 0;
while (i < T) {
if (i < T / 2) {
getarray(A[i]);
}
i = i + 1;
}
i = 0;
while (i < T) {
if (i >= T / 2) {
getarray(B[i]);
}
i = i + 1;
}
starttime();
i = 0;
while (i < T) {
if (i >= T / 2) {
int j = 0;
while (j < T) {
A[i][j] = -1;
j = j + 1;
}
}
i = i + 1;
}
i = 0;
while (i < T) {
if (i < T / 2) {
int j = 0;
while (j < T) {
B[i][j] = -1;
j = j + 1;
}
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
C[i][j] = A[i][j] * 2 + B[i][j] * 3;
j = j + 1;
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
int val = C[i][j];
val = val * val + 7;
val = val / 3;
C[i][j] = val;
j = j + 1;
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
int k = 0;
int sum = 0;
while (k < T) {
sum = sum + C[i][k] * A[k][j];
k = k + 1;
}
A[i][j] = sum;
j = j + 1;
}
i = i + 1;
}
int total = 0;
int r = 0;
while (r < R) {
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
total = total + A[i][j] * A[i][j];
j = j + 1;
}
i = i + 1;
}
r = r + 1;
}
stoptime();
putint(total);
putch(10);
return 0;
}
int A[1024][1024];
int B[1024][1024];
int C[1024][1024];
int main() {
int T = getint(); // 矩阵规模
int R = getint(); // 重复次数
int i = 0;
while (i < T) {
if (i < T / 2) {
getarray(A[i]);
}
i = i + 1;
}
i = 0;
while (i < T) {
if (i >= T / 2) {
getarray(B[i]);
}
i = i + 1;
}
starttime();
i = 0;
while (i < T) {
if (i >= T / 2) {
int j = 0;
while (j < T) {
A[i][j] = -1;
j = j + 1;
}
}
i = i + 1;
}
i = 0;
while (i < T) {
if (i < T / 2) {
int j = 0;
while (j < T) {
B[i][j] = -1;
j = j + 1;
}
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
C[i][j] = A[i][j] * 2 + B[i][j] * 3;
j = j + 1;
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
int val = C[i][j];
val = val * val + 7;
val = val / 3;
C[i][j] = val;
j = j + 1;
}
i = i + 1;
}
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
int k = 0;
int sum = 0;
while (k < T) {
sum = sum + C[i][k] * A[k][j];
k = k + 1;
}
A[i][j] = sum;
j = j + 1;
}
i = i + 1;
}
int total = 0;
int r = 0;
while (r < R) {
i = 0;
while (i < T) {
int j = 0;
while (j < T) {
total = total + A[i][j] * A[i][j];
j = j + 1;
}
i = i + 1;
}
r = r + 1;
}
stoptime();
putint(total);
putch(10);
return 0;
}

@ -1,11 +0,0 @@
实验步骤:
1.使用 Git 同步功能,从团队 Fork 的项目仓库中,拉取当前关卡对应分支的代码。
2.根据任务要求,完成相关代码文件的编写与完善。
3.编写测试脚本对代码qw逻辑进行充分验证。
4.确认自测通过后,点击“评测”按钮提交检验。
注意:评测输出内容可在 /data/workspace/myshixun/result/result1.txt 文件内查看。
Loading…
Cancel
Save