Compare commits
47 Commits
master
...
feature/se
| Author | SHA1 | Date |
|---|---|---|
|
|
e79d677644 | 1 week ago |
|
|
c8f40ea09a | 2 weeks ago |
|
|
d9201de428 | 2 weeks ago |
|
|
700bbb4e3b | 2 weeks ago |
|
|
728de089ff | 2 weeks ago |
|
|
bc4400c1c7 | 2 weeks ago |
|
|
c945a61f90 | 2 weeks ago |
|
|
0826c86772 | 2 weeks ago |
|
|
ce25b612bf | 2 weeks ago |
|
|
fa76f0fbfc | 2 weeks ago |
|
|
6e129b3a56 | 2 weeks ago |
|
|
5e7e8a6ff2 | 2 weeks ago |
|
|
9c7095bba7 | 2 weeks ago |
|
|
97c01debbd | 2 weeks ago |
|
|
f53f7ec82c | 2 weeks ago |
|
|
affccfb27c | 2 weeks ago |
|
|
b93d769576 | 2 weeks ago |
|
|
9efcdde353 | 2 weeks ago |
|
|
74f325c6fd | 2 weeks ago |
|
|
8477ab4aca | 2 weeks ago |
|
|
8e42c77caf | 2 weeks ago |
|
|
bff9a5d296 | 2 weeks ago |
|
|
6cc1908515 | 2 weeks ago |
|
|
e0c8898dae | 2 weeks ago |
|
|
310c93feac | 2 weeks ago |
|
|
066db23e40 | 2 weeks ago |
|
|
40403e955d | 2 weeks ago |
|
|
7eed5fe6f6 | 2 weeks ago |
|
|
4098545062 | 2 weeks ago |
|
|
f6773274dd | 2 weeks ago |
|
|
e1a4f30488 | 2 weeks ago |
|
|
f3fe34801e | 2 weeks ago |
|
|
d175189193 | 2 weeks ago |
|
|
d1f2efa4ae | 2 weeks ago |
|
|
a015a4bc30 | 3 weeks ago |
|
|
c4479eaa1e | 3 weeks ago |
|
|
a0d5288351 | 3 weeks ago |
|
|
5d4bb511d1 | 3 weeks ago |
|
|
c450277c83 | 3 weeks ago |
|
|
c21c066e4d | 3 weeks ago |
|
|
2070193fcd | 3 weeks ago |
|
|
a1ba450950 | 3 weeks ago |
|
|
56753bc842 | 3 weeks ago |
|
|
43e257368f | 3 weeks ago |
|
|
4f8dec86d7 | 3 weeks ago |
|
|
3b3318613a | 3 weeks ago |
|
|
a8bd6d647d | 3 weeks ago |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 测试脚本
|
||||
# 用法: ./run_tests.sh [--verbose] [<单个测试文件>]
|
||||
|
||||
COMPILER="./build/bin/compiler"
|
||||
TEST_DIR="test/test_case"
|
||||
RESULT_FILE="result.txt"
|
||||
VERBOSE=0
|
||||
|
||||
# 解析参数
|
||||
if [[ "$1" == "--verbose" ]]; then
|
||||
VERBOSE=1
|
||||
shift
|
||||
fi
|
||||
|
||||
# 检查编译器是否存在
|
||||
if [ ! -f "$COMPILER" ]; then
|
||||
echo "错误: 编译器未找到于 $COMPILER"
|
||||
echo "请先完成项目构建 (cmake 和 make)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 如果指定了单个文件,检查文件是否存在
|
||||
if [ -n "$1" ] && [ ! -f "$1" ]; then
|
||||
echo "错误: 文件 $1 不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清空(或创建)结果文件
|
||||
> "$RESULT_FILE"
|
||||
|
||||
# 计数器
|
||||
total=0
|
||||
passed=0
|
||||
failed=0
|
||||
|
||||
echo "开始测试 ir out 解析..."
|
||||
echo "输出将保存到 $RESULT_FILE"
|
||||
echo "------------------------"
|
||||
|
||||
# 确定测试文件列表
|
||||
if [ -n "$1" ]; then
|
||||
# 使用提供的单个文件
|
||||
TEST_FILES=("$1")
|
||||
else
|
||||
# 收集所有 .sy 文件
|
||||
mapfile -t TEST_FILES < <(find "$TEST_DIR" -type f -name "*.sy" | sort)
|
||||
fi
|
||||
|
||||
for file in "${TEST_FILES[@]}"; do
|
||||
((total++))
|
||||
if [ $VERBOSE -eq 1 ]; then
|
||||
echo "测试文件: $file"
|
||||
else
|
||||
echo -n "测试 $file ... "
|
||||
fi
|
||||
|
||||
echo "========== $file ==========" >> "$RESULT_FILE"
|
||||
|
||||
if [ $VERBOSE -eq 1 ]; then
|
||||
# "$COMPILER" --emit-parse-tree "$file" 2>&1 | tee -a "$RESULT_FILE"
|
||||
"$COMPILER" --emit-ir "$file" 2>&1 | tee -a "$RESULT_FILE"
|
||||
result=${PIPESTATUS[0]}
|
||||
else
|
||||
# "$COMPILER" --emit-parse-tree "$file" >> "$RESULT_FILE" 2>&1
|
||||
"$COMPILER" --emit-ir "$file" >> "$RESULT_FILE" 2>&1
|
||||
result=$?
|
||||
fi
|
||||
|
||||
echo "" >> "$RESULT_FILE"
|
||||
|
||||
if [ $result -eq 0 ]; then
|
||||
if [ $VERBOSE -eq 0 ]; then
|
||||
echo "通过"
|
||||
fi
|
||||
((passed++))
|
||||
else
|
||||
if [ $VERBOSE -eq 0 ]; then
|
||||
echo "失败"
|
||||
else
|
||||
echo ">>> 解析失败: $file"
|
||||
fi
|
||||
((failed++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo "------------------------"
|
||||
echo "总计: $total"
|
||||
echo "通过: $passed"
|
||||
echo "失败: $failed"
|
||||
echo "详细输出已保存至 $RESULT_FILE"
|
||||
|
||||
if [ $failed -gt 0 ]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
@ -1,11 +1,121 @@
|
||||
// GlobalValue 占位实现:
|
||||
// - 具体的全局初始化器、打印和链接语义需要自行补全
|
||||
|
||||
// ir/GlobalValue.cpp
|
||||
#include "ir/IR.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ir {
|
||||
|
||||
GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
|
||||
: User(std::move(ty), std::move(name)) {}
|
||||
|
||||
} // namespace ir
|
||||
void GlobalValue::SetInitializer(ConstantValue* init) {
|
||||
if (!init) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: init is null");
|
||||
}
|
||||
|
||||
// 获取实际的值类型(用于类型检查)
|
||||
std::shared_ptr<Type> value_type;
|
||||
|
||||
// 如果当前类型是指针,获取指向的值类型
|
||||
if (GetType()->IsPtrInt32()) {
|
||||
value_type = Type::GetInt32Type();
|
||||
} else if (GetType()->IsPtrFloat()) {
|
||||
value_type = Type::GetFloatType();
|
||||
} else if (GetType()->IsPtrInt1()) {
|
||||
value_type = Type::GetInt1Type();
|
||||
} else {
|
||||
// 非指针类型:直接使用当前类型
|
||||
value_type = GetType();
|
||||
}
|
||||
|
||||
// 类型检查
|
||||
bool type_match = false;
|
||||
|
||||
// 检查标量类型
|
||||
if (value_type->IsInt32() && init->GetType()->IsInt32()) {
|
||||
type_match = true;
|
||||
} else if (value_type->IsFloat() && init->GetType()->IsFloat()) {
|
||||
type_match = true;
|
||||
} else if (value_type->IsInt1() && init->GetType()->IsInt1()) {
|
||||
type_match = true;
|
||||
}
|
||||
// 检查数组类型:允许用单个标量初始化整个数组
|
||||
else if (value_type->IsArray()) {
|
||||
auto* array_ty = static_cast<ArrayType*>(value_type.get());
|
||||
auto* elem_type = array_ty->GetElementType().get();
|
||||
|
||||
if (elem_type->IsInt32() && init->GetType()->IsInt32()) {
|
||||
type_match = true;
|
||||
} else if (elem_type->IsFloat() && init->GetType()->IsFloat()) {
|
||||
type_match = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type_match) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
|
||||
}
|
||||
|
||||
initializer_.clear();
|
||||
initializer_.push_back(init);
|
||||
}
|
||||
|
||||
void GlobalValue::SetInitializer(const std::vector<ConstantValue*>& init) {
|
||||
if (init.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取实际的值类型
|
||||
std::shared_ptr<Type> value_type;
|
||||
|
||||
if (GetType()->IsPtrInt32()) {
|
||||
value_type = Type::GetInt32Type();
|
||||
} else if (GetType()->IsPtrFloat()) {
|
||||
value_type = Type::GetFloatType();
|
||||
} else if (GetType()->IsPtrInt1()) {
|
||||
value_type = Type::GetInt1Type();
|
||||
} else {
|
||||
value_type = GetType();
|
||||
}
|
||||
|
||||
// 检查类型
|
||||
if (value_type->IsArray()) {
|
||||
auto* array_ty = static_cast<ArrayType*>(value_type.get());
|
||||
size_t array_size = array_ty->GetElementCount();
|
||||
|
||||
if (init.size() > array_size) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: too many initializers");
|
||||
}
|
||||
|
||||
// 检查每个初始化值的类型
|
||||
auto* elem_type = array_ty->GetElementType().get();
|
||||
for (auto* elem : init) {
|
||||
bool elem_match = false;
|
||||
if (elem_type->IsInt32() && elem->GetType()->IsInt32()) {
|
||||
elem_match = true;
|
||||
} else if (elem_type->IsFloat() && elem->GetType()->IsFloat()) {
|
||||
elem_match = true;
|
||||
}
|
||||
|
||||
if (!elem_match) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: element type mismatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value_type->IsInt32() || value_type->IsFloat() || value_type->IsInt1()) {
|
||||
if (init.size() != 1) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: scalar requires exactly one initializer");
|
||||
}
|
||||
|
||||
if ((value_type->IsInt32() && !init[0]->GetType()->IsInt32()) ||
|
||||
(value_type->IsFloat() && !init[0]->GetType()->IsFloat()) ||
|
||||
(value_type->IsInt1() && !init[0]->GetType()->IsInt1())) {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("GlobalValue::SetInitializer: unsupported type");
|
||||
}
|
||||
|
||||
initializer_ = init;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
@ -1,31 +1,219 @@
|
||||
// 当前仅支持 void、i32 和 i32*。
|
||||
#include "ir/IR.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace ir {
|
||||
|
||||
Type::Type(Kind k) : kind_(k) {}
|
||||
|
||||
size_t Type::Size() const {
|
||||
switch (kind_) {
|
||||
case Kind::Void: return 0;
|
||||
case Kind::Int32: return 4;
|
||||
case Kind::Float: return 4; // 单精度浮点 4 字节
|
||||
case Kind::PtrInt32: return 8; // 假设 64 位指针
|
||||
case Kind::PtrFloat: return 8;
|
||||
case Kind::Label: return 8; // 标签地址大小(指针大小)
|
||||
default: return 0; // 派生类应重写
|
||||
}
|
||||
}
|
||||
|
||||
size_t Type::Alignment() const {
|
||||
switch (kind_) {
|
||||
case Kind::Int32: return 4;
|
||||
case Kind::Float: return 4;
|
||||
case Kind::PtrInt32: return 8;
|
||||
case Kind::PtrFloat: return 8;
|
||||
case Kind::Label: return 8; // 与指针相同
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::IsComplete() const {
|
||||
return kind_ != Kind::Void;
|
||||
}
|
||||
const std::shared_ptr<Type>& Type::GetVoidType() {
|
||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Void);
|
||||
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Void));
|
||||
return type;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Type>& Type::GetInt32Type() {
|
||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int32);
|
||||
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Int32));
|
||||
return type;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Type>& Type::GetFloatType() {
|
||||
static const std::shared_ptr<Type> type(new Type(Kind::Float));
|
||||
return type;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
|
||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::PtrInt32);
|
||||
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::PtrInt32));
|
||||
return type;
|
||||
}
|
||||
|
||||
Type::Kind Type::GetKind() const { return kind_; }
|
||||
const std::shared_ptr<Type>& Type::GetPtrFloatType() {
|
||||
static const std::shared_ptr<Type> type(new Type(Kind::PtrFloat));
|
||||
return type;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Type>& Type::GetLabelType() {
|
||||
static const std::shared_ptr<Type> type(new Type(Kind::Label));
|
||||
return type;
|
||||
}
|
||||
|
||||
// Int1 类型表示布尔值,通常用于比较指令的结果
|
||||
const std::shared_ptr<Type>& Type::GetInt1Type() {
|
||||
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Int1));
|
||||
return type;
|
||||
}
|
||||
// PtrInt1 类型表示指向 Int1 的指针,主要用于条件跳转等场景
|
||||
const std::shared_ptr<Type>& Type::GetPtrInt1Type() {
|
||||
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::PtrInt1));
|
||||
return type;
|
||||
}
|
||||
|
||||
bool Type::IsVoid() const { return kind_ == Kind::Void; }
|
||||
// ---------- 数组类型缓存 ----------
|
||||
// 使用自定义键类型保证唯一性:元素类型指针 + 维度向量
|
||||
struct ArrayKey {
|
||||
const Type* elem_type;
|
||||
std::vector<int> dims;
|
||||
|
||||
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
|
||||
bool operator==(const ArrayKey& other) const {
|
||||
return elem_type == other.elem_type && dims == other.dims;
|
||||
}
|
||||
};
|
||||
|
||||
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
|
||||
struct ArrayKeyHash {
|
||||
std::size_t operator()(const ArrayKey& key) const {
|
||||
std::size_t h = std::hash<const Type*>{}(key.elem_type);
|
||||
for (int d : key.dims) {
|
||||
h ^= std::hash<int>{}(d) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
static std::unordered_map<ArrayKey, std::weak_ptr<ArrayType>, ArrayKeyHash>& GetArrayCache() {
|
||||
static std::unordered_map<ArrayKey, std::weak_ptr<ArrayType>, ArrayKeyHash> cache;
|
||||
return cache;
|
||||
}
|
||||
|
||||
std::shared_ptr<ArrayType> Type::GetArrayType(std::shared_ptr<Type> elem,
|
||||
std::vector<int> dims) {
|
||||
// 检查维度合法性
|
||||
for (int d : dims) {
|
||||
if (d <= 0) {
|
||||
// SysY 数组维度必须为正整数常量表达式,这里假设已检查
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayKey key{elem.get(), dims};
|
||||
auto& cache = GetArrayCache();
|
||||
auto it = cache.find(key);
|
||||
if (it != cache.end()) {
|
||||
auto ptr = it->second.lock();
|
||||
if (ptr) return ptr;
|
||||
}
|
||||
|
||||
auto arr = std::shared_ptr<ArrayType>(new ArrayType(std::move(elem), std::move(dims)));
|
||||
cache[key] = arr;
|
||||
return arr;
|
||||
}
|
||||
|
||||
// ---------- 函数类型缓存 ----------
|
||||
struct FunctionKey {
|
||||
const Type* return_type;
|
||||
std::vector<const Type*> param_types;
|
||||
|
||||
bool operator==(const FunctionKey& other) const {
|
||||
return return_type == other.return_type && param_types == other.param_types;
|
||||
}
|
||||
};
|
||||
|
||||
struct FunctionKeyHash {
|
||||
std::size_t operator()(const FunctionKey& key) const {
|
||||
std::size_t h = std::hash<const Type*>{}(key.return_type);
|
||||
for (const Type* t : key.param_types) {
|
||||
h ^= std::hash<const Type*>{}(t) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
static std::unordered_map<FunctionKey, std::weak_ptr<FunctionType>, FunctionKeyHash>& GetFunctionCache() {
|
||||
static std::unordered_map<FunctionKey, std::weak_ptr<FunctionType>, FunctionKeyHash> cache;
|
||||
return cache;
|
||||
}
|
||||
|
||||
std::shared_ptr<FunctionType> Type::GetFunctionType(std::shared_ptr<Type> ret,
|
||||
std::vector<std::shared_ptr<Type>> params) {
|
||||
// 提取裸指针用于键(保证唯一性,因为 shared_ptr 指向同一对象)
|
||||
std::vector<const Type*> param_ptrs;
|
||||
param_ptrs.reserve(params.size());
|
||||
for (const auto& p : params) {
|
||||
param_ptrs.push_back(p.get());
|
||||
}
|
||||
|
||||
FunctionKey key{ret.get(), std::move(param_ptrs)};
|
||||
auto& cache = GetFunctionCache();
|
||||
auto it = cache.find(key);
|
||||
if (it != cache.end()) {
|
||||
auto ptr = it->second.lock();
|
||||
if (ptr) return ptr;
|
||||
}
|
||||
|
||||
auto func = std::shared_ptr<FunctionType>(new FunctionType(std::move(ret), std::move(params)));
|
||||
cache[key] = func;
|
||||
return func;
|
||||
}
|
||||
|
||||
// ---------- ArrayType 实现 ----------
|
||||
ArrayType::ArrayType(std::shared_ptr<Type> elem, std::vector<int> dims)
|
||||
: Type(Kind::Array), elem_type_(std::move(elem)), dims_(std::move(dims)) {
|
||||
// 数组元素类型必须是完整类型
|
||||
assert(elem_type_ && elem_type_->IsComplete());
|
||||
}
|
||||
|
||||
size_t ArrayType::GetElementCount() const {
|
||||
size_t count = 1;
|
||||
for (int d : dims_) count *= d;
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t ArrayType::Size() const {
|
||||
return GetElementCount() * elem_type_->Size();
|
||||
}
|
||||
|
||||
size_t ArrayType::Alignment() const {
|
||||
// 数组对齐等于其元素对齐
|
||||
return elem_type_->Alignment();
|
||||
}
|
||||
|
||||
bool ArrayType::IsComplete() const {
|
||||
// 维度已确定且元素类型完整,则数组完整
|
||||
return !dims_.empty() && elem_type_->IsComplete();
|
||||
}
|
||||
|
||||
// ---------- FunctionType 实现 ----------
|
||||
FunctionType::FunctionType(std::shared_ptr<Type> ret,
|
||||
std::vector<std::shared_ptr<Type>> params)
|
||||
: Type(Kind::Function), return_type_(std::move(ret)), param_types_(std::move(params)) {}
|
||||
|
||||
size_t FunctionType::Size() const {
|
||||
// 函数类型没有运行时大小,通常用于类型检查,返回 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t FunctionType::Alignment() const {
|
||||
// 不对齐
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool FunctionType::IsComplete() const {
|
||||
// 函数类型总是完整的(只要返回类型完整,但 SysY 中 void 也视为完整)
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue