feat(compiler): 提交除文档外的demo代码

master
李仁哲 4 weeks ago
parent 74130b0dfa
commit 3cd1241271

@ -0,0 +1,454 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "ascii-canvas"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891"
dependencies = [
"term",
]
[[package]]
name = "bit-set"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "ena"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1"
dependencies = [
"log",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fixedbitset"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "indexmap"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "keccak"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
dependencies = [
"cpufeatures",
]
[[package]]
name = "lalrpop"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501"
dependencies = [
"ascii-canvas",
"bit-set",
"ena",
"itertools",
"lalrpop-util 0.22.2",
"petgraph",
"pico-args",
"regex",
"regex-syntax",
"sha3",
"string_cache",
"term",
"unicode-xid",
"walkdir",
]
[[package]]
name = "lalrpop-util"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733"
dependencies = [
"regex-automata",
"rustversion",
]
[[package]]
name = "lalrpop-util"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884f3e747ed2dcee867cda1b0c31a048f9e20de2d916a248949319921a2e666e"
dependencies = [
"regex-automata",
]
[[package]]
name = "libc"
version = "0.2.183"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "memchr"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nudt-compiler-rust"
version = "0.1.0"
dependencies = [
"lalrpop",
"lalrpop-util 0.23.1",
"rustc-hash",
]
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link",
]
[[package]]
name = "petgraph"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]]
name = "phf_shared"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
]
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]]
name = "siphasher"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "string_cache"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
dependencies = [
"new_debug_unreachable",
"parking_lot",
"phf_shared",
"precomputed-hash",
]
[[package]]
name = "term"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1"
dependencies = [
"windows-sys",
]
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]

@ -0,0 +1,16 @@
[package]
name = "nudt-compiler-rust"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "compiler"
path = "src/main.rs"
[build-dependencies]
lalrpop = "0.22.1"
[dependencies]
lalrpop = "0.22.1"
lalrpop-util = "0.23.1"
rustc-hash = "2.1.1"

@ -0,0 +1,3 @@
fn main() {
lalrpop::process_src().unwrap();
}

@ -0,0 +1,274 @@
use super::mir::{
regs::{ PReg, Reg, RegKind, VReg},
mir_operand::MemLoc,
mir_block::MirBlock,
mir_function::MirFunction,
mir_label::MirLabel,
mir_inst::{MirInst, MirInstKind},
mir_context::{MirContext, RawData},
};
use crate::utils::{linked_list::LinkedListContainer,
storage::ArenaPtr};
pub trait Display {
fn display(self, mctx: &MirContext) -> String;
}
impl Display for MirLabel {
fn display(self, _mctx: &MirContext) -> String { self.0 }
}
impl Display for MirBlock {
fn display(self, mctx: &MirContext) -> String {
self.label(mctx).clone().display(mctx)
}
}
impl Display for MirFunction {
fn display(self, mctx: &MirContext) -> String {
self.label(mctx).clone().display(mctx)
}
}
impl Display for PReg {
fn display(self, _mctx: &MirContext) -> String {
let mut asm = String::new();
let str = match self.kind() {
RegKind::Address => match self.num() {
0 => "x0",
1 => "x1",
2 => "x2",
3 => "x3",
4 => "x4",
5 => "x5",
6 => "x6",
7 => "x7",
8 => "x8",
9 => "x9",
10 => "x10",
11 => "x11",
12 => "x12",
13 => "x13",
14 => "x14",
15 => "x15",
16 => "x16",
17 => "x17",
18 => "x18",
19 => "x19",
20 => "x20",
21 => "x21",
22 => "x22",
23 => "x23",
24 => "x24",
25 => "x25",
26 => "x26",
27 => "x27",
28 => "x28",
29 => "fp",
30 => "x30",
31 => "sp",
32 => "xzr",
_ => "<invalid>",
},
RegKind::Integer => match self.num() {
0 => "w0",
1 => "w1",
2 => "w2",
3 => "w3",
4 => "w4",
5 => "w5",
6 => "w6",
7 => "w7",
8 => "w8",
9 => "w9",
10 => "w10",
11 => "w11",
12 => "w12",
13 => "w13",
14 => "w14",
15 => "w15",
16 => "w16",
17 => "w17",
18 => "w18",
19 => "w19",
20 => "w20",
21 => "w21",
22 => "w22",
23 => "w23",
24 => "w24",
25 => "w25",
26 => "w26",
27 => "w27",
28 => "w28",
29 => "fp",
30 => "w30",
31 => "sp",
32 => "wzr",
_ => "invalid",
}
_ => "invalid"
};
asm += str.to_string().as_str();
asm
}
}
impl Display for VReg {
fn display(self, _mctx: &MirContext) -> String {
let mut asm = String::new();
let str = match self.1 {
RegKind::Integer => "vw",
_ => "invalid",
};
asm += str.to_string().as_str();
asm += &self.0.to_string();
asm
}
}
impl Display for Reg {
fn display(self, mctx: &MirContext) -> String {
let mut asm = String::new();
match self {
Reg::P(preg) => asm += format!("{}", preg.display(mctx)).as_str(),
Reg::V(vreg) => asm += format!("{}", vreg.display(mctx)).as_str(),
}
asm
}
}
impl Display for MirInst {
fn display(self, mctx: &MirContext) -> String {
let mut asm = String::new();
match &self.deref(mctx).unwrap().kind {
MirInstKind::Str { rm, mem } => {
asm += format!("str {}, {}", rm.display(mctx), mem.display(mctx)).as_str()
}
MirInstKind::Ldr { rd, mem } => {
asm += format!("ldr {}, {}", rd.display(mctx), mem.display(mctx)).as_str()
}
MirInstKind::Movz{ rd, imm } => {
asm += format!("movz {}, #{}", rd.display(mctx), imm).as_str();
}
MirInstKind::Movk{ rd, imm } => {
asm += format!("movk {}, #{}, lsl #16", rd.display(mctx),imm).as_str();
}
MirInstKind::MovReg { rd, rn } => {
asm += format!("mov {}, {}", rd.display(mctx), rn.display(mctx)).as_str()
}
MirInstKind::B { target } => {
asm += format!("b {}", target.clone().display(mctx)).as_str()
}
MirInstKind::Ret => {
asm += format!("ret").as_str()
}
MirInstKind::Add { rd, rn, rm } => {
asm += format!("add {}, {}, {}", rd.display(mctx), rn.display(mctx), rm.display(mctx)).as_str();
}
MirInstKind::Addi {rd,rn,imm} => {
asm += format!("add {}, {}, #{}", rd.display(mctx), rn.display(mctx), imm).as_str();
}
MirInstKind::Subi {rd,rn,imm} => {
asm += format!("sub {}, {}, #{}", rd.display(mctx), rn.display(mctx), imm).as_str();
}
MirInstKind::Adrp { rd, label } => {
asm += format!("adrp {}, {}", rd.display(mctx), label.clone().display(mctx)).as_str();
}
MirInstKind::AddLabel { rd, rn, label } => {
asm += format!("add {}, {}, :lo12:{}",rd.display(mctx), rn.display(mctx), label.clone().display(mctx)).as_str()
}
}
asm
}
}
impl Display for MemLoc {
fn display(self, mctx: &MirContext) -> String {
let mut asm = String::new();
match self {
MemLoc::Reg { address } => {
asm += format!("[{}]", address.display(mctx)).as_str()
}
MemLoc::RegOffset { base, offset } => {
if offset == 0 {
asm += format!("[{}]", base.display(mctx)).as_str()
}
else{
asm += format!("[{}, #{}]", base.display(mctx), offset).as_str()
}
}
MemLoc::Reg2Offset { base, offset } => {
if offset.is_address() {
asm += format!("[{}, {}]", base.display(mctx), offset.display(mctx)).as_str()
} else {
asm += format!("[{}, {}, SXTW]", base.display(mctx), offset.display(mctx)).as_str()
}
}
}
asm
}
}
impl MirContext {
pub fn get_asm(&self) -> String {
let mut asm = String::new();
asm += "\t.arch armv8-a\n\t.text\n";
for func_data in self.funcs.iter() {
let func = func_data.self_ptr();
if func.is_external(self) {
continue;
}
asm += format!("\t.global {}\n", func.label(self).clone().display(self)).as_str();
asm += format!("\t.type {}, %function\n", func.label(self).clone().display(self)).as_str();
asm += format!("\t.p2align 3\n").as_str();
asm += format!("{}:\n", func.label(self).clone().display(self)).as_str();
for block in func.iter(self) {
let block_label = block.label(self).clone().display(self);
let clean_label = block_label.trim_start_matches('.');
if block != func.head(self).unwrap() {
asm += format!("{}:\n", clean_label).as_str();
}
for inst in block.iter(self) {
asm += format!("\t{}\n", inst.display(self)).as_str();
}
}
asm += "\n";
}
asm += "\n";
if !self.raw_data.is_empty() {
for (label, raw_data) in self.raw_data.iter() {
let label_name = label.clone().display(self);
// 全局变量声明
match raw_data {
RawData::Bytes(bytes,size) => {
asm += "\t.section .data\n";
asm += "\t.p2align 3\n";
asm += format!("\t.global {}\n", label_name).as_str();
asm += format!("\t.type {}, %object\n", label_name).as_str();
asm += format!("{}:\n", label_name).as_str();
// 按4字节分组输出.word
for chunk in bytes {
asm += format!("\t.word {}\n", chunk).as_str();
}
// 没有赋值的填zeros
if *size > 32 * bytes.len() {
asm += format!("\t.zero {}\n", size - 32 * bytes.len()).as_str();
}
}
RawData::Bss(size) => {
asm += "\t.section .bss\n";
asm += "\t.p2align 3\n";
asm += format!("\t.global {}\n", label_name).as_str();
asm += format!("\t.type {}, %object\n", label_name).as_str();
asm += format!("{}:\n", label_name).as_str();
asm += format!("\t.zero {}\n", size).as_str();
}
}
asm += "\n";
}
}
asm
}
}

@ -0,0 +1,128 @@
use std::hash::Hash;
use super::{mir_label::MirLabel,
mir_inst::MirInst,
mir_function::MirFunction,
mir_context::MirContext};
use crate::{ utils::{linked_list::{LinkedListContainer, LinkedListNode},
storage::{Arena, ArenaPtr, GenericPtr}}};
pub struct MirBlockData {
label: MirLabel,
start: Option<MirInst>,
end: Option<MirInst>,
succ: Option<MirBlock>,
pre: Option<MirBlock>,
parent: Option<MirFunction>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MirBlock(pub GenericPtr<MirBlockData>);
impl MirBlock {
pub fn new(ctx: &mut MirContext, label: impl Into<MirLabel>) -> Self {
ctx.alloc(MirBlockData {
label: label.into(),
start: None,
end: None,
succ: None,
pre: None,
parent: None,
})
}
pub fn get_name(&self, ctx: &MirContext) -> String{
self.deref(ctx).expect("Invalid block").label.0.clone()
}
pub fn size(self, arena: &MirContext) -> usize {
let mut size = 0;
for _ in self.iter(arena) {
size += 1;
}
size
}
pub fn label(self, arena: &MirContext) -> &MirLabel {
&self.deref(arena).expect("Invalid block").label
}
pub fn remove(self, arena: &mut MirContext) {
self.unlink(arena);
arena.dealloc(self).unwrap();
}
pub fn get_head(self, ctx: &MirContext) -> Option<MirInst> {
self.deref(ctx).expect("Invalid block").start
}
pub fn get_tail(self, ctx: &MirContext) -> Option<MirInst> {
self.deref(ctx).expect("Invalid block").end
}
pub fn is_ret(self, ctx: &MirContext) -> bool {
if let Some(inst) = self.get_tail(ctx) {
inst.is_ret(ctx);
}
false
}
}
impl Hash for MirBlock {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl ArenaPtr for MirBlock {
type Arena = MirContext;
type Data = MirBlockData;
}
impl LinkedListContainer<MirInst> for MirBlock {
type Ctx = MirContext;
fn head(self, ctx: &MirContext) -> Option<MirInst> {
self.deref(ctx).expect("Invalid Inst").start
}
fn tail(self, ctx: &MirContext) -> Option<MirInst> {
self.deref(ctx).expect("Invalid Inst").end
}
fn set_head(self, ctx: &mut MirContext, start: Option<MirInst>) {
self.deref_mut(ctx).expect("Invalid Inst").start = start;
}
fn set_tail(self, ctx: &mut MirContext, end: Option<MirInst>) {
self.deref_mut(ctx).expect("Invalid Inst").end = end;
}
}
impl LinkedListNode for MirBlock {
type Container = MirFunction;
type Ctx = MirContext;
fn succ(self, ctx: &MirContext) -> Option<Self> {
self.deref(ctx).expect("Invaliid Block").succ
}
fn pre(self, ctx: &MirContext) -> Option<Self> {
self.deref(ctx).expect("Invaliid Block").pre
}
fn set_succ(self, ctx: &mut MirContext, succ: Option<Self>) {
self.deref_mut(ctx).expect("Invaliid Block").succ = succ;
}
fn set_pre(self, ctx: &mut MirContext, pre: Option<Self>) {
self.deref_mut(ctx).expect("Invaliid Block").pre = pre;
}
fn container(self, ctx: &MirContext) -> Option<MirFunction> {
self.deref(ctx).expect("Invaliid Block").parent
}
fn set_container(self, ctx: &mut MirContext, parent: Option<MirFunction>) {
self.deref_mut(ctx).expect("Invaliid Block").parent = parent;
}
}

@ -0,0 +1,103 @@
use super::{mir_label::MirLabel,
mir_block::{MirBlock, MirBlockData},
mir_function::{MirFunction, MirFunctionData},
mir_inst::{MirInst, MirInstData},
regs::{RegKind, VReg},
};
use crate::utils::{storage::{Arena, ArenaPtr, GenericArena}};
pub enum RawData {
Bytes(Vec<i32>, usize),
Bss(usize),
}
#[derive(Default)]
pub struct MirContext {
pub insts: GenericArena<MirInstData>,
pub blocks: GenericArena<MirBlockData>,
pub funcs: GenericArena<MirFunctionData>,
pub raw_data: Vec<(MirLabel, RawData)>,
pub vreg_counter: u32,
pub arch: String,
}
impl MirContext {
pub fn new() -> Self { Self::default() }
pub fn generate_vreg(&mut self, kind: RegKind) -> VReg {
let vreg = VReg::new(self.vreg_counter, kind);
self.vreg_counter += 1;
vreg
}
pub fn add_raw_data(&mut self, label: impl Into<MirLabel>, data: RawData) {
self.raw_data.push((label.into(), data));
}
pub fn get_functions(&self) -> impl Iterator<Item = MirFunction> + '_ {
self.funcs.iter().map(|data| data.self_ptr() )
}
}
impl Arena<MirBlock> for MirContext {
fn alloc_with<F>(&mut self, f: F) -> MirBlock
where
F: FnOnce(MirBlock) -> MirBlockData,
{
MirBlock(self.blocks.alloc_with(|p| f(MirBlock(p))))
}
fn deref(&self, ptr: MirBlock) -> Option<&MirBlockData> {
self.blocks.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: MirBlock) -> Option<&mut MirBlockData> {
self.blocks.deref_mut(ptr.0)
}
fn dealloc(&mut self, ptr: MirBlock) -> Option<MirBlockData> {
self.blocks.dealloc(ptr.0)
}
}
impl Arena<MirFunction> for MirContext {
fn alloc_with<F>(&mut self, f: F) -> MirFunction
where
F: FnOnce(MirFunction) -> MirFunctionData,
{
MirFunction(self.funcs.alloc_with(|p| f(MirFunction(p))))
}
fn deref(&self, ptr: MirFunction) -> Option<&MirFunctionData> { self.funcs.deref(ptr.0) }
fn deref_mut(&mut self, ptr: MirFunction) -> Option<&mut MirFunctionData> {
self.funcs.deref_mut(ptr.0)
}
fn dealloc(&mut self, ptr: MirFunction) -> Option<<MirFunction as ArenaPtr>::Data> {
self.funcs.dealloc(ptr.0)
}
}
impl Arena<MirInst> for MirContext {
fn alloc_with<F>(&mut self, f: F) -> MirInst
where
F: FnOnce(MirInst) -> MirInstData,
{
MirInst(self.insts.alloc_with(|p| f(MirInst(p))))
}
fn deref(&self, ptr: MirInst) -> Option<&MirInstData> {
self.insts.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: MirInst) -> Option<&mut MirInstData> {
self.insts.deref_mut(ptr.0)
}
fn dealloc(&mut self, ptr: MirInst) -> Option<MirInstData> {
self.insts.dealloc(ptr.0)
}
}

@ -0,0 +1,142 @@
use std::collections::BTreeSet;
use std::hash::Hash;
use super::{mir_label::MirLabel,
mir_block::MirBlock,
mir_context::MirContext,
regs::PReg};
use crate::utils::{linked_list::LinkedListContainer,
storage::{Arena, ArenaPtr, GenericPtr}};
pub struct MirFunctionData {
self_ptr: MirFunction,
label: MirLabel,
storage_stack_size: i32,
current_stack_size: i32,
calleeargs_stack_size: i32,
callee_regs: BTreeSet<PReg>,
is_external: bool,
start: Option<MirBlock>,
end: Option<MirBlock>,
}
impl MirFunctionData {
pub fn self_ptr(&self) -> MirFunction { self.self_ptr }
}
#[derive(Debug, PartialEq, Eq)]
pub struct MirFunction(pub GenericPtr<MirFunctionData>);
impl MirFunction {
pub fn new(ctx: &mut MirContext, label: impl Into<MirLabel>, is_external: bool) -> Self {
ctx.alloc_with(|self_ptr| MirFunctionData {
self_ptr,
label: label.into(),
storage_stack_size: 0,
current_stack_size: 0,
calleeargs_stack_size: 0,
callee_regs: BTreeSet::default(),
is_external,
start: None,
end: None,
})
}
pub fn label(self, arena: &MirContext) -> &MirLabel {
&self.deref(arena).expect("Invalid Function Pointer").label
}
pub fn get_id(self, ctx: &MirContext) -> String {
self.label(ctx).0.clone()
}
pub fn get_head(self, ctx: &MirContext) -> Option<MirBlock> {
self.deref(ctx).expect("Invalid Function Pointer").start
}
pub fn get_tail(self, ctx: &MirContext) -> Option<MirBlock> {
self.deref(ctx).expect("Invalid Function Pointer").end
}
pub fn is_external(self, ctx: &MirContext) -> bool {
self.deref(ctx).expect("Invalid Function Pointer").is_external
}
pub fn current_stack_size(self, ctx: &MirContext) -> i32 {
self.deref(ctx).expect("Invalid Function Pointer").current_stack_size
}
pub fn add_current_stack_size(self, ctx: &mut MirContext, size: i32) {
self.deref_mut(ctx).expect("Invalid Function Pointer").current_stack_size += size;
}
pub fn storage_stack_size(self, ctx: &MirContext) -> i32 {
self.deref(ctx).expect("Invalid Function Pointer").storage_stack_size
}
pub fn add_storage_stack_size(self, ctx: &mut MirContext, size: i32) {
self.deref_mut(ctx).expect("Invalid Function Pointer").storage_stack_size += size;
}
pub fn add_calleeargs_stack_size(self, ctx: &mut MirContext, size: i32) {
self.deref_mut(ctx).expect("Invalid Function Pointer").calleeargs_stack_size += size;
}
pub fn calleeargs_stack_size(self, ctx: &MirContext) -> i32 {
self.deref(ctx).expect("Invalid Function Pointer").calleeargs_stack_size
}
pub fn callee_regs(self, ctx: &MirContext) -> Vec<PReg> {
let mut regs: Vec<PReg> = self.deref(ctx).expect("Invalid Function Pointer").callee_regs.iter().copied().collect();
regs.sort();
regs
}
pub fn add_callee_reg(self, ctx: &mut MirContext, reg: PReg) {
self.deref_mut(ctx).expect("Invalid Function Pointer").callee_regs.insert(reg);
}
pub fn callee_stack_size(self, ctx: &MirContext) -> i32 {
let mut size = 0;
for _reg in self.callee_regs(ctx) {
size += 8;
}
if size % 8 != 0 {
size += 4;
}
size
}
}
impl ArenaPtr for MirFunction {
type Arena = MirContext;
type Data = MirFunctionData;
}
impl LinkedListContainer<MirBlock> for MirFunction {
type Ctx = MirContext;
fn head(self, ctx: &Self::Ctx) -> Option<MirBlock> { self.deref(ctx).expect("Invalid Function Pointer").start }
fn tail(self, ctx: &Self::Ctx) -> Option<MirBlock> { self.deref(ctx).expect("Invalid Function Pointer").end }
fn set_head(self, ctx: &mut Self::Ctx, start: Option<MirBlock>) {
self.deref_mut(ctx).expect("Invalid Function Pointer").start = start;
}
fn set_tail(self, ctx: &mut Self::Ctx, end: Option<MirBlock>) {
self.deref_mut(ctx).expect("Invalid Function Pointer").end = end;
}
}
impl Clone for MirFunction {
fn clone(&self) -> Self { *self }
}
impl Copy for MirFunction {}
impl Hash for MirFunction {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}

@ -0,0 +1,503 @@
use super::{
mir_block::MirBlock,
mir_context::MirContext,
mir_operand::MemLoc,
regs::Reg,
};
use crate::{ backend::mir::mir_label::MirLabel, utils::{
linked_list::{LinkedListContainer, LinkedListError, LinkedListNode},
storage::{Arena, ArenaPtr, GenericPtr},
}};
pub enum MirInstKind {
// 二元指令
Add { rd: Reg, rn: Reg, rm: Reg }, // 加法
Addi { rd: Reg, rn: Reg, imm: i32 },
Subi {rd: Reg, rn: Reg, imm: i32},
// 内存操作指令
Str { rm: Reg, mem: MemLoc }, // 存储到内存
Ldr { rd: Reg, mem: MemLoc }, // 从内存加载
// 移动指令
Movz { rd: Reg, imm: i32},
Movk { rd: Reg, imm: i32},
MovReg {rd: Reg, rn: Reg}, // 寄存器移动
// 分支指令
B { target: MirBlock }, // 无条件分支
Ret, // 函数返回
Adrp {rd: Reg, label: MirLabel}, // 加载全局变量标签
AddLabel {rd: Reg, rn: Reg, label: MirLabel},
}
pub struct MirInstData {
pub kind: MirInstKind,
pub succ: Option<MirInst>,
pub pre: Option<MirInst>,
pub parent: Option<MirBlock>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MirInst(pub GenericPtr<MirInstData>);
impl MirInst {
pub fn add(ctx: &mut MirContext, rd: Reg, rn: Reg, rm: Reg) -> Self {
let kind = MirInstKind::Add { rd, rn, rm };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn addi(ctx: &mut MirContext, rd: Reg, rn: Reg, imm: i32) -> Self {
let kind = MirInstKind::Addi { rd, rn, imm };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn subi(ctx: &mut MirContext, rd: Reg, rn: Reg, imm: i32) -> Self {
let kind = MirInstKind::Subi { rd, rn, imm };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn str(ctx: &mut MirContext, rm: Reg, mem: MemLoc) -> Self {
let kind = MirInstKind::Str { rm, mem};
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn ldr(ctx: &mut MirContext, rd: Reg, mem: MemLoc) -> Self {
let kind = MirInstKind::Ldr { rd, mem };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn movz(ctx: &mut MirContext, rd: Reg, imm: i32) -> Self {
let kind = MirInstKind::Movz { rd, imm};
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn movk(ctx: &mut MirContext, rd: Reg, imm: i32) -> Self {
let kind = MirInstKind::Movk { rd, imm};
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn b(ctx: &mut MirContext, target: MirBlock) -> Self {
let kind = MirInstKind::B { target };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn ret(ctx: &mut MirContext) -> Self {
let kind = MirInstKind::Ret;
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn adrp(ctx: &mut MirContext, rd: Reg, label: MirLabel) -> Self {
let kind = MirInstKind::Adrp { rd, label };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn add_label(ctx: &mut MirContext, rd: Reg, rn: Reg, label: MirLabel) -> Self {
let kind = MirInstKind::AddLabel { rd, rn, label };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn mov_reg(ctx: &mut MirContext, rd: Reg, rn: Reg) -> Self {
let kind = MirInstKind::MovReg { rd, rn };
let data = MirInstData {
kind,
succ: None,
pre: None,
parent: None,
};
ctx.alloc(data)
}
pub fn uses(self, mctx: &MirContext) -> Vec<Reg> {
match &self.deref(mctx).unwrap().kind {
MirInstKind::Add { rd:_, rn, rm } => vec![*rn, *rm],
MirInstKind::Addi {rd:_, rn, imm:_} | MirInstKind::Subi {rd:_, rn, imm:_} => vec![*rn],
MirInstKind::Ldr { mem, .. } => match mem {
MemLoc::Reg { address} => vec![*address],
MemLoc::RegOffset { base, .. } => vec![*base],
MemLoc::Reg2Offset { base, offset } => vec![*base, *offset],
}
MirInstKind::Str { rm, mem, .. } => {
let mut uses = vec![*rm];
match mem {
MemLoc::Reg { address} => uses.push(*address),
MemLoc::RegOffset { base, .. } => uses.push(*base),
MemLoc::Reg2Offset { base, offset } => {
uses.push(*base);
uses.push(*offset);
},
}
uses
}
MirInstKind::Movk { rd, imm:_ } => vec![*rd],
MirInstKind::MovReg { rd:_, rn } => vec![*rn],
MirInstKind::Movz { .. } => vec![],
MirInstKind::B { .. } => vec![],
MirInstKind::Ret => vec![],
MirInstKind::Adrp { .. } => vec![],
MirInstKind::AddLabel { rn, ..} => vec![*rn],
}
}
pub fn def(self, mctx: &MirContext) -> Vec<Reg> {
match &self.deref(mctx).unwrap().kind {
MirInstKind::Add { rd, rn:_, rm:_ } => vec![*rd],
MirInstKind::Addi {rd, rn:_, imm:_} | MirInstKind::Subi {rd, rn:_, imm:_} => vec![*rd],
MirInstKind::Ldr { rd, .. } => vec![*rd],
MirInstKind::Str { .. } => vec![],
MirInstKind::Movz { rd, imm:_ } => vec![*rd],
MirInstKind::Movk { rd, imm:_ } => vec![*rd],
MirInstKind::MovReg { rd, rn:_ } => vec![*rd],
MirInstKind::B { ..} => vec![],
MirInstKind::Ret => vec![],
MirInstKind::Adrp { rd, .. } => vec![*rd],
MirInstKind::AddLabel{ rd, .. } => vec![*rd],
}
}
pub fn all_regs(self, mctx: &MirContext) -> Vec<Reg> {
match &self.deref(mctx).unwrap().kind {
MirInstKind::Add { rd, rn, rm } => vec![*rd, *rn, *rm],
MirInstKind::Addi {rd, rn, imm:_} | MirInstKind::Subi {rd, rn, imm:_}=> vec![*rd,*rn],
MirInstKind::Ldr { rd, mem } => match mem {
MemLoc::Reg { address } => vec![*rd, *address],
MemLoc::RegOffset { base, .. } => vec![*rd, *base],
MemLoc::Reg2Offset { base, offset } => vec![*rd, *base, *offset],
}
MirInstKind::Str { rm, mem } => {
let mut regs = vec![*rm];
match mem {
MemLoc::Reg { address } => regs.push(*address),
MemLoc::RegOffset { base, .. } => regs.push(*base),
MemLoc::Reg2Offset { base, offset } => {
regs.push(*base);
regs.push(*offset);
},
}
regs
}
MirInstKind::Movz { rd, .. } => vec![*rd],
MirInstKind::Movk { rd, .. } => vec![*rd],
MirInstKind::MovReg { rd, rn } => vec![*rd, *rn],
MirInstKind::B { .. } => vec![],
MirInstKind::Ret => vec![],
MirInstKind::Adrp { rd, .. } => vec![*rd],
MirInstKind::AddLabel { rd, rn, .. } => vec![*rd, *rn],
}
}
pub fn replace_regs(self, mctx: &mut MirContext, from: Reg, to: Reg) {
match &mut self.deref_mut(mctx).unwrap().kind {
MirInstKind::Ldr { rd, mem } => {
if *rd == from {
*rd = to;
}
match mem {
MemLoc::Reg { address } => {
if *address == from {
*address = to;
}
}
MemLoc::RegOffset { base, .. } => {
if *base == from {
*base = to;
}
}
MemLoc::Reg2Offset { base, offset } => {
if *base == from {
*base = to;
}
if *offset == from {
*offset = to;
}
}
}
}
MirInstKind::Str { rm, mem } => {
if *rm == from {
*rm = to;
}
match mem {
MemLoc::Reg { address } => {
if *address == from {
*address = to;
}
}
MemLoc::RegOffset { base, .. } => {
if *base == from {
*base = to;
}
}
MemLoc::Reg2Offset { base, offset } => {
if *base == from {
*base = to;
}
if *offset == from {
*offset = to;
}
}
}
}
MirInstKind::Movz { rd, .. } => {
if *rd == from {
*rd = to;
}
}
MirInstKind::Movk { rd, .. } => {
if *rd == from {
*rd = to;
}
}
MirInstKind::MovReg { rd, rn } => {
if *rd == from {
*rd = to;
}
if *rn == from {
*rn = to;
}
}
MirInstKind::Add { rd, rn, rm } => {
if *rd == from {
*rd = to;
}
if *rn == from {
*rn = to;
}
if *rm == from {
*rm = to;
}
}
MirInstKind::Addi {rd, rn, imm:_} | MirInstKind::Subi {rd, rn, imm:_}=> {
if *rd == from {
*rd = to;
}
if *rn == from {
*rn = to;
}
}
MirInstKind::B { .. } => {},
MirInstKind::Ret => {},
MirInstKind::Adrp { rd, .. } => {
if *rd == from {
*rd = to;
}
}
MirInstKind::AddLabel { rd, rn, ..} => {
if *rd == from {
*rd = to;
}
if *rn == from {
*rn = to;
}
}
}
}
}
impl MirInst {
pub fn kind(self, ctx: &MirContext) -> &MirInstKind {
&self.deref(ctx).expect("Invalid Inst").kind
}
pub fn kind_mut(self, ctx: &mut MirContext) -> &mut MirInstKind {
&mut self.deref_mut(ctx).expect("Invalid Inst").kind
}
pub fn is_br(self, ctx: &MirContext) -> bool {
match self.kind(ctx) {
MirInstKind::B { .. } => true,
_ => false,
}
}
pub fn is_ret(self, ctx: &MirContext) -> bool {
match self.kind(ctx) {
MirInstKind::Ret { .. } => true,
_ => false,
}
}
pub fn is_branch(self, ctx: &MirContext) -> bool {
match self.kind(ctx) {
MirInstKind::B { .. } | // 无条件分支
MirInstKind::Ret { .. } => true,
_ => false,
}
}
pub fn is_load(self, ctx: &MirContext) -> bool {
match self.kind(ctx) {
MirInstKind::Ldr { .. } => true,
_ => false,
}
}
pub fn is_store(self, ctx: &MirContext) -> bool {
match self.kind(ctx) {
MirInstKind::Str { .. } => true,
_ => false,
}
}
pub fn is_memory(self, ctx: &MirContext) -> bool {
return self.is_load(ctx) || self.is_store(ctx);
}
}
impl ArenaPtr for MirInst {
type Arena = MirContext;
type Data = MirInstData;
}
impl LinkedListNode for MirInst {
type Container = MirBlock;
type Ctx = MirContext;
fn succ(self, ctx: &Self::Ctx) -> Option<Self> { self.deref(ctx).expect("Invalid Inst").succ }
fn pre(self, ctx: &Self::Ctx) -> Option<Self> { self.deref(ctx).expect("Invalid Inst").pre }
fn set_succ(self, arena: &mut Self::Ctx, succ: Option<Self>) {
self.deref_mut(arena).expect("Invalid Inst").succ = succ;
}
fn set_pre(self, arena: &mut Self::Ctx, pre: Option<Self>) {
self.deref_mut(arena).expect("Invalid Inst").pre = pre;
}
fn container(self, ctx: &Self::Ctx) -> Option<Self::Container> { self.deref(ctx).expect("Invalid Inst").parent }
fn set_container(self, arena: &mut Self::Ctx, parent: Option<Self::Container>) {
self.deref_mut(arena).expect("Invalid Inst").parent = parent;
}
fn insert_after(self, ctx: &mut Self::Ctx, node: Self) -> Result<(), LinkedListError<Self>> {
if self.container(ctx).is_none() {
return Err(LinkedListError::CurrentNodeNotLinked(self));
}
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(succ) = self.succ(ctx) {
succ.set_pre(ctx, Some(node));
node.set_succ(ctx, Some(succ));
}
node.set_pre(ctx, Some(self));
self.set_succ(ctx, Some(node));
match self.container(ctx) {
Some(container) => {
if container.tail(ctx) == Some(self) {
container.set_tail(ctx, Some(node));
}
}
None => unreachable!(),
}
node.set_container(ctx, self.container(ctx));
Ok(())
}
fn insert_before(self, ctx: &mut Self::Ctx, node: Self) -> Result<(), LinkedListError<Self>> {
if self.container(ctx).is_none() {
return Err(LinkedListError::CurrentNodeNotLinked(self));
}
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(pre) = self.pre(ctx) {
pre.set_succ(ctx, Some(node));
node.set_pre(ctx, Some(pre));
}
node.set_succ(ctx, Some(self));
self.set_pre(ctx, Some(node));
match self.container(ctx) {
Some(container) => {
if container.head(ctx) == Some(self) {
container.set_head(ctx, Some(node));
}
}
None => unreachable!(),
}
node.set_container(ctx, self.container(ctx));
Ok(())
}
}

@ -0,0 +1,29 @@
use std::hash::Hash;
#[derive(Debug, Clone)]
pub struct MirLabel( pub String);
impl MirLabel {
pub fn new(name: String) -> Self { Self(name) }
}
impl PartialEq for MirLabel {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for MirLabel {}
impl Hash for MirLabel {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl<T> From<T> for MirLabel
where
T: AsRef<str>,
{
fn from(value: T) -> Self { Self(value.as_ref().to_string()) }
}

@ -0,0 +1,27 @@
use super::regs::Reg;
use crate::frontend::ir;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MirOperandKind {
Mem(MemLoc),
Reg(Reg),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MirOperand {
pub(crate) typ: ir::typ::Typ,
pub(crate) kind: MirOperandKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemLoc {
/// 地址在寄存器
Reg { address: Reg },
/// 基地址在寄存器,偏移位立即数
RegOffset { base: Reg, offset: i32 },
/// 基地址和偏移位都在寄存器(全局数组)
Reg2Offset { base: Reg, offset: Reg },
}

@ -0,0 +1,7 @@
pub mod regs;
pub mod mir_operand;
pub mod mir_block;
pub mod mir_context;
pub mod mir_label;
pub mod mir_function;
pub mod mir_inst;

@ -0,0 +1,232 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RegKind {
Integer,
Address,
}
#[derive(Debug, Clone, Copy, )]
pub enum Reg {
P(PReg),
V(VReg),
}
impl Reg {
pub fn kind(&self) -> RegKind {
match self {
Reg::P(preg) => preg.kind(),
Reg::V(vreg) => vreg.kind(),
}
}
pub fn is_preg(&self) -> bool { matches!(self, Reg::P(_)) }
pub fn preg_num(&self) -> u8 {
match self {
Reg::P(preg) => preg.0,
Reg::V(vreg) => panic!("virtual reg {} has no preg_num", vreg.0),
}
}
pub fn is_vreg(&self) -> bool { matches!(self, Reg::V(_)) }
pub fn is_address(&self) -> bool {
match self {
Reg::P(preg) => preg.kind() == RegKind::Address,
Reg::V(vreg) => vreg.kind() == RegKind::Address,
}
}
pub fn is_caller_saved(&self) -> bool {
match self {
Reg::P(preg) => {
preg.is_callee_saved()
}
Reg::V(_) => false,
}
}
}
// 手动实现PartialEq和Eq
impl PartialEq for Reg {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
// 两个物理寄存器比较
(Reg::P(a), Reg::P(b)) => {
// 判断是否属于同一寄存器文件
match (a.kind(), b.kind()) {
// 通用寄存器文件Integer和Address共享
(RegKind::Integer, RegKind::Address)
| (RegKind::Address, RegKind::Integer)
| (RegKind::Integer, RegKind::Integer)
| (RegKind::Address, RegKind::Address) => a.0 == b.0,
// 不同寄存器文件(通用 vs 浮点)
_ => false,
}
}
// 两个虚拟寄存器比较:仅需编号相同
(Reg::V(a), Reg::V(b)) => a.0 == b.0,
// 其他情况物理vs虚拟不相等
_ => false,
}
}
}
// 手动实现Hash以保持与PartialEq一致
impl std::hash::Hash for Reg {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
Reg::P(p) => {
// 通用寄存器Integer/Address和浮点寄存器使用不同的哈希域
let domain = match p.kind() {
RegKind::Integer | RegKind::Address => 0u8,
};
domain.hash(state);
p.0.hash(state);
}
Reg::V(v) => {
// 虚拟寄存器单独哈希域
2u8.hash(state);
v.0.hash(state);
}
}
}
}
impl Eq for Reg {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct PReg(pub u8, pub RegKind);
impl PReg {
pub const fn new(num: u8, kind: RegKind) -> Self { Self(num, kind) }
pub const fn num(&self) -> u8 { self.0 }
pub const fn kind(&self) -> RegKind { self.1 }
pub const fn is_integer(&self) -> bool {
match self.1 {
RegKind::Integer => true,
_ => false,
}
}
pub const fn is_address(&self) -> bool {
match self.1 {
RegKind::Address => true,
_ => false,
}
}
pub fn hw_index(&self) -> u8 { self.0}
pub fn is_callee_saved(&self) -> bool { CALLEE_SAVED_REGS.contains(self) }
pub fn is_caller_saved(&self) -> bool { CALLER_SAVED_REGS.contains(self) }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct VReg(pub u32, pub RegKind);
impl VReg {
pub fn new(num: u32, kind: RegKind) -> Self { Self(num, kind) }
pub fn num(&self) -> u32 { self.0 }
pub fn kind(&self) -> RegKind { self.1 }
}
impl From<VReg> for Reg {
fn from(vreg: VReg) -> Self { Self::V(vreg) }
}
impl From<PReg> for Reg {
fn from(preg: PReg) -> Self { Self::P(preg) }
}
#[rustfmt::skip]
// ARMV8-A64地址寄存器
pub const fn x_reg(index: u8) -> PReg { PReg::new(index, RegKind::Address) }
pub const fn x0() -> PReg { PReg::new(0, RegKind::Address) }
pub const fn x1() -> PReg { PReg::new(1, RegKind::Address) }
pub const fn x2() -> PReg { PReg::new(2, RegKind::Address) }
pub const fn x3() -> PReg { PReg::new(3, RegKind::Address) }
pub const fn x4() -> PReg { PReg::new(4, RegKind::Address) }
pub const fn x5() -> PReg { PReg::new(5, RegKind::Address) }
pub const fn x6() -> PReg { PReg::new(6, RegKind::Address) }
pub const fn x7() -> PReg { PReg::new(7, RegKind::Address) }
pub const fn x8() -> PReg { PReg::new(8, RegKind::Address) }
pub const fn x9() -> PReg { PReg::new(9, RegKind::Address) }
pub const fn x10() -> PReg { PReg::new(10, RegKind::Address) }
pub const fn x11() -> PReg { PReg::new(11, RegKind::Address) }
pub const fn x12() -> PReg { PReg::new(12, RegKind::Address) }
pub const fn x13() -> PReg { PReg::new(13, RegKind::Address) }
pub const fn x14() -> PReg { PReg::new(14, RegKind::Address) }
pub const fn x15() -> PReg { PReg::new(15, RegKind::Address) }
pub const fn x16() -> PReg { PReg::new(16, RegKind::Address) }
pub const fn x17() -> PReg { PReg::new(17, RegKind::Address) }
pub const fn x18() -> PReg { PReg::new(18, RegKind::Address) }
pub const fn x19() -> PReg { PReg::new(19, RegKind::Address) }
pub const fn x20() -> PReg { PReg::new(20, RegKind::Address) }
pub const fn x21() -> PReg { PReg::new(21, RegKind::Address) }
pub const fn x22() -> PReg { PReg::new(22, RegKind::Address) }
pub const fn x23() -> PReg { PReg::new(23, RegKind::Address) }
pub const fn x24() -> PReg { PReg::new(24, RegKind::Address) }
pub const fn x25() -> PReg { PReg::new(25, RegKind::Address) }
pub const fn x26() -> PReg { PReg::new(26, RegKind::Address) }
pub const fn x27() -> PReg { PReg::new(27, RegKind::Address) }
pub const fn x28() -> PReg { PReg::new(28, RegKind::Address) }
pub const fn fp() -> PReg { PReg::new(29, RegKind::Address) }
pub const fn x30() -> PReg { PReg::new(30, RegKind::Address) }
pub const fn sp() -> PReg { PReg::new(31, RegKind::Address) }
pub const fn xzr() -> PReg { PReg::new(32, RegKind::Address) }
pub const fn bzw() -> PReg { PReg::new(33, RegKind::Integer)}
// ARMV8-A64整数寄存器
pub const fn w_reg(index: u8) -> PReg { PReg::new(index, RegKind::Integer) }
pub const fn w0() -> PReg { PReg::new(0, RegKind::Integer) }
pub const fn w1() -> PReg { PReg::new(1, RegKind::Integer) }
pub const fn w2() -> PReg { PReg::new(2, RegKind::Integer) }
pub const fn w3() -> PReg { PReg::new(3, RegKind::Integer) }
pub const fn w4() -> PReg { PReg::new(4, RegKind::Integer) }
pub const fn w5() -> PReg { PReg::new(5, RegKind::Integer) }
pub const fn w6() -> PReg { PReg::new(6, RegKind::Integer) }
pub const fn w7() -> PReg { PReg::new(7, RegKind::Integer) }
pub const fn w8() -> PReg { PReg::new(8, RegKind::Integer) }
pub const fn w9() -> PReg { PReg::new(9, RegKind::Integer) }
pub const fn w10() -> PReg { PReg::new(10, RegKind::Integer) }
pub const fn w11() -> PReg { PReg::new(11, RegKind::Integer) }
pub const fn w12() -> PReg { PReg::new(12, RegKind::Integer) }
pub const fn w13() -> PReg { PReg::new(13, RegKind::Integer) }
pub const fn w14() -> PReg { PReg::new(14, RegKind::Integer) }
pub const fn w15() -> PReg { PReg::new(15, RegKind::Integer) }
pub const fn w16() -> PReg { PReg::new(16, RegKind::Integer) }
pub const fn w17() -> PReg { PReg::new(17, RegKind::Integer) }
pub const fn w18() -> PReg { PReg::new(18, RegKind::Integer) }
pub const fn w19() -> PReg { PReg::new(19, RegKind::Integer) }
pub const fn w20() -> PReg { PReg::new(20, RegKind::Integer) }
pub const fn w21() -> PReg { PReg::new(21, RegKind::Integer) }
pub const fn w22() -> PReg { PReg::new(22, RegKind::Integer) }
pub const fn w23() -> PReg { PReg::new(23, RegKind::Integer) }
pub const fn w24() -> PReg { PReg::new(24, RegKind::Integer) }
pub const fn w25() -> PReg { PReg::new(25, RegKind::Integer) }
pub const fn w26() -> PReg { PReg::new(26, RegKind::Integer) }
pub const fn w27() -> PReg { PReg::new(27, RegKind::Integer) }
pub const fn w28() -> PReg { PReg::new(28, RegKind::Integer) }
pub const fn w29() -> PReg { PReg::new(29, RegKind::Integer) }
pub const fn w30() -> PReg { PReg::new(30, RegKind::Integer) }
pub const fn w31() -> PReg { PReg::new(31, RegKind::Integer) }
pub const fn wzr() -> PReg { PReg::new(32, RegKind::Integer) }
pub const CALLER_SAVED_REGS: [PReg; 18] = [
w9(), w10(), w11(), w12(), w13(), w14(), w15(), w16(), w17(),
x9(), x10(), x11(), x12(), x13(), x14(), x15(), x16(), x17()
];
pub const CALLEE_SAVED_REGS: [PReg; 20] = [
w19(), w20(), w21(), w22(), w23(), w24(), w25(), w26(), w27(), w28(),
x19(), x20(), x21(), x22(), x23(), x24(), x25(), x26(), x27(), x28(),
];
pub const INT_ARG_REGS: [PReg; 16] = [
w0(), w1(), w2(), w3(), w4(), w5(), w6(), w7(),
x0(), x1(), x2(), x3(), x4(), x5(), x6(), x7()
];

@ -0,0 +1,722 @@
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
use super::mir::{
mir_block::MirBlock,
mir_context::{MirContext,RawData},
mir_function::MirFunction,
mir_inst::{MirInst},
mir_label::MirLabel,
mir_operand::{MirOperand, MirOperandKind, MemLoc},
regs::{self, Reg, PReg},
};
use crate::{
frontend::ir::{
self, basicblock::BasicBlock,function::Function, global::GlobalData, instruction::{InstructionKind, MemAccessOp}, value::{ConstantValue, Value}
}, utils::{
linked_list::{LinkedListContainer},
storage::ArenaPtr,
}
};
pub struct MirgenContext<'s> {
pub(super) mctx: MirContext,
pub(super) ctx: &'s ir::context::Context,
pub(super) table: HashMap<Value, MirOperand>,
pub funcs: HashMap<String, MirFunction>,
pub blocks: HashMap<BasicBlock, MirBlock>,
pub globals: HashMap<String, MirLabel>,
pub(super) curr_func: Option<MirFunction>,
pub(super) curr_block: Option<MirBlock>,
pub func_map: HashMap<MirFunction, Function>,
pub release: HashSet<Value>,
pub curr_cond: Option<(Value, InstructionKind)>,
}
pub trait MirGen {
fn mirgen(&self, mirgen: &mut MirgenContext);
}
impl MirGen for GlobalData {
fn mirgen(&self, mirgen: &mut MirgenContext) {
let global = self.self_ptr;
let name = global.name(mirgen.ctx).to_string();
let label_name = name.trim_start_matches('@').to_string();
let label = MirLabel::from(label_name.clone());
mirgen.globals.insert(name.clone(), label.clone());
match global.value(mirgen.ctx) {
ConstantValue::Int32 { value, .. } => {
let new_label = MirLabel::from(label_name.clone());
mirgen.mctx.add_raw_data(new_label, RawData::Bytes(vec![*value], 4));
}
ConstantValue::Zero {typ} | ConstantValue::Undef { typ }=> {
let size = typ.bytewidth(mirgen.ctx);
mirgen.mctx.add_raw_data(label.clone(), RawData::Bss(size));
}
ConstantValue::GlobalPtr { name: global_name, .. } => {
mirgen.globals.insert(global_name.clone(), MirLabel::from(global_name));
}
}
}
}
impl MirGen for ir::function::Function {
fn mirgen(&self, mirgen: &mut MirgenContext) {
let name = self.get_id(mirgen.ctx);
let label = MirLabel::from(name.clone());
let mfunc = MirFunction::new(&mut mirgen.mctx, label,false);
mirgen.curr_func = Some(mfunc);
mirgen.funcs.insert(name, mfunc);
mirgen.func_map.insert(mfunc, *self);
// 生成用户函数的基本快
for block in self.iter(mirgen.ctx) {
block.mirgen(mirgen);
}
for (i, &param_val) in self.get_parameters(mirgen.ctx).iter().take(8).enumerate() {
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
let preg = mirgen.generate_param_reg(param_val, i as u32);
let mov = MirInst::mov_reg(&mut mirgen.mctx, new_reg, preg);
let _ = mfunc.head(&mirgen.mctx).unwrap().push_back(&mut mirgen.mctx, mov);
let mem_loc = MirOperandKind::Reg(new_reg);
mirgen.table.insert(param_val, MirOperand {
typ: param_val.kind(mirgen.ctx),
kind: mem_loc,
});
}
}
}
impl MirGen for ir::basicblock::BasicBlock {
fn mirgen(&self, mirgen: &mut MirgenContext) {
let name = self.get_name();
let label = MirLabel::from(name.clone());
let mblock = MirBlock::new(&mut mirgen.mctx, label);
mirgen.curr_block = Some(mblock);
let _ = mirgen.curr_func.as_ref().unwrap().push_back(&mut mirgen.mctx, mblock);
mirgen.blocks.insert(*self, mblock);
}
}
impl MirGen for ir::instruction::Instruction {
fn mirgen(&self, mirgen: &mut MirgenContext) {
match self.get_kind(mirgen.ctx) {
ir::instruction::InstructionKind::Terminator { op } => {
match op {
ir::instruction::TerminatorOp::Br => {
let target = self.get_operand_bbk(mirgen.ctx,0).expect("Br instruction must have a target basic block");
let b = MirInst::b(&mut mirgen.mctx, mirgen.blocks[&target]);
let _ =mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, b);
},
ir::instruction::TerminatorOp::Ret => {
if self.get_operands(mirgen.ctx).len() != 0 {
let val = self.get_operand(mirgen.ctx, 0);
if let Some(val) = val {
mirgen.gen_ret_move(val);
}
} else {
}
},
_ => todo!(),
}
}
ir::instruction::InstructionKind::Binary { op } => {
let result_val = self.get_result(mirgen.ctx).unwrap();
let lhs = self.get_operand(mirgen.ctx, 0).unwrap();
let rhs = self.get_operand(mirgen.ctx, 1).unwrap();
// 创建目标寄存器
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
if !lhs.is_constant(mirgen.ctx) && !rhs.is_constant(mirgen.ctx) {
// 获取左操作数寄存器
let lhs_reg = mirgen.generate_opd_reg(lhs);
// 获取右操作数寄存器
let rhs_reg = mirgen.generate_opd_reg(rhs);
match op {
ir::instruction::BinaryOp::Add => {
// 生成加法指令
let add = MirInst::add(&mut mirgen.mctx, temp_reg, lhs_reg, rhs_reg);
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add);
}
_ => todo!("Unsupported binary operation: {:?}", op),
}
} else if !lhs.is_constant(mirgen.ctx) && rhs.is_constant(mirgen.ctx) {
// 获取左操作数寄存器
let lhs_reg = mirgen.generate_opd_reg(lhs);
// 处理常量右操作数
if let ir::value::ValueKind::Constant { value } = &rhs.deref(mirgen.ctx).unwrap().kind {
if let ConstantValue::Int32 { value, .. } = value {
match op {
ir::instruction::BinaryOp::Add => {
// 生成加法指令
if *value > 4095 || *value < -4096{
// let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
mirgen.generate_movimm(temp_reg, *value);
let add = MirInst::add(&mut mirgen.mctx, temp_reg, lhs_reg,temp_reg);
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add);
} else{
let addi = MirInst::addi(&mut mirgen.mctx, temp_reg, lhs_reg, *value as i32);
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, addi);
}
},
_ => todo!("Unsupported binary operation: {:?}", op),
}
} else {
panic!("Expected int32 onstant for right operand");
}
} else {
todo!();
}
} else if lhs.is_constant(mirgen.ctx) && rhs.is_constant(mirgen.ctx) {
if lhs.kind(mirgen.ctx).is_int32(mirgen.ctx){
let l_value;
let r_value;
let imm: i32;
if let ir::value::ValueKind::Constant { value } = &lhs.deref(mirgen.ctx).unwrap().kind {
if let ConstantValue::Int32 { value, .. } = value {
l_value = *value;
} else {
panic!("Expected int32 constant for left operand");
}
} else {
panic!("Expected int32 constant for left operand");
}
if let ir::value::ValueKind::Constant { value } = &rhs.deref(mirgen.ctx).unwrap().kind {
if let ConstantValue::Int32 { value, .. } = value {
r_value = *value;
} else {
panic!("Expected int32 constant for left operand");
}
} else {
panic!("Expected int32 constant for left operand");
}
match op {
ir::instruction::BinaryOp::Add => imm = l_value + r_value,
_ => todo!("Unsupported binary operation: {:?}", op),
}
mirgen.generate_movimm(temp_reg, imm);
} else {
panic!("Expected i32 constant for left operand");
}
} else {
// 获取右操作数寄存器
let rhs_reg = mirgen.generate_opd_reg(rhs);
// 处理常量左操作数
if let ir::value::ValueKind::Constant { value } = &lhs.deref(mirgen.ctx).unwrap().kind {
if let ConstantValue::Int32 { value, .. } = value {
match op {
ir::instruction::BinaryOp::Add => {
// 生成加法指令
if *value > 4095 || *value < -4096 {
mirgen.generate_movimm(temp_reg, *value);
let add = MirInst::add(&mut mirgen.mctx, temp_reg, temp_reg,rhs_reg);
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add);
} else {
let addi = MirInst::addi(&mut mirgen.mctx, temp_reg, rhs_reg, *value);
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, addi);
}
}
_ => todo!("Unsupported binary operation: {:?}", op),
}
} else {
panic!("Unsupported constant type: {:?}", value);
}
} else {
panic!("Expected int32 constant for left operand");
}
}
// 记录结果
mirgen.table.insert(result_val, MirOperand {
typ: result_val.kind(mirgen.ctx),
kind: MirOperandKind::Reg(temp_reg),
});
}
ir::instruction::InstructionKind::MemAccess { op } => {
match op {
MemAccessOp::Alloca { typ } => {
// 在栈上分配空间
let mut size = typ.bitwidth(mirgen.ctx);
size = (size + 7) / 8;
let current_offset = mirgen.curr_func.unwrap().current_stack_size(&mirgen.mctx);
let _ = mirgen.curr_func.unwrap().add_current_stack_size(&mut mirgen.mctx, size as i32);
let total_stack = mirgen.curr_func.unwrap().calleeargs_stack_size(&mirgen.mctx);
// 非数组值用地址偏移
let mem_loc = MemLoc::RegOffset { base: regs::sp().into(), offset: total_stack+current_offset };
let mopd = MirOperand {
typ,
kind: MirOperandKind::Mem(mem_loc),
};
mirgen.table.insert(self.get_result(mirgen.ctx).unwrap(), mopd);
}
MemAccessOp::Store => {
let val = self.get_operand(mirgen.ctx, 0).unwrap();
let ptr = self.get_operand(mirgen.ctx, 1).unwrap();
// 检查是否是全局变量
let is_global_ptr =
if let ir::value::ValueKind::Constant { value} = &ptr.deref(mirgen.ctx).unwrap().kind {
matches!(value, ConstantValue::GlobalPtr { .. })
}
else {
false
};
let mem_loc = if is_global_ptr {
// 提取全局变量名称
let name =
if let ir::value::ValueKind::Constant {
value: ConstantValue::GlobalPtr { name, .. }
} = &ptr.deref(mirgen.ctx).unwrap().kind {name.clone()}
else {
unreachable!()
};
let label = mirgen.globals[&name].clone();
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
// 生成加载全局地址的指令
mirgen.generate_adrp(temp_reg, label);
// 生成加载实际值的指令
let mem = MemLoc::RegOffset { base: temp_reg, offset: 0 };
mem
}else {
// 处理局部变量存储
let mem = match mirgen.table[&ptr].kind {
MirOperandKind::Mem(m) => m,
_ => unreachable!(),
};
mem
};
match &val.deref(mirgen.ctx).unwrap().kind {
ir::value::ValueKind::Constant { value } => {
let zero_reg = regs::wzr().into();
match value {
ConstantValue::Int32 { value, .. } => {
// 使用零寄存器或加载立即数
if *value == 0 {
mirgen.generate_str(zero_reg, mem_loc);
} else {
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
mirgen.generate_movimm(new_reg, *value as i32);
mirgen.generate_str(new_reg, mem_loc);
}
}
ConstantValue::Undef{typ:_} => {
}
ConstantValue::Zero { typ:_ }=> {
mirgen.generate_str(zero_reg, mem_loc);
}
_ => todo!(),
}
}
ir::value::ValueKind::InstResult { ..} => {
let mopd = mirgen.table[&val];
match mopd.kind {
MirOperandKind::Reg(reg) => {
mirgen.generate_str(reg, mem_loc);
}
MirOperandKind::Mem(MemLoc::Reg { address }) => {
mirgen.generate_str(address, mem_loc);
}
MirOperandKind::Mem(MemLoc::RegOffset { base, offset }) => {
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
if offset > 4095 || offset < -4096 {
mirgen.generate_movimm(new_reg, offset);
let add = MirInst::add(&mut mirgen.mctx, new_reg, base, new_reg);
mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add).unwrap();
} else {
let add = MirInst::addi(&mut mirgen.mctx, new_reg, base, offset);
mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add).unwrap();
}
let mem_loc = MemLoc::Reg { address: new_reg };
mirgen.generate_str(new_reg, mem_loc);
mirgen.table.insert(val, MirOperand {
typ: val.kind(mirgen.ctx),
kind: MirOperandKind::Mem(mem_loc),
});
mirgen.release.insert(val);
}
MirOperandKind::Mem(MemLoc::Reg2Offset { base, offset }) => {
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
let add = MirInst::add(&mut mirgen.mctx, new_reg, base, offset);
mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add).unwrap();
mirgen.generate_str(new_reg, mem_loc);
let mem_loc = MemLoc::Reg { address: new_reg };
mirgen.table.insert(val, MirOperand {
typ: val.kind(mirgen.ctx),
kind: MirOperandKind::Mem(mem_loc),
});
mirgen.release.insert(val);
}
}
}
ir::value::ValueKind::Parameter { function:_, index, typ:_ }=>{
if mirgen.table.get(&val).is_some() {
let arg_reg = match mirgen.table[&val].kind {
MirOperandKind::Reg(reg) => reg,
MirOperandKind::Mem(MemLoc::Reg { address }) => address,
_ => todo!(),
};
mirgen.generate_str(arg_reg, mem_loc);
} else {
if *index < 8 {
panic!("Unreachable")
} else {
// 大于八个的参数在栈上通过fp获取
let argadress_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
mirgen.generate_ldr(argadress_reg, MemLoc::RegOffset { base: regs::fp().into(), offset: ((*index - 8) * 8) as i32 });
mirgen.generate_str(argadress_reg, mem_loc);
let mem_loc = MirOperandKind::Reg(argadress_reg);
mirgen.table.insert(val, MirOperand {
typ: val.kind(mirgen.ctx),
kind: mem_loc,
});
mirgen.release.insert(val);
}
}
}
_ => todo!()
}
}
MemAccessOp::Load => {
let ptr_val = self.get_operand(mirgen.ctx, 0).unwrap();
let result_val = self.get_result(mirgen.ctx).unwrap();
// 检查是否是全局变量
let is_global_ptr =
if let ir::value::ValueKind::Constant { value} = &ptr_val.deref(mirgen.ctx).unwrap().kind {
matches!(value, ConstantValue::GlobalPtr { .. })
}
else {
false
};
let mem_loc = if is_global_ptr {
// 提取全局变量名称
let name =
if let ir::value::ValueKind::Constant {
value: ConstantValue::GlobalPtr { name, .. }
} = &ptr_val.deref(mirgen.ctx).unwrap().kind {name.clone()}
else {
unreachable!()
};
// 处理全局变量加载
let label = mirgen.globals[&name].clone();
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
// 生成加载全局地址的指令
mirgen.generate_adrp(temp_reg, label);
// 生成加载实际值的指令
let mem = MemLoc::RegOffset { base: temp_reg, offset: 0 };
mem
} else {
let mem = match mirgen.table[&ptr_val].kind {
MirOperandKind::Mem(m) => m,
_ => unreachable!(),
};
mem
};
// let size = (result_val.kind(mirgen.ctx).bitwidth(mirgen.ctx) + 7) / 8;
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into()
;
mirgen.generate_ldr(temp_reg, mem_loc);
// 记录结果
let mem_loc = MirOperandKind::Reg(temp_reg);
mirgen.table.insert(result_val, MirOperand {
typ: result_val.kind(mirgen.ctx),
kind: mem_loc,
});
}
}
}
}
}
}
/*
*
*
* --------------------------------------------------- <----- fpsp
* (callee_saved_registers
* ---------------------------------------------------
* (caller_saved_registers)
* ---------------------------------------------------
* (spill)
* ---------------------------------------------------
* (Alloca)
* ---------------------------------------------------
*
* --------------------------------------------------- <----- sp
*/
impl<'s> MirgenContext<'s> {
pub fn new(ctx: &'s ir::context::Context) -> Self {
Self {
mctx: MirContext::default(),
ctx,
table: HashMap::default(),
funcs: HashMap::default(),
blocks: HashMap::default(),
globals: HashMap::default(),
curr_func: None,
curr_block: None,
func_map: HashMap::default(),
release: HashSet::default(),
curr_cond: None,
}
}
pub fn mircontext(self) -> MirContext { self.mctx }
pub fn mirgen(&mut self) {
// 处理全局变量
for global_data in self.ctx.globals.iter() {
global_data.mirgen(self);
}
for func in self.ctx.get_functions() {
//println!("Translating function: {}", func.get_id(self.ctx));
func.mirgen(self);
}
// 翻译指令
for func in self.ctx.get_functions() {
self.curr_func = Some(self.funcs[&func.get_id(self.ctx)]);
let mut stack_size = 0;
// 计算函数局部变量栈空间Alloca指令
for block in func.iter(self.ctx) {
self.curr_block = Some(self.blocks[&block]);
for inst in block.iter(self.ctx) {
if let ir::instruction::InstructionKind::MemAccess { op: MemAccessOp::Alloca { typ } } = inst.get_kind(self.ctx) {
stack_size += typ.bitwidth(self.ctx);
}
}
}
stack_size = (stack_size + 7) / 8;
// 调用者保护临时寄存器空间x9-x15
self.curr_func.unwrap().add_storage_stack_size(&mut self.mctx, stack_size as i32);
// 计算函数内部给被调用函数分配的参数空间
let mut callee_stack = 0;
for block in func.iter(self.ctx) {
self.curr_block = Some(self.blocks[&block]);
}
callee_stack = callee_stack*8;
self.curr_func.unwrap().add_calleeargs_stack_size(&mut self.mctx, callee_stack as i32);
let mut blocks = vec![]; //TODO!
for func in self.ctx.get_functions(){
for bbk in func.iter(self.ctx){
blocks.push(bbk.clone());
}
}
for block in blocks {
self.curr_cond = None;
self.curr_block = Some(self.blocks[&block]);
for inst in block.iter(self.ctx) {
inst.mirgen(self);
}
let mut temp_table = HashMap::default();
for (val, opd) in self.table.iter() {
if self.release.contains(val){
continue;
} else {
temp_table.insert(*val, *opd);
}
}
self.release = HashSet::default();
self.table = temp_table;
}
}
}
pub fn gen_ret_move(&mut self, val: Value) {
let curr_block = self.curr_block.unwrap();
let ret_reg = self.generate_ret_reg(val.kind(self.ctx)); // 返回寄存器
match &val.deref(self.ctx).unwrap().kind {
ir::value::ValueKind::Constant { value } => {
match value {
ConstantValue::Int32 { value, .. } => {
// 直接移动到返回寄存器
self.generate_movimm(regs::Reg::P(ret_reg), *value);
}
_ => todo!(),
}
}
ir::value::ValueKind::InstResult { .. } => {
let mopd = self.table[&val];
match mopd.kind {
MirOperandKind::Reg(reg) => {
if reg != regs::Reg::P(ret_reg) {
// 移动值到返回寄存器
let mov = MirInst::mov_reg(&mut self.mctx, regs::Reg::P(ret_reg), reg);
curr_block.push_back(&mut self.mctx, mov).unwrap();
}
}
MirOperandKind::Mem(mem_loc) => {
self.generate_ldr(regs::Reg::P(ret_reg), mem_loc);
}
}
}
ir::value::ValueKind::Parameter { function:_, index, typ }=>{
if *index < 8 {
let arg_reg = match *index {
0 => regs::w0().into(),
1 => regs::w1().into(),
2 => regs::w2().into(),
3 => regs::w3().into(),
4 => regs::w4().into(),
5 => regs::w5().into(),
6 => regs::w6().into(),
7 => regs::w7().into(),
_ => unreachable!(),
};
if typ.is_int32(self.ctx){
let mov = MirInst::mov_reg(&mut self.mctx, regs::Reg::P(ret_reg), arg_reg);
curr_block.push_back(&mut self.mctx, mov).unwrap();
} else {
panic!("Unsupported Type")
}
} else {
let mem_loc = if *index*8 < 4096 {
MemLoc::RegOffset { base: regs::fp().into(), offset: (*index*8) as i32 }
} else {
let new_reg = self.mctx.generate_vreg(regs::RegKind::Integer).into();
self.generate_movimm(new_reg, (*index*8) as i32);
MemLoc::Reg2Offset { base: regs::fp().into(), offset: new_reg }
};
self.generate_ldr(regs::Reg::P(ret_reg), mem_loc);
}
}
_ => todo!(),
}
}
pub fn generate_ret_reg(&mut self, ty: ir::typ::Typ) -> PReg {
if ty.is_ptr(self.ctx) {
regs::x0().into()
} else {
regs::w0().into()
}
}
pub fn generate_param_reg(&mut self, _arg: ir::value::Value, index: u32) -> Reg {
match index {
0 => regs::w0().into(),
1 => regs::w1().into(),
2 => regs::w2().into(),
3 => regs::w3().into(),
4 => regs::w4().into(),
5 => regs::w5().into(),
6 => regs::w6().into(),
7 => regs::w7().into(),
_ => unreachable!()
}
}
pub fn generate_opd_reg(&mut self, opd: ir::value::Value) -> Reg {
if self.table.get(&opd).is_some() {
let v_opd = self.table[&opd];
match v_opd.kind {
MirOperandKind::Reg(reg) => reg,
_ => panic!("Expected register operand for binary op"),
}
} else {
match &opd.deref(self.ctx).unwrap().kind {
ir::value::ValueKind::Parameter{ function:_, index, typ:_ } => {
if *index < 8 {
panic!("Unreachable")
} else {
// 大于八个的参数在栈上通过fp获取
let new_reg = self.mctx.generate_vreg(regs::RegKind::Integer).into();
self.generate_ldr(new_reg, MemLoc::RegOffset { base: regs::fp().into(), offset: ((*index - 8) * 8) as i32 });
let mem_loc = MirOperandKind::Reg(new_reg);
self.table.insert(opd, MirOperand {
typ: opd.kind(self.ctx),
kind: mem_loc,
});
new_reg
}
}
_ => panic!("Expected register operand for binary op")
}
}
}
pub fn generate_movimm(&mut self, rn: Reg, imm: i32) {
let low = imm & 0xFFFF;
let high = (imm >> 16) & 0xFFFF;
let movz = MirInst::movz(&mut self.mctx, rn, low);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, movz);
if high != 0 {
let movk = MirInst::movk(&mut self.mctx, rn, high);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, movk);
}
}
pub fn generate_str(&mut self, rm: Reg, mem_loc: MemLoc) {
match mem_loc {
MemLoc::RegOffset { base, offset } => {
if offset > 255 || offset < -256{
let temp_reg = self.mctx.generate_vreg(regs::RegKind::Integer).into();
self.generate_movimm(temp_reg, offset);
let str = MirInst::str(&mut self.mctx, rm, MemLoc::Reg2Offset { base: base, offset: temp_reg });
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, str);
} else {
let str = MirInst::str(&mut self.mctx, rm, mem_loc);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, str);
}
},
_ => {
let str = MirInst::str(&mut self.mctx, rm, mem_loc);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, str);
}
}
}
pub fn generate_ldr(&mut self, rd: Reg, mem_loc: MemLoc) {
match mem_loc {
MemLoc::RegOffset { base, offset } => {
if offset > 255 || offset < -256{
let temp_reg = self.mctx.generate_vreg(regs::RegKind::Integer).into();
self.generate_movimm(temp_reg, offset);
let ldr = MirInst::ldr(&mut self.mctx, rd, MemLoc::Reg2Offset { base: base, offset: temp_reg});
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, ldr);
} else {
let ldr = MirInst::ldr(&mut self.mctx, rd, mem_loc);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, ldr);
}
}
_ => {
let ldr = MirInst::ldr(&mut self.mctx, rd, mem_loc);
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, ldr);
}
}
}
pub fn generate_adrp(&mut self, rd: Reg, label: MirLabel ) {
let adrp = MirInst::adrp(&mut self.mctx, rd, label.clone());
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, adrp);
let add_label = MirInst::add_label(&mut self.mctx, rd, rd, label.clone());
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, add_label);
}
}
pub fn find_additive_decomposition(n: i32) -> Option<(u32, u32)> {
if n.count_ones() == 2 {
let a = 31 - n.leading_zeros();
let b = n.trailing_zeros();
//println!("n: {} -> {}, {}", n, a, b);
Some((a, b))
} else {
None
}
}

@ -0,0 +1,12 @@
pub mod mir;
pub mod mirgen;
pub mod asm2string;
pub mod regalloc;
pub fn mirgen( ir: &mut crate::frontend::ir::context::Context ) -> mir::mir_context::MirContext{
let mut mirgen_context = mirgen::MirgenContext::new(&ir);
mirgen_context.mirgen();
let mut mctx = mirgen_context.mircontext();
regalloc::naive_alloc::regalloc(&mut mctx);
mctx
}

@ -0,0 +1,228 @@
use std::{array, collections::{HashMap, HashSet}};
use crate::{backend::mir::{
mir_context::MirContext,
mir_function::MirFunction,
mir_inst::MirInst,
mir_operand::MemLoc,
regs::{self, Reg},
}, utils::linked_list::{LinkedListContainer, LinkedListNode}};
pub fn allocate_reg(_mctx: &mut MirContext, _vreg: regs::VReg, candidates: &[regs::PReg], hw_reg_used: &mut [bool]) -> Option<regs::PReg> {
for &preg in candidates {
let index = preg.hw_index() as usize;
if !hw_reg_used[index] {
hw_reg_used[index] = true;
return Some(preg);
}
}
None
}
pub fn regalloc(mctx: &mut MirContext) {
// 硬件寄存器状态(9-15和19-28可以用来分配)
let hw_reg_used: [bool; 29] = array::from_fn(|i| {
!((9..=14).contains(&i) || (19..=28).contains(&i))
});
let integer_candidates = vec![
regs::w19(), regs::w20(), regs::w21(), regs::w22(), regs::w23(), regs::w24(), regs::w25(), regs::w26(), regs::w27(), regs::w28(),
regs::w9(), regs::w10(), regs::w11(), regs::w12(), regs::w13(), regs::w14(), regs::w15(), regs::w16(), regs::w17(),
];
let address_candidates = vec![
regs::x19(), regs::x20(), regs::x21(), regs::x22(), regs::x23(), regs::x24(), regs::x25(), regs::x26(), regs::x27(), regs::x28(),
regs::x9(), regs::x10(), regs::x11(), regs::x12(), regs::x13(), regs::x14(), regs::x15(), regs::x16(), regs::x17(),
];
// 预先收集所有函数的信息
let mut func_info = Vec::new();
for func_data in mctx.funcs.iter() {
let function = func_data.self_ptr();
if function.is_external(mctx) {
continue;
}
let mut all_vregs = HashSet::new();
// 使用不可变借用收集虚拟寄存器
{
for block in function.iter(&mctx) {
for inst in block.iter(&mctx) {
let mut collect_reg = |reg: Reg| {
if let Reg::V(vreg) = reg {
all_vregs.insert(vreg);
}
};
let cur_regs = inst.all_regs(&mctx);
for reg in cur_regs {
collect_reg(reg);
}
}
}
}
func_info.push((function, all_vregs));
}
// 现在使用可变借用来处理每个函数
for (function, all_vregs) in func_info {
let curr_func = Some(function);
let mut reg_map = HashMap::new();
let mut spill_map = HashMap::new();
let mut available_regs = hw_reg_used.clone();
let mut spilled_registers = HashSet::new();
let mut use_count = HashMap::new();
for block in function.iter(mctx) {
for inst in block.iter(mctx) {
for reg in inst.uses(mctx) {
if let Reg::V(vreg) = reg {
*use_count.entry(vreg).or_insert(0) += 1;
}
}
}
}
let mut sorted_vregs: Vec<_> = all_vregs.iter().collect();
// 使用频率降序排除
sorted_vregs.sort_by(|a,b| use_count.get(b).cmp(&use_count.get(a)));
// 分配物理寄存器
for &vreg in &sorted_vregs {
let preg = match vreg.kind() {
regs::RegKind::Integer => allocate_reg(mctx, *vreg, &integer_candidates, &mut available_regs),
regs::RegKind::Address => allocate_reg(mctx, *vreg, &address_candidates, &mut available_regs),
};
if let Some(preg) = preg {
reg_map.insert(vreg, preg);
} else {
spilled_registers.insert(vreg);
}
}
for &reg in &spilled_registers {
let e = match reg.kind() {
regs::RegKind::Integer => 4,
_ => 8
};
let cur_stack = curr_func.unwrap().storage_stack_size(mctx) + curr_func.unwrap().calleeargs_stack_size(mctx);
spill_map.insert(reg, cur_stack);
curr_func.unwrap().add_storage_stack_size(mctx, e);
}
// 处理每条指令的溢出
curr_func.unwrap().add_storage_stack_size(mctx, 19*8+24*4);
let mut curr_block = function.head(mctx);
while let Some(block) = curr_block {
let mut curr_inst = block.head(mctx);
while let Some(inst) = curr_inst {
let next_inst = inst.succ(mctx);
// 处理源操作数(uses)
let mut spill_reg_index = 0;
for reg in inst.uses(mctx) {
if let Reg::V(vreg) = reg {
if let Some(spill_slot) = spill_map.get(&vreg) {
let spill_reg = if spill_reg_index == 0 {
match vreg.kind() {
regs::RegKind::Address => regs::x15().into(),
regs::RegKind::Integer => regs::w15().into(),
}
} else if spill_reg_index == 1{
match vreg.kind() {
regs::RegKind::Address => regs::x16().into(),
regs::RegKind::Integer => regs::w16().into(),
_ => todo!(),
}
} else {
match vreg.kind() {
regs::RegKind::Address => regs::x17().into(),
regs::RegKind::Integer => regs::w17().into(),
_ => todo!(),
}
};
spill_reg_index += 1;
let spill_offset = *spill_slot;
generate_spill_load(
mctx,
spill_reg,
MemLoc::RegOffset { base: regs::sp().into(), offset: spill_offset },
inst
);
// 即使目的操作数也是源操作数
let flag = if inst.def(mctx).contains(&reg) {
true
} else {
false
};
inst.replace_regs(mctx, Reg::V(vreg), spill_reg);
if flag {
generate_spill_store(
mctx,
spill_reg,
MemLoc::RegOffset { base: regs::sp().into(), offset: spill_offset },
inst
);
}
}
}
}
// 处理目标操作数(defs)
for reg in inst.def(mctx) {
if let Reg::V(vreg) = reg {
if let Some(spill_slot) = spill_map.get(&vreg) {
let spill_reg = match vreg.kind() {
regs::RegKind::Address => regs::x15().into(),
regs::RegKind::Integer => regs::w15().into(),
};
let spill_offset = *spill_slot;
inst.replace_regs(mctx, Reg::V(vreg), spill_reg);
generate_spill_store(
mctx,
spill_reg,
MemLoc::RegOffset { base: regs::sp().into(), offset: spill_offset },
inst
);
}
}
}
// 替换非溢出的虚拟寄存器和调整偏移
for reg in inst.all_regs(mctx) {
if let Reg::V(vreg) = reg {
if let Some(allocated_reg) = reg_map.get(&vreg) {
inst.replace_regs(mctx,Reg::V(vreg),(*allocated_reg).into());
}
}
}
curr_inst = next_inst;
}
curr_block = block.succ(mctx);
}
generate_prologue(mctx,curr_func.unwrap());
generate_epilogue(mctx, curr_func.unwrap());
}
}
pub fn generate_spill_load(mctx: &mut MirContext, reg: Reg, mem_loc: MemLoc, inst: MirInst) {
let load = MirInst::ldr(mctx, reg.into(), mem_loc);
let _ = inst.insert_before(mctx, load);
}
pub fn generate_spill_store(mctx: &mut MirContext, reg: Reg, mem_loc: MemLoc, inst: MirInst) {
let store = MirInst::str(mctx, reg.into(), mem_loc);
let _ = inst.insert_after(mctx, store);
}
pub fn generate_prologue(mctx: &mut MirContext, function: MirFunction) {
function.add_callee_reg(mctx, regs::fp().into());
function.add_callee_reg(mctx, regs::x30().into());
let mut stack_size = function.storage_stack_size(mctx) + function.calleeargs_stack_size(mctx) + function.callee_regs(mctx).len() as i32 * 8;
stack_size = (stack_size + 15) & !15;
let sub = MirInst::subi(mctx, regs::sp().into(), regs::sp().into(), stack_size);
function.head(mctx).unwrap().push_front(mctx, sub).unwrap();
}
pub fn generate_epilogue(mctx: &mut MirContext, function: MirFunction) {
let mut stack_size = function.storage_stack_size(mctx) + function.calleeargs_stack_size(mctx) + function.callee_regs(mctx).len() as i32 * 8;
stack_size = (stack_size + 15) & !15;
// let ldp = MirInst::ldp(mctx, regs::fp().into(), regs::x30().into(), MemLoc::RegOffset{base: regs::sp().into(), offset: (stack_size - 16) });
let addi = MirInst::addi(mctx, regs::sp().into(), regs::sp().into(), stack_size );
let ret = MirInst::ret(mctx);
function.tail(mctx).unwrap().push_back(mctx, addi).unwrap();
function.tail(mctx).unwrap().push_back(mctx, ret).unwrap();
}

@ -0,0 +1,214 @@
use super::context::Context;
use super::defuse::{Useable, User};
use super::function::Function;
use super::instruction::Instruction;
use crate::utils::linked_list::{LinkedListContainer, LinkedListNode};
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr, Idx};
use rustc_hash::FxHashSet as HashSet;
pub struct BasicBlockData {
self_ptr: BasicBlock,
// 基本块的首支令和尾指令
head: Option<Instruction>,
tail: Option<Instruction>,
users: HashSet<User<BasicBlock>>,
function: Option<Function>,
// 用于LinkedListNode实现是基本块放入Function的顺序并非实际的前驱和后继关系
pre: Option<BasicBlock>,
succ: Option<BasicBlock>,
}
impl BasicBlockData {
pub fn get_self_ptr(&self) -> BasicBlock {
self.self_ptr
}
}
#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct BasicBlock(pub GenericPtr<BasicBlockData>);
impl BasicBlock {
pub fn new(ctx: &mut Context) -> Self {
ctx.alloc_with(|self_ptr| BasicBlockData {
self_ptr: self_ptr,
head: None,
tail: None,
pre: None,
succ: None,
users: HashSet::default(),
function: None,
})
}
pub fn get_name(self) -> String{
format!("bb_{}", self.0.index())
}
pub fn get_head(self, ctx: &Context) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head
}
pub fn get_tail(self, ctx: &Context) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
}
pub fn is_entry(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre
.is_none()
}
pub fn is_terminated(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
.map_or(false, |tail| tail.is_terminater(ctx))
}
pub fn is_ret(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
.map_or(false, |tail| tail.is_ret(ctx))
}
pub fn get_function(self, ctx: &Context) -> Option<Function> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function
}
}
impl ArenaPtr for BasicBlock {
type Arena = Context;
type Data = BasicBlockData;
}
impl Useable for BasicBlock {
fn users(self, arena: &Self::Arena) -> impl IntoIterator<Item = User<Self>> {
self.deref(arena)
.expect("Failed to deref `basicblocks` in struct")
.users
.iter()
.copied()
}
fn insert(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref `basicblocks` in struct")
.users
.insert(user);
}
fn remove(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref `basicblocks` in struct Context")
.users
.remove(&user);
}
}
impl LinkedListContainer<Instruction> for BasicBlock {
type Ctx = Context;
fn head(self, ctx: &Self::Ctx) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head
}
fn tail(self, ctx: &Self::Ctx) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
}
fn set_head(self, ctx: &mut Self::Ctx, head: Option<Instruction>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head = head;
}
fn set_tail(self, ctx: &mut Self::Ctx, tail: Option<Instruction>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail = tail;
}
}
impl LinkedListNode for BasicBlock {
type Container = Function;
type Ctx = Context;
fn succ(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.succ
}
fn pre(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre
}
fn container(self, ctx: &Self::Ctx) -> Option<Self::Container> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function
}
fn set_succ(self, ctx: &mut Self::Ctx, succ: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.succ = succ;
}
fn set_pre(self, ctx: &mut Self::Ctx, pre: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre = pre;
}
fn set_container(self, ctx: &mut Self::Ctx, container: Option<Self::Container>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function = container;
}
fn unlink(self, ctx: &mut Self::Ctx) {
let pre = self.pre(ctx);
let succ = self.succ(ctx);
if let Some(pre) = pre {
pre.set_succ(ctx, succ);
}
if let Some(succ) = succ {
succ.set_pre(ctx, pre);
}
if let Some(container) = self.container(ctx) {
if container.head(ctx) == Some(self) {
container.set_head(ctx, succ);
}
if container.tail(ctx) == Some(self) {
container.set_tail(ctx, pre);
}
}
self.set_pre(ctx, None);
self.set_succ(ctx, None);
self.set_container(ctx, None);
}
}

@ -0,0 +1,205 @@
use super::basicblock::{BasicBlock, BasicBlockData};
use super::function::{Function, FunctionData};
use super::global::{Global, GlobalData};
use super::instruction::{Instruction, InstructionData};
use super::typ::{Typ, TypeData};
use super::value::{Value, ValueData};
use crate::utils::storage::{Arena, GenericArena, GenericPtr, UniqueArena};
pub struct Context {
pub target: usize,
pub types: UniqueArena<TypeData>,
pub globals: GenericArena<GlobalData>,
pub values: GenericArena<ValueData>,
pub basicblocks: GenericArena<BasicBlockData>,
pub functions: GenericArena<FunctionData>,
pub instructions: GenericArena<InstructionData>,
}
impl Default for Context {
fn default() -> Self {
Self::new(4)
}
}
impl Context {
/// 创建一个新的Context
pub fn new(target: usize) -> Self {
Self {
target: target,
types: UniqueArena::default(),
globals: GenericArena::default(),
values: GenericArena::default(),
basicblocks: GenericArena::default(),
functions: GenericArena::default(),
instructions: GenericArena::default(),
}
}
// 设置目标机器字节数
pub fn set_target(&mut self, target: usize){
self.target = target;
}
/// 获取所有函数
pub fn get_functions(&self) -> impl Iterator<Item = Function> + '_ {
self.functions
.iter()
.map(|functiondata| functiondata.get_self_ptr())
}
}
impl Arena<Typ> for Context {
fn alloc_with<F>(&mut self, _: F) -> Typ
where
F: FnOnce(Typ) -> TypeData,
{
panic!("Failed to allocate type in context");
}
fn alloc(&mut self, typ: TypeData) -> Typ {
Typ(self.types.alloc(typ))
}
fn dealloc(&mut self, ptr: Typ) -> Option<TypeData> {
self.types.dealloc(ptr.0)
}
fn deref(&self, ptr: Typ) -> Option<&TypeData> {
self.types.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: Typ) -> Option<&mut TypeData> {
self.types.deref_mut(ptr.0)
}
}
impl Arena<Global> for Context {
fn alloc_with<F>(&mut self, f: F) -> Global
where
F: FnOnce(Global) -> GlobalData,
{
Global(
self.globals
.alloc_with(|ptr: GenericPtr<GlobalData>| f(Global(ptr))),
)
}
fn alloc(&mut self, data: GlobalData) -> Global {
Global(self.globals.alloc_with(|_| data))
}
fn dealloc(&mut self, ptr: Global) -> Option<GlobalData> {
self.globals.dealloc(ptr.0)
}
fn deref(&self, ptr: Global) -> Option<&GlobalData> {
self.globals.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: Global) -> Option<&mut GlobalData> {
self.globals.deref_mut(ptr.0)
}
}
impl Arena<Value> for Context {
/// 申请一个新的值并用f初始化该值f是一个函数闭包闭包要求传入一个Value作为参数并返回一个ValueData
fn alloc_with<F>(&mut self, f: F) -> Value
where
F: FnOnce(Value) -> ValueData,
{
Value(
self.values
.alloc_with(|ptr: GenericPtr<ValueData>| f(Value(ptr))),
)
}
/// 只将已经创建好的数据存进Arena中
fn alloc(&mut self, data: ValueData) -> Value {
Value(self.values.alloc_with(|_| data))
}
fn dealloc(&mut self, ptr: Value) -> Option<ValueData> {
self.values.dealloc(ptr.0)
}
fn deref(&self, ptr: Value) -> Option<&<Value as crate::utils::storage::ArenaPtr>::Data> {
self.values.deref(ptr.0)
}
fn deref_mut(
&mut self,
ptr: Value,
) -> Option<&mut <Value as crate::utils::storage::ArenaPtr>::Data> {
self.values.deref_mut(ptr.0)
}
}
impl Arena<BasicBlock> for Context {
fn alloc_with<F>(&mut self, f: F) -> BasicBlock
where
F: FnOnce(BasicBlock) -> super::basicblock::BasicBlockData,
{
BasicBlock(
self.basicblocks
.alloc_with(|ptr: GenericPtr<super::basicblock::BasicBlockData>| {
f(BasicBlock(ptr))
}),
)
}
fn alloc(&mut self, data: super::basicblock::BasicBlockData) -> BasicBlock {
BasicBlock(self.basicblocks.alloc_with(|_| data))
}
fn dealloc(&mut self, ptr: BasicBlock) -> Option<super::basicblock::BasicBlockData> {
self.basicblocks.dealloc(ptr.0)
}
fn deref(&self, ptr: BasicBlock) -> Option<&super::basicblock::BasicBlockData> {
self.basicblocks.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: BasicBlock) -> Option<&mut super::basicblock::BasicBlockData> {
self.basicblocks.deref_mut(ptr.0)
}
}
impl Arena<Function> for Context {
fn alloc_with<F>(&mut self, f: F) -> Function
where
F: FnOnce(Function) -> FunctionData,
{
Function(self.functions.alloc_with(|ptr| f(Function(ptr))))
}
fn dealloc(&mut self, ptr: Function) -> Option<FunctionData> {
self.functions.dealloc(ptr.0)
}
fn deref(&self, ptr: Function) -> Option<&FunctionData> {
self.functions.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: Function) -> Option<&mut FunctionData> {
self.functions.deref_mut(ptr.0)
}
}
impl Arena<Instruction> for Context {
fn alloc_with<F>(&mut self, f: F) -> Instruction
where
F: FnOnce(Instruction) -> InstructionData,
{
Instruction(self.instructions.alloc_with(|ptr| f(Instruction(ptr))))
}
fn dealloc(&mut self, ptr: Instruction) -> Option<InstructionData> {
self.instructions.dealloc(ptr.0)
}
fn deref(&self, ptr: Instruction) -> Option<&InstructionData> {
self.instructions.deref(ptr.0)
}
fn deref_mut(&mut self, ptr: Instruction) -> Option<&mut InstructionData> {
self.instructions.deref_mut(ptr.0)
}
}

@ -0,0 +1,45 @@
use super::instruction::Instruction;
use crate::utils::storage::ArenaPtr;
pub trait Useable: ArenaPtr {
/* 获取值的使用者 */
fn users(self, arena: &Self::Arena) -> impl IntoIterator<Item = User<Self>>;
/* 为一个值添加一个使用者 */
fn insert(self, arena: &mut Self::Arena, user: User<Self>);
/* 删除一个值的使用者 */
fn remove(self, arena: &mut Self::Arena, user: User<Self>);
}
/// def-use链中的使用者泛型结构体可与任何实现了Useable特性的结构体关联
/// E.G:
///
/// add %1 %2
/// User<Instruction> { instruction: instructions, index: 1,}
/// User<Instruction> { instruction: instructions, index: 2,}
/// index 0 留给指令的运算结果
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
pub struct User<T: Useable> {
instruction: Instruction,
index: usize,
_marker: std::marker::PhantomData<T>, //User结构体只在逻辑上和T关联不实际存储T类型的值
}
impl<T: Useable> User<T> {
pub fn new(instruction: Instruction, index: usize) -> Self {
Self {
instruction,
index,
_marker: std::marker::PhantomData,
}
}
pub fn get_instruction(&self) -> Instruction {
self.instruction
}
pub fn get_index(&self) -> usize {
self.index
}
}

@ -0,0 +1,111 @@
use super::basicblock::BasicBlock;
use super::value::Value;
use super::{context::Context, typ::Typ};
use crate::utils::linked_list::LinkedListContainer;
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr};
pub struct FunctionData {
self_ptr: Function,
id: String,
parameters: Vec<Value>,
return_type: Typ,
head: Option<BasicBlock>,
tail: Option<BasicBlock>,
}
impl FunctionData {
pub fn get_self_ptr(&self) -> Function {
*(&self.self_ptr)
}
}
#[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct Function(pub GenericPtr<FunctionData>);
impl Function {
/// 创建一个新的函数
pub fn new(ctx: &mut Context, id: String, return_type: Typ) -> Self {
ctx.alloc_with(|self_ptr| FunctionData {
self_ptr,
id,
parameters: vec![],
return_type,
head: None,
tail: None,
})
}
/// 获取函数名
pub fn get_id(self, ctx: &Context) -> String {
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.id
.clone()
}
/// 获取函数的返回类型
pub fn get_return_type(self, ctx: &Context) -> Typ {
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.return_type
}
/// 获取函数的参数列表
pub fn get_parameters(self, ctx: &Context) -> Vec<Value> {
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.parameters
.clone()
}
/// 添加一个参数到函数参数列表中
pub fn add_parameter(self, ctx: &mut Context, typ: Typ) -> Value {
let parameter = Value::parameter(
ctx,
self,
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.parameters
.len() as u32,
typ,
);
let function = self
.deref_mut(ctx)
.expect("Failed to deref `functions` in struct Context");
function.parameters.push(parameter);
parameter
}
}
impl ArenaPtr for Function {
type Data = FunctionData;
type Arena = Context;
}
impl LinkedListContainer<BasicBlock> for Function {
type Ctx = Context;
fn head(self, ctx: &Self::Ctx) -> Option<BasicBlock> {
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.head
}
fn tail(self, ctx: &Self::Ctx) -> Option<BasicBlock> {
self.deref(ctx)
.expect("Failed to deref `functions` in struct Context")
.tail
}
fn set_head(self, ctx: &mut Self::Ctx, head: Option<BasicBlock>) {
self.deref_mut(ctx)
.expect("Failed to deref `functions` in struct Context")
.head = head;
}
fn set_tail(self, ctx: &mut Self::Ctx, tail: Option<BasicBlock>) {
self.deref_mut(ctx)
.expect("Failed to deref `functions` in struct Context")
.tail = tail;
}
}

@ -0,0 +1,56 @@
use super::context::Context;
use super::typ::Typ;
use super::value::ConstantValue;
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr};
pub struct GlobalData {
pub self_ptr: Global,
name: String,
value: ConstantValue,
}
impl GlobalData {
pub fn get_self_ptr(&self) -> Global {
self.self_ptr
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
pub struct Global(pub GenericPtr<GlobalData>);
impl ArenaPtr for Global {
type Arena = Context;
type Data = GlobalData;
}
impl Global {
/// 创建一个全局变量
pub fn new(ctx: &mut Context, name: String, value: ConstantValue) -> Self {
ctx.alloc_with(|self_ptr| GlobalData {
self_ptr,
name,
value,
})
}
/// 获取全局变量的名称
pub fn name(self, ctx: &Context) -> &str {
&self
.deref(ctx)
.expect("Failed to deref `name` of struct Global")
.name
}
/// 获取全局变量的值
pub fn value(self, ctx: &Context) -> &ConstantValue {
&self
.deref(ctx)
.expect("Failed to deref `value` of struct Global")
.value
}
/// 获取全局变量的类型
pub fn typ(self, ctx: &Context) -> Typ {
self.value(ctx).typ()
}
}

@ -0,0 +1,435 @@
use std::vec;
use crate::{
frontend::{
ir::{
defuse::{Useable, User},
},
},
utils::{
linked_list::{LinkedListContainer, LinkedListNode},
storage::{Arena, ArenaPtr, GenericPtr},
},
};
use super::{basicblock::BasicBlock, context::Context, typ::Typ, value::Value};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TerminatorOp {
// ret <type> <value> ; Return a value from a non-void function
// ret void ; Return from void function
Ret,
// br label <dest> ;无条件跳转
Br,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BinaryOp {
// <result> = add <Typ> <op1>, <op2> ; yields Typ:result
Add,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MemAccessOp {
// <result> = alloca <type>
Alloca { typ: Typ },
// store <Typ> <value>, <Typ>* <pointer>
Store,
// <<result> = load <Typ>, <Typ>* <pointer>
Load,
}
#[derive(Debug, Clone, Copy)]
pub enum InstructionKind {
// Terminator instructions
Terminator { op: TerminatorOp },
// Binary instructions
Binary { op: BinaryOp },
// Memory access instructions
MemAccess { op: MemAccessOp },
}
impl PartialEq for InstructionKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(InstructionKind::Terminator { op: op1 }, InstructionKind::Terminator { op: op2 }) => {
op1 == op2
}
(InstructionKind::Binary { op: op1 }, InstructionKind::Binary { op: op2 }) => {
op1 == op2
}
(InstructionKind::MemAccess { op: op1 }, InstructionKind::MemAccess { op: op2 }) => {
op1 == op2
}
_ => false,
}
}
}
pub struct InstructionData {
self_ptr: Instruction,
kind: InstructionKind,
operands: Vec<(Value, bool)>,
operands_bbk: Vec<(BasicBlock, bool)>,
result: Option<Value>,
succ: Option<Instruction>,
pre: Option<Instruction>,
basicblock: Option<BasicBlock>,
}
impl InstructionData {
pub fn get_self_ptr(&self) -> Instruction {
self.self_ptr
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
pub struct Instruction(pub GenericPtr<InstructionData>);
impl Instruction {
/// 创建一个还未指定操作数的指令
fn new_without_operands(ctx: &mut Context, kind: InstructionKind, typ: Typ) -> Self {
let instruction = ctx.alloc_with(|self_ptr| InstructionData {
self_ptr: self_ptr,
kind,
operands: vec![],
operands_bbk: vec![],
result: None,
succ: None,
pre: None,
basicblock: None,
});
if !typ.is_void(ctx) {
let result = Value::inst_result(ctx, instruction, typ);
instruction
.deref_mut(ctx)
.expect("Failed to deref `instructions` in struct `Context`")
.result = Some(result);
result.insert(ctx, User::new(instruction, 0)); // 默认插入到第0个位置
instruction
} else {
instruction
}
}
/// 创建一个指定操作数的指令
pub fn new_with_operands(
ctx: &mut Context,
kind: InstructionKind,
typ: Typ,
operands: Vec<Value>,
) -> Self {
let instruction = Self::new_without_operands(ctx, kind, typ);
let instruction_data = instruction
.deref_mut(ctx)
.expect("Failed to deref `instructions` in struct `Context`");
instruction_data.operands = operands.into_iter().map(|op| (op, true)).collect();
instruction
}
/// 获取指定index位置的操作数
pub fn get_operand(self, ctx: &Context, index: usize) -> Option<Value> {
if index
>= self
.deref(ctx)
.expect("Failed to deref `operands` in struct `Instruction`")
.operands
.len()
{
return None;
}
self.deref(ctx)
.expect("Failed to deref `operands` in struct `Instruction`")
.operands
.get(index)
.map(|(value, _)| *value)
}
/// 获取所有操作数
pub fn get_operands(self, ctx: &Context) -> Vec<Value> {
self.deref(ctx)
.expect("Failed to deref `operands` in struct `Instruction`")
.operands
.iter()
.map(|(value, _)| *value)
.collect()
}
/// 获取指令操作数个数
pub fn operand_count(self, ctx: &Context) -> usize {
self.deref(ctx)
.expect("Failed to deref `operands` in struct `Instruction`")
.operands
.len()
}
/// 获取指令类型
pub fn get_kind(&self, ctx: &Context) -> InstructionKind {
self.deref(ctx)
.expect("Failed to deref `kind` in struct `Instruction`")
.kind
}
/// 获取指令的运算结果
pub fn get_result(&self, ctx: &Context) -> Option<Value> {
self.deref(ctx)
.expect("Failed to deref `result` in struct `Instruction`")
.result
}
/// 获取指令结果的类型
pub fn result_typ(&self, ctx: &Context) -> Typ {
self.get_result(ctx)
.expect("Failed to get result from instruction")
.kind(ctx)
}
/// 获取指令所在的基本块
pub fn get_basicblock(&self, ctx: &Context) -> Option<BasicBlock> {
self.deref(ctx)
.expect("Failed to deref `basic_block` in struct `Instruction`")
.basicblock
}
/// 创建ret指令
pub fn ret(ctx: &mut Context, value: Option<Value>) -> Self {
let typ = Typ::void(ctx);
if value.is_none() {
return Self::new_without_operands(
ctx,
InstructionKind::Terminator {
op: TerminatorOp::Ret,
},
typ,
);
}
let instruction = Self::new_with_operands(
ctx,
InstructionKind::Terminator {
op: TerminatorOp::Ret,
},
typ,
vec![value.unwrap()],
);
value.unwrap().insert(ctx, User::new(instruction, 1));
instruction
}
/// 判断是否是ret指令
pub fn is_ret(&self, ctx: &Context) -> bool {
matches!(
self.get_kind(ctx),
InstructionKind::Terminator {
op: TerminatorOp::Ret
}
)
}
/// 为分支指令增加一个基本块
fn add_operand_bbk(self, ctx: &mut Context, block: BasicBlock) {
self.deref_mut(ctx)
.expect("Failed to deref_mut `operand_bbk` in struct `Instruction`")
.operands_bbk
.push((block, true));
}
/// 获取跳转指令指定index的基本块
pub fn get_operand_bbk(self, ctx: &Context, index: usize) -> Option<BasicBlock> {
if index
>= self
.deref(ctx)
.expect("Failed to deref `operands_bbk` in struct `Instruction`")
.operands_bbk
.len()
{
return None;
}
self.deref(ctx)
.expect("Failed to deref `operands_bbk` in struct `Instruction`")
.operands_bbk
.get(index)
.map(|(value, _)| *value)
}
/// 创建无条件跳转指令
pub fn br(ctx: &mut Context, dest: BasicBlock) -> Self {
let typ = Typ::void(ctx);
let instruction = Self::new_with_operands(
ctx,
InstructionKind::Terminator {
op: TerminatorOp::Br,
},
typ,
vec![],
);
instruction.add_operand_bbk(ctx, dest);
dest.insert(ctx, User::new(instruction, 1));
instruction
}
/// 判断是否是分支指令
pub fn is_br(&self, ctx: &Context) -> bool {
matches!(
self.get_kind(ctx),
InstructionKind::Terminator {
op: TerminatorOp::Br
}
)
}
/// 判断指令是否是terminator指令
pub fn is_terminater(&self, ctx: &Context) -> bool {
matches!(self.get_kind(ctx), InstructionKind::Terminator { .. })
}
/// 创建双目运算符
pub fn binary(ctx: &mut Context, op: BinaryOp, typ: Typ, op1: Value, op2: Value) -> Self {
let instruction =
Self::new_with_operands(ctx, InstructionKind::Binary { op }, typ, vec![op1, op2]);
op1.insert(ctx, User::new(instruction, 1));
op2.insert(ctx, User::new(instruction, 2));
instruction
}
/// 创建访存指令
pub fn memaccess(ctx: &mut Context, op: MemAccessOp, typ: Typ, ops: Vec<Value>) -> Self {
match op {
MemAccessOp::Store => {
let void = Typ::void(ctx);
let instruction = Self::new_with_operands(
ctx,
InstructionKind::MemAccess { op },
void,
ops.clone(),
);
for (i, op) in ops.iter().enumerate() {
op.insert(ctx, User::new(instruction, i + 1));
}
instruction
}
_ => {
let instruction = Self::new_with_operands(
ctx,
InstructionKind::MemAccess { op },
typ,
ops.clone(),
);
for (i, op) in ops.iter().enumerate() {
op.insert(ctx, User::new(instruction, i + 1));
}
instruction
}
}
}
/// 判断是否是store指令
pub fn is_store(&self, ctx: &Context) -> bool {
matches!(
self.get_kind(ctx),
InstructionKind::MemAccess {
op: MemAccessOp::Store
}
)
}
/// 判断是否是load指令
pub fn is_load(&self, ctx: &Context) -> bool {
matches!(
self.get_kind(ctx),
InstructionKind::MemAccess {
op: MemAccessOp::Load
}
)
}
/// 判断是否是alloca指令
pub fn is_alloca(&self, ctx: &Context) -> bool {
matches!(
self.get_kind(ctx),
InstructionKind::MemAccess {
op: MemAccessOp::Alloca { .. }
}
)
}
}
impl ArenaPtr for Instruction {
type Arena = Context;
type Data = InstructionData;
}
impl LinkedListNode for Instruction {
type Container = BasicBlock;
type Ctx = Context;
fn succ(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `succ` in struct `Instruction`")
.succ
}
fn pre(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `pre` in struct `Instruction`")
.pre
}
fn container(self, ctx: &Self::Ctx) -> Option<Self::Container> {
self.deref(ctx)
.expect("Failed to deref `container` in struct `Instruction")
.basicblock
}
fn set_succ(self, ctx: &mut Self::Ctx, succ: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `succ` in struct `Instruction`")
.succ = succ;
}
fn set_pre(self, ctx: &mut Self::Ctx, pre: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `pre` in struct `Instruction`")
.pre = pre;
}
fn set_container(self, ctx: &mut Self::Ctx, container: Option<Self::Container>) {
self.deref_mut(ctx)
.expect("Failed to deref `container` in struct `Instruction`")
.basicblock = container;
}
fn unlink(self, ctx: &mut Self::Ctx) {
let pre = self.pre(ctx);
let succ = self.succ(ctx);
if let Some(pre) = pre {
pre.set_succ(ctx, succ);
}
if let Some(succ) = succ {
succ.set_pre(ctx, pre);
}
if let Some(container) = self.container(ctx) {
if container.get_head(ctx) == Some(self) {
container.set_head(ctx, succ);
}
if container.get_tail(ctx) == Some(self) {
container.set_tail(ctx, pre);
}
}
self.set_pre(ctx, None);
self.set_succ(ctx, None);
self.set_container(ctx, None);
}
}

@ -0,0 +1,8 @@
pub mod context;
pub mod typ;
pub mod global;
pub mod value;
pub mod function;
pub mod basicblock;
pub mod instruction;
pub mod defuse;

@ -0,0 +1,60 @@
use super::context::Context;
use crate::{
utils::storage::{Arena, ArenaPtr, UniqueArenaPtr},
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TypeData {
Void,
Int32,
Ptr { typ_of_ptr: Typ },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, Copy, PartialOrd)]
pub struct Typ(pub UniqueArenaPtr<TypeData>);
impl ArenaPtr for Typ {
type Arena = Context;
type Data = TypeData;
}
impl Typ {
pub fn void(ctx: &mut Context) -> Self{
ctx.alloc(TypeData::Void)
}
pub fn is_void(&self, ctx: &Context) -> bool{
matches!(self.deref(ctx).unwrap(), TypeData::Void)
}
pub fn int32(ctx: &mut Context) -> Self {
ctx.alloc(TypeData::Int32)
}
pub fn is_int32(&self, ctx: &Context) -> bool {
matches!(self.deref(ctx).unwrap(), TypeData::Int32)
}
pub fn ptr(ctx: &mut Context, typ_of_ptr: Typ) -> Self {
ctx.alloc(TypeData::Ptr { typ_of_ptr })
}
pub fn is_ptr(&self, ctx: &Context) -> bool {
matches!(self.deref(ctx).unwrap(), TypeData::Ptr { .. })
}
/// 类型所占位数
pub fn bitwidth(&self, ctx: &Context) -> usize {
match self.deref(ctx).unwrap() {
TypeData::Void => 0,
TypeData::Int32 => 32,
TypeData::Ptr { .. } => ctx.target as usize * 8,
}
}
/// 类型所占字节数
pub fn bytewidth(&self, ctx: &Context) -> usize {
(self.bitwidth(ctx) + 7) / 8
}
}

@ -0,0 +1,243 @@
use super::context::Context;
use super::defuse::{Useable, User};
use super::function::Function;
use super::instruction::Instruction;
use super::typ::Typ;
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr};
use rustc_hash::FxHashSet as HashSet;
#[derive(Debug, Clone)]
pub enum ConstantValue {
Undef {
typ: Typ,
},
Zero {
typ: Typ,
},
Int32 {
typ: Typ,
value: i32,
},
GlobalPtr {
typ: Typ, // 全局指针类型
name: String, // 全局变量的名
value_type: Typ, // 指针指向数据的类型
},
}
impl ConstantValue {
//常量值的类型
pub fn typ(&self) -> Typ {
match self {
ConstantValue::Undef { typ } => *typ,
ConstantValue::Zero { typ, .. } => *typ,
ConstantValue::Int32 { typ, .. } => *typ,
ConstantValue::GlobalPtr { value_type, .. } => *value_type,
}
}
pub fn undef(typ: Typ) -> ConstantValue {
ConstantValue::Undef { typ }
}
pub fn is_undef(&self) -> bool {
matches!(self, ConstantValue::Undef { .. })
}
/// 创建zero类型
pub fn zero(typ: Typ) -> ConstantValue {
ConstantValue::Zero { typ }
}
/// 判断是不是zero类型
pub fn is_zero(&self) -> bool {
matches!(self, ConstantValue::Zero { .. })
}
pub fn int32(ctx: &mut Context, value: i32) -> ConstantValue {
let int32 = Typ::int32(ctx);
ConstantValue::Int32 { typ: int32, value }
}
pub fn global_ptr(ctx: &mut Context, name: String, value_type: Typ) -> ConstantValue {
let global_ptr = Typ::ptr(ctx, value_type.clone());
ConstantValue::GlobalPtr {
typ: global_ptr,
name,
value_type,
}
}
pub fn to_string(&self, _ctx: &Context) -> String {
let mut str = String::new();
match self {
ConstantValue::Undef { typ: _ } => str.push_str("undef"),
ConstantValue::Zero {..} => {
str.push_str("0")
}
ConstantValue::Int32 { value, .. } => str.push_str(&value.to_string()),
ConstantValue::GlobalPtr { name, .. } => {
str.push_str("@");
str.push_str(name);
}
}
str
}
}
#[derive(Debug)]
pub enum ValueKind {
// 指令的运算结果
InstResult {
instruction: Instruction,
typ: Typ,
},
// 函数参数
Parameter {
function: Function,
index: u32,
typ: Typ,
},
// 常量值
Constant {
value: ConstantValue,
},
}
#[derive(Debug)]
pub struct ValueData {
// 值类型的种类
pub kind: ValueKind,
pub users: HashSet<User<Value>>,
self_ptr: Value,
}
impl ValueData {
pub fn get_self_ptr(&self) -> Value {
self.self_ptr
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, Copy, PartialOrd)]
pub struct Value(pub GenericPtr<ValueData>);
impl ArenaPtr for Value {
type Arena = Context;
type Data = ValueData;
}
impl Value {
pub fn new(ctx: &mut Context, kind: ValueKind) -> Self {
ctx.alloc_with(|self_ptr| ValueData {
self_ptr: self_ptr,
kind,
users: HashSet::default(),
})
}
// InstResult类型的值获取指令
pub fn get_instruction(self, ctx: &Context) -> Option<Instruction> {
match self.deref(ctx).unwrap().kind {
ValueKind::InstResult { instruction, .. } => Some(instruction),
_ => None,
}
}
// 获取值类型
pub fn kind(&self, ctx: &Context) -> Typ {
match self
.deref(ctx)
.expect("Failed to deref `Value` in Value::kind()")
.kind
{
ValueKind::InstResult { typ, .. } => typ,
ValueKind::Parameter { typ, .. } => typ,
ValueKind::Constant { ref value, .. } => value.typ(),
}
}
pub fn parameter(ctx: &mut Context, function: Function, index: u32, typ: Typ) -> Self {
Self::new(
ctx,
ValueKind::Parameter {
function: function,
index,
typ,
},
)
}
pub fn is_parameter(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_parameter` in Value")
.kind,
ValueKind::Parameter { .. }
)
}
pub fn inst_result(ctx: &mut Context, instruction: Instruction, typ: Typ) -> Self {
let value = Self::new(
ctx,
ValueKind::InstResult {
instruction: instruction,
typ,
},
);
value
}
pub fn constant(ctx: &mut Context, value: ConstantValue) -> Self {
Self::new(ctx, ValueKind::Constant { value })
}
pub fn is_constant(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_constant` in Value")
.kind,
ValueKind::Constant { .. }
)
}
pub fn global_ptr(ctx: &mut Context, name: String, value_type: Typ) -> Self {
let t = ConstantValue::global_ptr(ctx, name, value_type);
let t = Self::new(ctx, ValueKind::Constant { value: t });
t
}
pub fn is_global_ptr(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_global_ptr` in Value")
.kind,
ValueKind::Constant {
value: ConstantValue::GlobalPtr { .. }
}
)
}
}
impl Useable for Value {
fn users(self, arena: &Self::Arena) -> impl IntoIterator<Item = User<Self>> {
self.deref(arena)
.expect("Failed to deref `users` in struct Context")
.users
.iter()
.copied()
}
fn insert(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref mut `users` in struct Context")
.users
.insert(user);
}
fn remove(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref mut `users` in struct Context")
.users
.remove(&user);
}
}

@ -0,0 +1,221 @@
use super::ir::{
basicblock::BasicBlock,
context::Context,
function::Function,
global::{Global, GlobalData},
instruction::{
BinaryOp as IBinaryOp,InstructionKind,
MemAccessOp, TerminatorOp
},
typ::{Typ, TypeData},
value::{Value, ValueKind},
};
use crate::{
frontend::ir::instruction::Instruction,
utils::{
linked_list::LinkedListContainer,
storage::{ArenaPtr, Idx},
},
};
pub trait Display {
fn display(self, ctx: &Context) -> String;
}
impl Context {
pub fn get_ir_string(&self) -> String {
let mut ir = String::new();
for GlobalData {
self_ptr: global, ..
} in self.globals.iter()
{
ir += &format!("{}\n", global.display(self));
}
for func in self.get_functions() {
ir += &format!("{}\n", func.display(self));
}
ir
}
}
impl Display for Global {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
let typ = self.value(ctx).typ().display(ctx);
if self.value(ctx).is_undef() || self.value(ctx).is_zero() {
ir += &format!("@{} = global {} zeroinitializer\n", self.name(ctx), typ);
} else {
ir += &format!(
"@{} = global {} {}\n",
self.name(ctx),
typ,
self.value(ctx).to_string(ctx)
);
}
ir
}
}
impl Display for Function {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
ir += &format!(
"define {} @{}(",
self.get_return_type(ctx).display(ctx),
self.get_id(ctx)
);
for (i, param) in self.get_parameters(ctx).iter().enumerate() {
if i != 0 {
ir += ", ";
}
ir += &format!("{} {}", param.kind(ctx).display(ctx), param.display(ctx));
}
ir += ") {\n";
for bbk in self.iter(ctx) {
ir += &format!("{}\n", bbk.display(ctx));
}
ir += "}";
ir
}
}
impl Display for Typ {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
match self.deref(ctx).unwrap() {
TypeData::Void => {
ir += "void";
}
TypeData::Int32 => {
ir += "i32";
}
TypeData::Ptr { typ_of_ptr: typ } => {
if typ.is_void(ctx) {
ir += &format!("i8*")
} else {
ir += &format!("{}*", typ.display(ctx));
}
}
}
ir
}
}
impl Display for BasicBlock {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
ir += &format!("{}:", self.get_name());
for inst in self.iter(ctx) {
ir += &format!("\n\t{}", inst.display(ctx));
}
ir
}
}
impl Display for Instruction {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
if let Some(result) = self.get_result(ctx) {
ir += &format!("{} = ", result.display(ctx));
}
match self.get_kind(ctx) {
InstructionKind::Terminator { op } => match op {
TerminatorOp::Ret => {
if let Some(ret_val) = self.get_operand(ctx, 0) {
ir += &format!(
"ret {} {}",
ret_val.kind(ctx).display(ctx),
ret_val.display(ctx)
);
} else {
ir += "ret void";
}
}
TerminatorOp::Br => {
ir += &format!(
"br label %{}",
self.get_operand_bbk(ctx, 0)
.expect("Failed to get the first operand of the br instruction")
.get_name()
);
}
},
InstructionKind::Binary { op } => match op {
IBinaryOp::Add => {
let op1 = self.get_operand(ctx, 0).unwrap();
let op2 = self.get_operand(ctx, 1).unwrap();
let typ = op1.kind(ctx);
ir += &format!(
"add {} {}, {}",
typ.display(ctx),
op1.display(ctx),
op2.display(ctx)
);
}
},
InstructionKind::MemAccess { op } => {
match op {
MemAccessOp::Alloca { typ } => {
ir += &format!("alloca {}", typ.display(ctx));
}
MemAccessOp::Load => {
let typ = self.result_typ(ctx);
let op1 = self.get_operand(ctx, 0).unwrap();
let typ_of_op1 = op1.kind(ctx);
ir += &format!(
"load {}, {}* {}",
typ.display(ctx),
typ_of_op1.display(ctx),
op1.display(ctx)
);
}
MemAccessOp::Store => {
let op1 = self.get_operand(ctx, 0).unwrap();
let typ_of_op1 = op1.kind(ctx);
let op2 = self.get_operand(ctx, 1).unwrap();
let typ_of_op2 = op2.kind(ctx);
ir += &format!(
"store {} {}, {}* {}",
typ_of_op1.display(ctx),
op1.display(ctx),
typ_of_op2.display(ctx),
op2.display(ctx)
);
}
};
}
}
ir
}
}
impl Display for Value {
fn display(self, ctx: &Context) -> String {
let mut ir = String::new();
match &self.deref(ctx).unwrap().kind {
ValueKind::InstResult {
instruction: _,
typ: _,
}
| ValueKind::Parameter {
function: _,
index: _,
typ: _,
} => {
ir += &format!("%v{}", self.0.index());
}
ValueKind::Constant { value } => {
ir += &format!("{}", value.to_string(ctx));
}
};
ir
}
}

@ -0,0 +1,549 @@
use super::{
ir::{
basicblock::BasicBlock,
context::{Context},
function::Function,
global::Global,
instruction::{
BinaryOp as IBinaryOp, Instruction,
MemAccessOp,
},
typ::Typ,
value::{ConstantValue, Value},
},
lalrpop::ast::{
self, BlockItem, ComptimeValue, Decl, Exp,
FuncDef, FuncFParam, GlobalItem, InitVal, Stmt, Type, TypeKind, VarDecl, VarDef,
},
symboltable::{SymbolEntry, SymbolTable},
};
use crate::{
frontend::lalrpop::ast::{BinaryOp as ABinaryOp, CompUnit, ExpKind},
utils::linked_list::LinkedListContainer,
};
#[derive(Debug, Clone, Copy)]
pub enum IrGenResult {
Global(Global), //全局变量需要特殊处理和一般的值不同需要通过地址访问
Value(Value),
}
impl IrGenResult {
pub fn unwrap(self, ctx: &mut Context) -> Value {
match self {
IrGenResult::Value(val) => val,
IrGenResult::Global(slot) => {
let name = slot.name(ctx).to_string();
let value_ty = slot.typ(ctx);
Value::global_ptr(ctx, name, value_ty)
}
}
}
}
#[derive(Default)]
pub struct IrGenContext {
pub ctx: Context,
/// 符号表
pub symboltable: SymbolTable,
//当前函数
pub cur_func: Option<Function>,
pub cur_func_id: Option<String>,
pub cur_bbk: Option<BasicBlock>,
// Stacks for loop control flow.
pub loop_entry_stack: Vec<BasicBlock>,
pub loop_exit_stack: Vec<BasicBlock>,
// Return BasicBlock and slot
pub cur_ret_slot: Option<Value>,
pub cur_ret_bbk: Option<BasicBlock>,
}
impl IrGenContext {
pub fn context(self) -> Context {
self.ctx
}
//将AST中的数据类型转化为IR中的数据类型
fn ast2ir_type(&mut self, typ: &Type) -> Typ {
match typ.kind() {
TypeKind::Void => Typ::void(&mut self.ctx),
TypeKind::Int => Typ::int32(&mut self.ctx),
TypeKind::Ptr(ty) => {
let ty = self.ast2ir_type(ty);
Typ::ptr(&mut self.ctx, ty)
}
TypeKind::Function(..) => unreachable!("function type should be handled separately"),
}
}
/// AST常量值转化为IR中的常量值
fn ast2ir_const(&mut self, comptime_const: &ComptimeValue) -> ConstantValue {
match comptime_const {
ComptimeValue::Int(a) => ConstantValue::int32(&mut self.ctx, *a),
ComptimeValue::Undef(typ) => {
let ir_ty = self.ast2ir_type(typ);
ConstantValue::undef(ir_ty)
}
}
}
/// AST二元表达式生成表达式转化为IR中的值
fn ast2ir_binary(&mut self, exp: &Exp) -> Option<Value> {
let cur_bbk = self.cur_bbk.unwrap();
match &exp.kind {
ExpKind::Binary(op, opd1, opd2) => {
// 提前计算操作数和类型
let typ = exp.get_type();
let typ_of_ir = self.ast2ir_type(&typ);
let opd1_val = self.ast2ir_exp(opd1)?;
let opd2_val = self.ast2ir_exp(opd2)?;
let instruction = match op {
// 算术运算统一处理
ABinaryOp::Add => {
let op_kind = match op {
ABinaryOp::Add=> IBinaryOp::Add,
};
Instruction::binary(&mut self.ctx, op_kind, typ_of_ir, opd1_val, opd2_val)
}
};
cur_bbk.push_back(&mut self.ctx, instruction).unwrap();
instruction.get_result(&self.ctx)
}
_ => None,
}
}
/// AST中的表达式转化为IR表达式并计算结果为IR值返回
fn ast2ir_exp(&mut self, exp: &Exp) -> Option<Value> {
let cur_bbk = self.cur_bbk.unwrap();
match &exp.kind {
ExpKind::Const(v) => {
let v = self.ast2ir_const(v);
Some(Value::constant(&mut self.ctx, v))
}
ExpKind::Binary(..) => self.ast2ir_binary(exp),
ExpKind::LVal(lval) => {
// 提前获取符号表条目和类型
let entry = self.symboltable.lookup(&lval.id).unwrap();
let ir_value = entry.ir_value.unwrap();
let typ_of_ir = self.ast2ir_type(&entry.typ.clone());
let slot = ir_value.unwrap(&mut self.ctx);
if slot.is_parameter(&self.ctx) {
Some(slot)
} else {
let load = Instruction::memaccess(
&mut self.ctx,
MemAccessOp::Load,
typ_of_ir,
vec![slot],
);
cur_bbk.push_back(&mut self.ctx, load).unwrap();
load.get_result(&self.ctx)
}
}
}
}
// /// 将AST中的函数参数转化为IR中的函数参数过程和表达式计算不相同尤其是在数组和指针的处理上
// fn ast2ir_param(&mut self, exp: &Exp, _param_type: Typ) -> Option<Value> {
// let cur_bbk = self.cur_bbk.unwrap();
// match &exp.kind {
// ExpKind::Const(v) => {
// let value_of_ir = self.ast2ir_const(v);
// Some(Value::constant(&mut self.ctx, value_of_ir))
// }
// ExpKind::Binary(..) => self.ast2ir_binary(exp),
// ExpKind::LVal(LVal { id }) => {
// //在符号表中查找变量的IR值
// let entry = self.symboltable.lookup(id).unwrap();
// let ir_value = entry.ir_value.unwrap();
// //获取变量类型
// let typ_of_ir = self.ast2ir_type(&entry.typ.clone());
// let slot = ir_value.unwrap(&mut self.ctx);
// if slot.is_parameter(&self.ctx){
// //如果时函数参数直接返回slot因为此时的值已经在栈帧中
// Some(slot)
// } else {
// //不是函数参数则可能是临时变量或者全局变量,需要从内存中加载出来
// let instruction = Instruction::memaccess(
// &mut self.ctx,
// MemAccessOp::Load,
// typ_of_ir,
// vec![slot],
// );
// cur_bbk.push_back(&mut self.ctx, instruction).unwrap();
// Some(
// instruction
// .get_result(&self.ctx)
// .expect("Failed to unwrap the result of the lval in AST"),
// )
// }
// }
// }
// }
fn bbk_end_with_terminator(&mut self) -> bool {
let cur_bbk = self.cur_bbk.as_ref().unwrap();
// Check if the current basic block ends with a terminator instruction
cur_bbk.is_terminated(&self.ctx)
}
}
pub trait IrGen {
fn irgen(&self, irgen: &mut IrGenContext);
}
impl IrGen for CompUnit {
///为Sysy顶层的编译单元生成IR
fn irgen(&self, irgen: &mut IrGenContext) {
//全局作用域
irgen.symboltable.enter_scope();
for item in &self.items {
item.irgen(irgen);
}
irgen.symboltable.leave_scope();
}
}
impl IrGen for GlobalItem {
// Generate IR for an item.
fn irgen(&self, irgen: &mut IrGenContext) {
match self {
GlobalItem::Decl(decl) => match decl {
Decl::VarDecl(VarDecl { defs, .. }) => {
for VarDef { id, init, .. } in defs {
// 未给出初始化值的变量声明默认初始化为0
let init = init.as_ref().unwrap();
let comptime = match init {
InitVal::Exp(exp) => exp
.try_fold(&irgen.symboltable)
.expect("global def expected to have constant initializer"),
};
let constant = irgen.ast2ir_const(&comptime);
let slot = Global::new(
&mut irgen.ctx,
format!("NUDT_GLOBAL_VAR_{}", id),
constant,
);
irgen.symboltable.insert(
id.clone(),
SymbolEntry {
typ: match init {
InitVal::Exp(exp) => exp.typ().clone(),
},
comptime: Some(comptime),
ir_value: Some(IrGenResult::Global(slot)),
},
);
}
}
},
GlobalItem::FuncDef(func_def) => func_def.irgen(irgen),
}
}
}
impl IrGen for FuncDef {
fn irgen(&self, irgen: &mut IrGenContext) {
// 进入函数当前的作用域
irgen.symboltable.enter_scope();
let mut param_tys = Vec::new();
for FuncFParam {
typ, ..
} in self.params.iter()
{
let typ = typ.clone();
param_tys.push(typ.clone());
}
let func_ty = Type::function(param_tys.clone(), self.typ.clone());
irgen.symboltable.insert_upper(
self.id.clone(),
SymbolEntry {
typ: func_ty,
comptime: None,
ir_value: None,
},
1,
);
let ir_ret_ty = irgen.ast2ir_type(&self.typ);
let function = Function::new(&mut irgen.ctx, self.id.clone(), ir_ret_ty);
let bbk = BasicBlock::new(&mut irgen.ctx);
function.push_back(&mut irgen.ctx, bbk).unwrap();
irgen.cur_func = Some(function);
irgen.cur_func_id = Some(self.id.clone());
irgen.cur_bbk = Some(bbk);
for FuncFParam {
typ,
id,
} in self.params.iter()
{
let typ = typ.clone();
let ir_ty = irgen.ast2ir_type(&typ);
let param = function.add_parameter(&mut irgen.ctx, ir_ty);
irgen.symboltable.insert(
id.clone(),
SymbolEntry {
typ: typ.clone(),
comptime: None,
ir_value: Some(IrGenResult::Value(param)),
},
);
}
// 为传值的的参数创建alloca空间
// 理论上再循环中使用if判断参数是否属于传值的类型但是因为demo只支持int类型所以一定是传值
for (FuncFParam { id, .. }, typ) in self.params.iter().zip(param_tys.iter()) {
let ir_typ = irgen.ast2ir_type(typ);
let slot = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Alloca { typ: ir_typ },
ir_typ,
vec![],
);
bbk.push_front(&mut irgen.ctx, slot).unwrap();
let slot = slot.get_result(&irgen.ctx).unwrap();
// get old entry
let param = irgen
.symboltable
.lookup(id)
.unwrap()
.ir_value
.unwrap()
.unwrap(&mut irgen.ctx);
// store
let store = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Store,
ir_typ,
vec![param, slot],
);
bbk.push_back(&mut irgen.ctx, store).unwrap();
// set new entry
irgen.symboltable.insert(
id.clone(),
SymbolEntry {
typ: typ.clone(),
comptime: None,
ir_value: Some(IrGenResult::Value(slot)),
},
);
}
//创建返回基本块和返回值槽
let ret_block = BasicBlock::new(&mut irgen.ctx);
irgen.cur_ret_bbk = Some(ret_block);
// 为返回值创建alloca空间
if !self.typ.is_void() {
let ir_ret_ty = irgen.ast2ir_type(&self.typ);
let ret_slot = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Alloca { typ: ir_ret_ty },
ir_ret_ty,
vec![],
);
bbk.push_front(&mut irgen.ctx, ret_slot).unwrap();
irgen.cur_ret_slot = Some(ret_slot.get_result(&irgen.ctx).unwrap());
}
// 函数体生成
self.block.irgen(irgen);
// 为函数添加返回基本块(保证每个函数的出口唯一)
function.push_back(&mut irgen.ctx, ret_block).unwrap();
if !irgen.bbk_end_with_terminator() {
// 有可能函数在之前就已经有ret指令
let br2ret = Instruction::br(&mut irgen.ctx, ret_block);
irgen
.cur_bbk
.unwrap()
.push_back(&mut irgen.ctx, br2ret)
.unwrap();
}
if !self.typ.is_void() {
//有返回值
// load, ret
let ret_slot = irgen.cur_ret_slot.unwrap();
let typ = irgen.ast2ir_type(&self.typ);
let load =
Instruction::memaccess(&mut irgen.ctx, MemAccessOp::Load, typ, vec![ret_slot]);
ret_block.push_back(&mut irgen.ctx, load).unwrap();
let val = load.get_result(&irgen.ctx).unwrap();
let ret = Instruction::ret(&mut irgen.ctx, Some(val));
ret_block.push_back(&mut irgen.ctx, ret).unwrap();
} else {
//没有返回值
// just return
let ret = Instruction::ret(&mut irgen.ctx, None);
ret_block.push_back(&mut irgen.ctx, ret).unwrap();
}
irgen.cur_func = None;
irgen.cur_func_id = None;
irgen.cur_bbk = None;
irgen.cur_ret_slot = None;
irgen.cur_ret_bbk = None;
// 离开函数作用域
irgen.symboltable.leave_scope();
}
}
impl IrGen for Decl {
fn irgen(&self, irgen: &mut IrGenContext) {
let entry_block = irgen.cur_func.unwrap().head(&irgen.ctx).unwrap(); //aloca指令都放到入口块中
match self {
Decl::VarDecl(VarDecl { defs, .. }) => {
for VarDef { id, init, .. } in defs {
let init = init.as_ref().unwrap();
let init_val = match init {
InitVal::Exp(exp) => exp,
};
let ir_ty = irgen.ast2ir_type(init_val.typ());
let stack_slot = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Alloca { typ: ir_ty },
ir_ty,
vec![],
);
entry_block.push_front(&mut irgen.ctx, stack_slot).unwrap();
irgen.symboltable.insert(
id,
SymbolEntry {
typ: init_val.typ().clone(),
comptime: None,
ir_value: Some(IrGenResult::Value(
stack_slot.get_result(&irgen.ctx).unwrap(),
)),
},
);
let slot = stack_slot.get_result(&irgen.ctx).unwrap();
Self::init_decl(irgen, init_val, ir_ty, slot);
}
}
}
}
}
impl Decl {
/// 常量和变量声明的初始化
fn init_decl(irgen: &mut IrGenContext, init_val: &Exp, ir_ty: Typ, slot: Value) {
let cur_block = irgen.cur_bbk.unwrap();
// 处理标量常量
if matches!(init_val.kind, ExpKind::Const(ComptimeValue::Undef { .. })) {
return;
}
let init_value = irgen.ast2ir_exp(init_val).unwrap();
let store = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Store,
ir_ty,
vec![init_value, slot],
);
cur_block.push_back(&mut irgen.ctx, store).unwrap();
}
}
impl IrGen for Stmt {
fn irgen(&self, irgen: &mut IrGenContext) {
let cur_block = irgen.cur_bbk.unwrap();
match self {
Stmt::Assign(ast::Assign {
lval: ast::LVal { id },
exp,
}) => {
let entry = irgen.symboltable.lookup(&id).unwrap();
let ir_value = entry.ir_value.unwrap();
let slot = ir_value.unwrap(&mut irgen.ctx);
let val = irgen.ast2ir_exp(&exp).unwrap();
let typ_of_ir = irgen.ast2ir_type(&exp.typ());
let store = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Store,
typ_of_ir,
vec![val, slot],
);
cur_block.push_back(&mut irgen.ctx, store).unwrap();
}
Stmt::ExpStmt(ast::ExpStmt { exp }) => {
if let Some(exp) = exp {
irgen.ast2ir_exp(exp);
}
}
Stmt::Block(bbk) => bbk.irgen(irgen),
Stmt::Return(ast::Return { exp }) => {
if let Some(exp) = exp {
let val = irgen.ast2ir_exp(exp).unwrap();
let typ_of_ir = irgen.ast2ir_type(&exp.typ());
let store = Instruction::memaccess(
&mut irgen.ctx,
MemAccessOp::Store,
typ_of_ir,
vec![val, irgen.cur_ret_slot.unwrap()],
);
irgen
.cur_bbk
.unwrap()
.push_back(&mut irgen.ctx, store)
.unwrap();
}
if !irgen.cur_bbk.unwrap().is_terminated(&irgen.ctx) {
let br = Instruction::br(&mut irgen.ctx, irgen.cur_ret_bbk.unwrap());
irgen
.cur_bbk
.unwrap()
.push_back(&mut irgen.ctx, br)
.unwrap();
}
}
}
}
}
impl IrGen for ast::Block {
fn irgen(&self, irgen: &mut IrGenContext) {
irgen.symboltable.enter_scope();
for item in self.items.iter() {
if irgen.cur_bbk.unwrap().is_terminated(&irgen.ctx) {
return;
}
match item {
BlockItem::Decl(decl) => decl.irgen(irgen),
BlockItem::Stmt(stmt) => stmt.irgen(irgen),
}
}
irgen.symboltable.leave_scope();
}
}

@ -0,0 +1,349 @@
use core::panic;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::{fmt, hash};
// CompUnit -> [CompUnit](Decl|FuncDef)
#[derive(Debug)]
pub struct CompUnit {
pub items: Vec<GlobalItem>,
}
#[derive(Debug)]
pub enum GlobalItem {
Decl(Decl),
FuncDef(FuncDef),
}
// Decl -> VarDecl
#[derive(Debug)]
pub enum Decl {
VarDecl(VarDecl),
}
// VarDecl -> Btype VarDef{',' VarDef}';'
#[derive(Debug)]
pub struct VarDecl {
pub typ: Type,
pub defs: Vec<VarDef>,
}
// VarDef -> Ident{'['ConstExp']'} | Ident{'['ConstExp']'}' '=' InitVal
#[derive(Debug)]
pub struct VarDef {
pub id: String,
pub init: Option<InitVal>,
}
// InitVal -> Exp
#[derive(Debug)]
pub enum InitVal {
Exp(Exp),
}
impl InitVal {
pub fn to_exp(self) -> Exp {
match self {
InitVal::Exp(val) => val,
}
}
}
// FuncDef -> FuncType Ident '(' [FuncFParams] ')' Block
#[derive(Debug)]
pub struct FuncDef {
pub typ: Type,
pub id: String,
pub params: Vec<FuncFParam>,
pub block: Block,
}
#[derive(Debug)]
pub struct FuncFParam {
pub typ: Type,
pub id: String,
}
// Block -> '{'{BlockItem}'}'
#[derive(Debug)]
pub struct Block {
pub items: Vec<BlockItem>,
}
// BlockItem -> Decl | Stmt
#[derive(Debug)]
pub enum BlockItem {
Decl(Decl),
Stmt(Stmt),
}
/* Stmt -> LVal '=' Exp';'
| [Exp]';'
| Block
| 'return' [Exp]';'
*/
#[derive(Debug)]
pub enum Stmt {
Assign(Assign),
ExpStmt(ExpStmt),
Block(Block),
Return(Return),
}
#[derive(Debug)]
pub struct Assign {
pub lval: LVal,
pub exp: Exp,
}
#[derive(Debug)]
pub struct ExpStmt {
pub exp: Option<Exp>,
}
#[derive(Debug)]
pub struct Return {
pub exp: Option<Exp>,
}
#[derive(Debug, Clone)]
pub enum ExpKind {
Const(ComptimeValue),
Binary(BinaryOp, Box<Exp>, Box<Exp>),
LVal(LVal),
}
#[derive(Debug, Clone)]
pub struct Exp {
pub kind: ExpKind,
pub typ: Option<Type>,
}
impl Exp {
pub fn typ(&self) -> &Type {
self.typ.as_ref().unwrap()
}
pub fn const_(val: ComptimeValue) -> Self {
let typ = val.get_type();
Self {
kind: ExpKind::Const(val),
typ: Some(typ),
}
}
pub fn binary(op: BinaryOp, lhs: Exp, rhs: Exp) -> Self {
Self {
kind: ExpKind::Binary(op, Box::new(lhs), Box::new(rhs)),
typ: None,
}
}
pub fn lval(lval: LVal) -> Self {
Self {
kind: ExpKind::LVal(lval),
typ: None,
}
}
}
#[derive(Debug, Clone)]
pub struct LVal {
pub id: String,
}
#[derive(Debug, Clone, Copy)]
pub enum BinaryOp {
Add, //add
}
#[derive(Debug, Clone)]
pub enum ComptimeValue {
Int(i32),
Undef(Type),
}
impl ComptimeValue {
/**
* intint
*/
pub fn unwrap2int(&self) -> i32 {
match self {
ComptimeValue::Int(i) => *i,
ComptimeValue::Undef(_) => {
panic!("Undef Value")
}
}
}
pub fn int(i: i32) -> Self {
ComptimeValue::Int(i)
}
pub fn undef(t: Type) -> Self {
ComptimeValue::Undef(t)
}
pub fn get_type(&self) -> Type {
match self {
ComptimeValue::Int(_) => Type::int(),
ComptimeValue::Undef(t) => t.clone(),
}
}
pub fn is_zero(&self) -> bool {
match self {
ComptimeValue::Int(i) => *i == 0,
ComptimeValue::Undef(_) => false,
}
}
}
/* Start实现ComptimeVal的运算符重载 包含:+*/
impl std::ops::Add for ComptimeValue {
type Output = Self;
fn add(self, other: Self) -> Self {
match (&self, &other) {
// float + int -> TODO! 此处只是举例实际要看实现语法中是否包含这种类型如果存在float那么需要考虑不同类型运算时的类型转化问题
// int + int
(ComptimeValue::Int(x), ComptimeValue::Int(y)) => ComptimeValue::Int(*x + *y),
_ => panic!(
"Type{} + Type{} is not supported",
self.get_type(),
other.get_type()
),
}
}
}
impl PartialEq for ComptimeValue {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(ComptimeValue::Int(x), ComptimeValue::Int(y)) => x == y,
(ComptimeValue::Undef(_x), ComptimeValue::Undef(_y)) => false,
_ => false,
}
}
}
impl Eq for ComptimeValue {}
/* End: 实现ComptimeVal的运算符重载 */
#[derive(Debug, Eq, Hash, PartialEq, Clone)]
pub enum TypeKind {
Void,
Int,
Ptr(Box<Type>),
Function(Vec<Type>, Box<Type>),
}
#[derive(Clone, Eq)]
pub struct Type(Rc<TypeKind>);
/* 此处代码参考https://github.com/JuniMay/orzcc */
impl hash::Hash for Type {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl PartialEq for Type {
// Just compare the pointers
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}
impl fmt::Debug for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind() {
TypeKind::Void => write!(f, "void"),
TypeKind::Int => write!(f, "int"),
TypeKind::Ptr(t) => write!(f, "{}*", t),
TypeKind::Function(params, ret) => write!(
f,
"{}({})",
ret,
params
.iter()
.map(|t| t.to_string())
.collect::<Vec<_>>()
.join(", ")
),
}
}
}
impl Type {
thread_local! {
/// The pool to implement singleton.
///
/// Reference: https://github.com/pku-minic/koopa/blob/master/src/ir/types.rs
///
/// XXX: This is not the only solution. In the implementation of IR, we use
/// `UniqueArena` to store types.
static POOL: RefCell<HashMap<TypeKind, Type>> = RefCell::new(HashMap::default());
}
/// Create x new type.
pub fn make(kind: TypeKind) -> Type {
Self::POOL.with(|pool| {
let mut pool = pool.borrow_mut();
if let Some(typ) = pool.get(&kind) {
typ.clone()
} else {
let typ = Type(Rc::new(kind.clone()));
pool.insert(kind, typ.clone());
typ
}
})
}
/// Get the kind of the type.
pub fn kind(&self) -> &TypeKind {
&self.0
}
/// Create x new void type.
pub fn void() -> Self {
Self::make(TypeKind::Void)
}
/// Create x new integer type.
pub fn int() -> Self {
Self::make(TypeKind::Int)
}
/// Create x new function type.
pub fn function(params: Vec<Type>, ret: Type) -> Self {
Self::make(TypeKind::Function(params, Box::new(ret)))
}
pub fn is_int(&self) -> bool {
matches!(self.kind(), TypeKind::Int)
}
pub fn is_void(&self) -> bool {
matches!(self.kind(), TypeKind::Void)
}
pub fn unwrap_func(&self) -> (Vec<Type>, Type) {
if let TypeKind::Function(params, ret) = self.kind() {
let params = params.clone();
let ret = ret.clone();
(params, *ret)
} else {
panic!("unwrap_func: not x function type: {}", self);
}
}
}

@ -0,0 +1,134 @@
use crate::frontend::lalrpop::ast::*;
grammar;
match {
r"\s*" => {},
r"//[^\n\r]*[\n\r]*" => {},
r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/" => {},
_
}
// Terminal symbols definition
Ident: String = r"[_a-zA-Z][_a-zA-Z0-9]*" => <>.to_string();
Int: i32 = {
r"[1-9][0-9]*" => i32::from_str_radix(<>, 10).unwrap(),
r"0[0-7]*" => i32::from_str_radix(<>, 8).unwrap(),
r"0[xX][0-9a-fA-F]+" => i32::from_str_radix(&<>[2..], 16).unwrap(),
}
// Number -> IntConst
pub Number: ComptimeValue = {
<n: Int> => ComptimeValue::int(n),
}
// Nonterminal symbols definition
// CompUnit -> [CompUnit](Decl|FuncDef)
pub CompUnit: CompUnit = <items: (GlobalItem)*> => CompUnit{ <> };
GlobalItem: GlobalItem = {
Decl => GlobalItem::Decl(<>),
FuncDef => GlobalItem::FuncDef(<>),
}
// Decl -> VarDecl
Decl: Decl = {
VarDecl => Decl::VarDecl(<>),
}
// BType -> "int" | "void"
pub BType: Type = {
"int" => Type::int(),
"void" => Type::void(),
}
// VarDecl -> BType VarDef { ',' VarDef } ';'
VarDecl: VarDecl = {
<typ: BType> <def: VarDef> <mut defs: ("," <VarDef>)*> ";" => {
defs.insert(0, def);
VarDecl { typ, defs }
}
}
// VarDef -> Ident { '[' ConstExp ']' }
// | Ident { '[' ConstExp ']' } '=' InitVal
VarDef: VarDef = {
<id: Ident> <init: ("=" <InitVal>)?> => VarDef { id, init }
}
// InitVal -> Exp
InitVal: InitVal = {
Exp => InitVal::Exp(<>),
}
// FuncDef -> FuncType Ident '(' FuncFParams ')' Block
pub FuncDef: FuncDef = {
<typ: BType> <id: Ident> "(" ")" <block: Block> => FuncDef { typ, id, params: vec![], block },
<typ: BType> <id: Ident> "(" <params: FuncFParams> ")" <block: Block> => {
FuncDef { typ, id, params, block }
}
}
// FuncFParams -> FuncFParam { ',' FuncFParam }
FuncFParams: Vec<FuncFParam> = {
<param: FuncFParam> <mut params: ("," <FuncFParam>)*> => {
params.insert(0, param);
params
}
}
// FuncFParam -> BType Ident [ '[' ']' { '[' Exp ']' } ]
FuncFParam: FuncFParam = {
<typ: BType> <id: Ident> => {
FuncFParam { typ, id }
},
}
// Block -> '{' { BlockItem } '}'
Block: Block = {
"{" <items: (BlockItem)*> "}" => Block { items }
}
// BlockItem -> Decl|Stmt
BlockItem: BlockItem = {
Decl => BlockItem::Decl(<>),
Stmt => BlockItem::Stmt(<>),
}
Stmt: Stmt = {
<lval: LVal> "=" <exp: Exp> ";" => Stmt::Assign(Assign { <> }),
<exp: (Exp)?> ";" => Stmt::ExpStmt(ExpStmt { <> }),
Block => Stmt::Block(<>),
"return" <exp: (Exp)?> ";" => Stmt::Return(Return { <> }),
}
// LVal -> Ident { '[' Exp ']' }
LVal: LVal = <id: Ident> => LVal { <> };
// PrimaryExp -> '(' Exp ')' | LVal | Number
pub PrimaryExp: Exp = {
"(" <e: Exp> ")" => e,
<v: LVal> => Exp::lval(v),
<n: Number> => Exp::const_(n),
}
// UnaryExp -> PrimaryExp
// | Ident '(' [ FuncRParams ] ')'
// | UnaryOp UnaryExp
pub UnaryExp: Exp = {
PrimaryExp => <>,
"+" <e: UnaryExp> => e,
}
// AddExp -> UnaryExp | AddExp ('+') UnaryExp
pub AddExp: Exp = {
UnaryExp => <>,
<lhs: AddExp> "+" <rhs: UnaryExp> => Exp::binary(BinaryOp::Add, lhs, rhs),
}
// Exp -> AddExp
pub Exp: Exp = AddExp => <>;
// ConstExp -> AddExp
// pub ConstExp: Exp = AddExp => <>;

@ -0,0 +1,18 @@
pub mod ir;
pub mod ir2string;
pub mod irgen;
pub mod lalrpop;
pub mod symboltable;
pub mod typecheck;
pub fn irgen(ast: &mut lalrpop::ast::CompUnit, ptr_width: u8) -> ir::context::Context {
let mut irgen = irgen::IrGenContext::default();
irgen.ctx.set_target(ptr_width as usize);
crate::frontend::lalrpop::ast::CompUnit::type_check(ast);
<crate::frontend::lalrpop::ast::CompUnit as irgen::IrGen>::irgen(ast, &mut irgen);
irgen.context()
}

@ -0,0 +1,75 @@
use rustc_hash::FxHashMap as HashMap;
use super::{
irgen::IrGenResult,
lalrpop::ast::{ComptimeValue, Type},
};
#[derive(Debug)]
pub struct SymbolEntry {
pub typ: Type,
pub comptime: Option<ComptimeValue>,
pub ir_value: Option<IrGenResult>,
}
impl SymbolEntry {
pub fn from_ty(typ: Type) -> Self {
Self {
typ,
comptime: None,
ir_value: None,
}
}
}
#[derive(Default)]
pub struct SymbolTable {
stack: Vec<HashMap<String, SymbolEntry>>,
pub curr_ret_ty: Option<Type>,
}
impl SymbolTable {
pub fn enter_scope(&mut self) {
self.stack.push(HashMap::default());
}
pub fn leave_scope(&mut self) {
self.stack.pop();
}
pub fn insert(&mut self, name: impl Into<String>, entry: SymbolEntry) {
self.stack.last_mut().unwrap().insert(name.into(), entry);
}
pub fn insert_upper(&mut self, name: impl Into<String>, entry: SymbolEntry, upper: usize) {
self.stack
.iter_mut()
.rev()
.nth(upper)
.unwrap()
.insert(name.into(), entry);
}
pub fn lookup(&self, name: &str) -> Option<&SymbolEntry> {
for scope in self.stack.iter().rev() {
if let Some(entry) = scope.get(name) {
return Some(entry);
}
}
None
}
pub fn lookup_mut(&mut self, name: &str) -> Option<&mut SymbolEntry> {
for scope in self.stack.iter_mut().rev() {
if let Some(entry) = scope.get_mut(name) {
return Some(entry);
}
}
None
}
pub fn register_sysylib(&mut self) {
assert_eq!(self.stack.len(), 1);
// TODO!
}
}

@ -0,0 +1,246 @@
use crate::frontend;
use crate::frontend::lalrpop::ast::{*};
use crate::frontend::symboltable::*;
impl CompUnit {
pub fn type_check(&mut self) {
let mut symtable = SymbolTable::default();
// 全局作用域
symtable.enter_scope();
// 注册系统库
symtable.register_sysylib();
for item in self.items.iter_mut() {
item.type_check(&mut symtable);
}
// 退出全局作用域
symtable.leave_scope();
}
}
impl GlobalItem {
pub fn type_check(&mut self, symtable: &mut SymbolTable) {
match self {
GlobalItem::Decl(decl) => match decl {
Decl::VarDecl(decl) => decl.type_check(symtable),
},
GlobalItem::FuncDef(FuncDef {
typ,
id,
params,
block,
}) => {
symtable.enter_scope();
// 插入函数参数到作用域
let mut param_tys = Vec::new();
for param in params.iter() {
let typ = param.typ.clone();
param_tys.push(typ.clone());
symtable.insert(param.id.clone(), SymbolEntry::from_ty(typ.clone()));
}
let func_ty = Type::function(param_tys, typ.clone());
// 插入函数符号到作用域,位于当前作用域之上,因为我们处于参数作用域
symtable.insert_upper(id.clone(), SymbolEntry::from_ty(func_ty), 1);
symtable.curr_ret_ty = Some(typ.clone());
block.type_check(symtable);
symtable.curr_ret_ty = None;
symtable.leave_scope();
}
}
}
}
impl VarDecl {
pub fn type_check(&mut self, symtable: &mut SymbolTable) {
let mut new_defs = Vec::new();
for mut def in self.defs.drain(..) {
let typ = self.typ.clone();
let init = def
.init
.map(|init| {
// fold as much as possible
let typed_init = init.type_check(Some(&typ), symtable);
match typed_init.try_fold(symtable) {
Some(val) => Exp::const_(val),
None => typed_init,
}
})
.unwrap_or_else(|| {
let undef = ComptimeValue::undef(typ.clone());
Exp::const_(undef)
});
def.init = Some(frontend::lalrpop::ast::InitVal::Exp(init));
symtable.insert(def.id.clone(), SymbolEntry::from_ty(typ));
new_defs.push(def);
}
self.defs = new_defs;
}
}
impl InitVal {
pub fn type_check(self, expect_type: Option<&Type>, symboltable: &mut SymbolTable) -> Exp {
match self {
InitVal::Exp(exp) => exp.type_check(expect_type, symboltable),
}
}
}
impl Block {
pub fn type_check(&mut self, symtable: &mut SymbolTable) {
// 进入块作用域
symtable.enter_scope();
let mut new_items = Vec::new();
for item in self.items.drain(..) {
let item = match item {
BlockItem::Decl(decl) => match decl {
Decl::VarDecl(mut decl) => {
decl.type_check(symtable);
BlockItem::Decl(Decl::VarDecl(decl))
}
},
BlockItem::Stmt(stmt) => {
let stmt = stmt.type_check(symtable);
BlockItem::Stmt(stmt)
}
};
new_items.push(item);
}
self.items = new_items;
symtable.leave_scope();
}
}
impl Stmt {
pub fn type_check(self, symtable: &mut SymbolTable) -> Self {
match self {
Stmt::Assign(Assign { lval, exp }) => {
let id = lval.id; // 直接获取 id 的所有权
let entry = symtable.lookup(&id).expect("variable not found");
// 计算最终类型(例如处理数组维度)
let typ = &entry.typ;
// 类型检查表达式
let expr = exp.type_check(Some(typ), symtable);
// 重构 Assign 结构体
let assign = Stmt::Assign(Assign {
lval: LVal {
id, // 使用已解构的 id
},
exp: expr,
});
assign
}
Stmt::ExpStmt(ExpStmt { exp }) => {
let expr = exp.map(|expr| expr.type_check(None, symtable));
Stmt::ExpStmt(ExpStmt { exp: expr })
}
Stmt::Block(mut block) => {
block.type_check(symtable);
Stmt::Block(block)
}
Stmt::Return(Return { exp }) => {
let exp = exp.map(|expr| expr.type_check(symtable.curr_ret_ty.as_ref(), symtable));
if exp.is_none() {
return Stmt::Return(Return { exp });
}
let exp = exp.unwrap();
let ret_ty = symtable.curr_ret_ty.as_ref().unwrap();
if ret_ty.is_int() ^ exp.typ().is_int() {
panic!("unsupported return type");
}
Stmt::Return(Return { exp: Some(exp) })
}
}
}
}
impl Exp {
/// 类型检查表达式,返回类型正确的表达式。
pub fn get_type(&self) -> &Type {
self.typ.as_ref().unwrap()
}
/// 常量折叠
pub fn try_fold(&self, symtable: &SymbolTable) -> Option<ComptimeValue> {
match &self.kind {
ExpKind::Const(val) => Some(val.clone()),
ExpKind::Binary(op, lhs, rhs) => {
let lhs = lhs.try_fold(symtable)?;
let rhs = rhs.try_fold(symtable)?;
match op {
BinaryOp::Add => Some(lhs + rhs),
}
}
ExpKind::LVal(LVal { id}) => {
let entry = symtable.lookup(id).unwrap();
let val = entry.comptime.as_ref()?.clone();
Some(val)
}
}
}
pub fn type_check(mut self, expect: Option<&Type>, symtable: &SymbolTable) -> Self {
if self.typ.is_some() && expect.is_none() {
return self;
}
let mut expr = match self.kind {
ExpKind::Const(_) => self,
ExpKind::Binary(op, lhs, rhs) => {
let lhs = lhs.type_check(None, symtable);
let rhs = rhs.type_check(None, symtable);
let lhs_ty = lhs.get_type().clone();
let mut expr = Exp::binary(op, lhs, rhs);
match op {
BinaryOp::Add => {
expr.typ = Some(lhs_ty.clone());
}
}
expr
}
ExpKind::LVal(LVal { id }) => {
let entry = symtable.lookup(&id).unwrap();
let typ = entry.typ.clone();
let mut expr = Exp::lval(LVal {
id,
});
expr.typ = Some(typ);
expr
}
};
if let Some(typ) = expect {
if typ.is_int() {
expr.typ = Some(typ.clone());
} else if typ != expr.get_type() {
panic!("unsupported type coercion: {:?}", typ);
}
}
if let Some(comptime) = expr.try_fold(symtable) {
expr = Exp::const_(comptime);
}
expr
}
}

@ -0,0 +1,113 @@
use lalrpop_util::lalrpop_mod;
use rustc_hash::FxHashMap as HashMap;
use std::io::Result;
pub mod backend;
pub mod frontend;
pub mod utils;
//指定生成的代码的位置
lalrpop_mod!(#[allow(clippy::all)] pub sysy, "/frontend/lalrpop/sysy.rs");
/// 解析命令行参数
fn parse_arguments() -> HashMap<String, String> {
let mut args_map = HashMap::default();
let args: Vec<String> = std::env::args().collect();
let mut i = 0;
while i < args.len() {
let arg = args[i].as_str();
if arg == "-ast" {
args_map.insert(String::from("ast"), args[i + 1].to_string());
i += 1;
} else if arg == "-ir" {
args_map.insert(String::from("ir"), args[i + 1].to_string());
i += 1;
} else if arg == "-asm" {
args_map.insert(String::from("asm"), args[i + 1].to_string());
i += 1;
} else if arg == "-S" {
args_map.insert(String::from("S"), String::from("true"));
} else if arg == "-o" {
args_map.insert(String::from("o"), args[i + 1].to_string());
i += 1;
} else if arg == "-O1" {
args_map.insert(String::from("O1"), String::from("true"));
} else if arg == "-h" {
println!("[Compiler] Usage:");
println!("[Compiler] compiler [options] source_file");
println!("[Compiler] Options:");
println!("[Compiler] -ast <file> : Output the AST to a file");
println!("[Compiler] -ir <file> : Output the IR to a file");
println!(
"[Compiler] -asm <file> : Output the ASM to a file( Has higher priority than -S!!! )"
);
println!("[Compiler] -S : Output the ASM to stdout");
println!("[Compiler] -o <file> : Output the ASM to a file");
println!("[Compiler] -O1 : Enable optimization level 1");
std::process::exit(0);
} else {
args_map.insert(String::from("source"), arg.to_string());
}
i += 1;
}
args_map
}
/// 检查命令行参数
fn check_args(args: &HashMap<String, String>) {
let emit_s = if args.get("S").is_some() && args.get("S").unwrap() == "true" {
true
} else {
false
};
let source = args.get("source");
let output_file = args.get("o");
if source.is_none() {
panic!("Error: Source file `{}` not specified", source.unwrap());
}
if output_file.is_none() && emit_s {
panic!("Error: Output file not specified");
}
if !std::path::Path::new(source.unwrap()).exists() {
panic!("Error: Source file `{}` not found", source.unwrap());
}
}
fn main() -> Result<()> {
// 参数解析与检查
let args = parse_arguments();
check_args(&args);
// 提取参数
let emit_ast = args.get("ast"); // 输出AST文件
let emit_ir = args.get("ir"); // 输出IR文件
let emit_asm = args.get("asm"); // 输出ASM文件
let emit_s = matches!(args.get("S"), Some(v) if v == "true"); // 适配比赛编译器选项要求,表示生成汇编代码
let _optimize = matches!(args.get("O1"), Some(v) if v == "true"); // 优化选项
let source = args.get("source"); // 源文件名
let output_file = args.get("o"); // 输出文件名
let src = std::fs::read_to_string(source.unwrap())?; // 读取源文件内容
let mut ast = sysy::CompUnitParser::new().parse(&src).unwrap();
if let Some(ast_file) = emit_ast {
std::fs::write(ast_file, format!("{:#?}", ast)).expect("Failed to write AST to file");
}
let mut ir = frontend::irgen(&mut ast, 8); // ARMV8架构
if let Some(ir_file) = emit_ir {
std::fs::write(ir_file, ir.get_ir_string()).expect("Failed to write IR to file");
}
let mir = backend::mirgen(&mut ir);
if emit_s || emit_asm.is_some() {
let mut asm_file = output_file;
if emit_asm.is_some() {
asm_file = emit_asm;
}
std::fs::write(asm_file.unwrap(), mir.get_asm()).expect("Failed to write ASM to file");
}
Ok(())
}

@ -0,0 +1,530 @@
/// 链表错误操作方法
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LinkedListError<N> {
/// 节点已经在链表中
NodeAlreadyInContainer(N),
/// 不允许删除不在链表中的节点
PositionNodeNotInContainer(N),
/// 当前节点没有链接
CurrentNodeNotLinked(N),
}
impl<N> From<LinkedListError<N>> for String
where
N: std::fmt::Debug,
{
fn from(err: LinkedListError<N>) -> String {
format!("LinkedListError: {:?}", err)
}
}
/// 链表操作方法
/// # 参数列表
/// - `Node`: 链表节点类型
pub trait LinkedListContainer<Node>: Copy + Eq
where
Node: LinkedListNode<Ctx = Self::Ctx, Container = Self>,
{
/// 节点的上下文环境与容器的上下文环境一致,来自同一个内存池。
type Ctx;
/// 获取链表头节点
fn head(self, ctx: &Self::Ctx) -> Option<Node>;
/// 设置链表头节点
fn set_head(self, ctx: &mut Self::Ctx, head: Option<Node>);
/// 获取链表尾节点
fn tail(self, ctx: &Self::Ctx) -> Option<Node>;
/// 设置链表尾节点
fn set_tail(self, ctx: &mut Self::Ctx, tail: Option<Node>);
/// 在链表前面添加节点
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `node`: 添加的节点
///
/// # 返回值
/// - [`Ok`]: 操作成功
/// - [`LinkedListError::NodeAlreadyInContainer`]: 节点已存在链表中
fn push_front(self, ctx: &mut Self::Ctx, node: Node) -> Result<(), LinkedListError<Node>> {
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(head) = self.head(ctx) {
head.insert_before(ctx, node)
.unwrap_or_else(|_| unreachable!());
} else {
self.set_head(ctx, Some(node));
self.set_tail(ctx, Some(node));
node.set_container(ctx, Some(self));
}
Ok(())
}
/// 在链表后面添加节点
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `node`: 添加的节点
///
/// # 返回值
/// - [`Ok`]: 操作成功
/// - [`LinkedListError::NodeAlreadyInContainer`]: 节点已存在链表中
fn push_back(self, ctx: &mut Self::Ctx, node: Node) -> Result<(), LinkedListError<Node>> {
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(tail) = self.tail(ctx) {
tail.insert_after(ctx, node)
.unwrap_or_else(|_| unreachable!());
} else {
self.set_head(ctx, Some(node));
self.set_tail(ctx, Some(node));
node.set_container(ctx, Some(self));
}
Ok(())
}
/// 将另外一个链表中的所有节点移动到当前链表
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `other`: 要排空的容器
fn append(self, ctx: &mut Self::Ctx, other: Self) {
let mut cur = other.head(ctx);
while let Some(node) = cur {
let succ = node.succ(ctx);
node.unlink(ctx);
self.push_back(ctx, node).unwrap_or_else(|_| unreachable!());
cur = succ;
}
debug_assert!(other.head(ctx).is_none());
debug_assert!(other.tail(ctx).is_none());
}
/// 在指定位置将链表分成两个链表,分开后指定位置节点属于第一个链表
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `other`: 另一个存链表的存储器
/// - `pos`: 指定分离位置
///
/// # 返回值
/// - [`Ok`]:操作成功
/// - [`LinkedListError::PositionNodeNotInContainer`]:节点不在容器中
fn split(
self,
ctx: &mut Self::Ctx,
other: Self,
pos: Node,
) -> Result<(), LinkedListError<Node>> {
if pos.container(ctx) != Some(self) {
return Err(LinkedListError::PositionNodeNotInContainer(pos));
}
let mut curr = self.tail(ctx);
while let Some(node) = curr {
if node == pos {
break;
}
let pre = node.pre(ctx);
node.unlink(ctx);
other
.push_front(ctx, node)
.unwrap_or_else(|_| unreachable!());
curr = pre;
}
debug_assert!(self.tail(ctx) == Some(pos));
Ok(())
}
/// 创建链表的迭代器
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
///
/// # Returns
/// 创建的迭代器
fn iter(self, ctx: &Self::Ctx) -> LinkedListIterator<Node> {
LinkedListIterator {
ctx,
curr_forward: self.head(ctx),
curr_backward: self.tail(ctx),
}
}
/// 用迭代器中的节点扩展链表
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `iter`: 用来扩展的节点的迭代器
///
/// # 返回值
/// - [`Ok`]: 操作成功
/// - [`LinkedListError`]: 操作错误
fn extend<I: IntoIterator<Item = Node>>(
self,
ctx: &mut Self::Ctx,
iter: I,
) -> Result<(), LinkedListError<Node>> {
for node in iter {
self.push_back(ctx, node)?;
}
Ok(())
}
/// 创建链表游标
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `strategy`: 获取下一个节点的游标策略
///
/// # 返回值
/// 创建的游标
fn cursor(self, ctx: &Node::Ctx, strategy: CursorStrategy) -> LinkedListCursor<Node> {
LinkedListCursor::new(self, ctx, strategy, CursorDirection::Forward)
}
}
/// 链表节点操作方法
pub trait LinkedListNode: Copy + Eq {
/// 存储链表的容器
type Container: LinkedListContainer<Self, Ctx = Self::Ctx>;
/// 访问数据的环境类型
type Ctx;
/// 获取后继节点
fn succ(self, ctx: &Self::Ctx) -> Option<Self>;
/// 获取前驱节点
fn pre(self, ctx: &Self::Ctx) -> Option<Self>;
/// 获取存储链表的容器
fn container(self, ctx: &Self::Ctx) -> Option<Self::Container>;
/// 设置后继节点
fn set_succ(self, ctx: &mut Self::Ctx, succ: Option<Self>);
/// 设置前驱节点
fn set_pre(self, ctx: &mut Self::Ctx, pre: Option<Self>);
/// 创建一个容器存储链表
fn set_container(self, ctx: &mut Self::Ctx, container: Option<Self::Container>);
/// 在这个节点后插入节点
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `node`: 被插入的节点
///
/// # 返回值
/// - [`Ok`]: 插入成功
/// - [`LinkedListError::CurrentNodeNotLinked`]: 当前节点不在链表中
/// - [`LinkedListError::NodeAlreadyInContainer`]:待插入的节点已经在链表中
fn insert_after(self, ctx: &mut Self::Ctx, node: Self) -> Result<(), LinkedListError<Self>> {
if self.container(ctx).is_none() {
return Err(LinkedListError::CurrentNodeNotLinked(self));
}
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(succ) = self.succ(ctx) {
succ.set_pre(ctx, Some(node));
node.set_succ(ctx, Some(succ));
}
node.set_pre(ctx, Some(self));
self.set_succ(ctx, Some(node));
match self.container(ctx) {
Some(container) => {
if container.tail(ctx) == Some(self) {
container.set_tail(ctx, Some(node));
}
}
None => unreachable!(),
}
node.set_container(ctx, self.container(ctx));
Ok(())
}
/// 在借钱前面插入一个节点
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `node`: 被插入的节点
///
/// # 返回值
/// - [`Ok`]: 插入成功
/// - [`LinkedListError::CurrentNodeNotLinked`]: 当前节点不在链表中
/// - [`LinkedListError::NodeAlreadyInContainer`]:待插入的节点已经在链表中
fn insert_before(self, ctx: &mut Self::Ctx, node: Self) -> Result<(), LinkedListError<Self>> {
if self.container(ctx).is_none() {
return Err(LinkedListError::CurrentNodeNotLinked(self));
}
if node.container(ctx).is_some() {
return Err(LinkedListError::NodeAlreadyInContainer(node));
}
if let Some(pre) = self.pre(ctx) {
pre.set_succ(ctx, Some(node));
node.set_pre(ctx, Some(pre));
}
node.set_succ(ctx, Some(self));
self.set_pre(ctx, Some(node));
match self.container(ctx) {
Some(container) => {
if container.head(ctx) == Some(self) {
container.set_head(ctx, Some(node));
}
}
None => unreachable!(),
}
node.set_container(ctx, self.container(ctx));
Ok(())
}
/// 取消该节点的链接但不会冲arena中移除
/// # Parameters
/// - `ctx`: 获取数据的环境如内存池Arena
fn unlink(self, ctx: &mut Self::Ctx) {
let pre = self.pre(ctx);
let succ = self.succ(ctx);
if let Some(pre) = pre {
pre.set_succ(ctx, succ);
}
if let Some(succ) = succ {
succ.set_pre(ctx, pre);
}
if let Some(container) = self.container(ctx) {
if container.head(ctx) == Some(self) {
container.set_head(ctx, succ);
}
if container.tail(ctx) == Some(self) {
container.set_tail(ctx, pre);
}
}
self.set_pre(ctx, None);
self.set_succ(ctx, None);
self.set_container(ctx, None);
}
/// 在这个节点后扩展链表
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `iter`: 扩展的迭代器
///
/// # 返回值
/// - [`Ok`]:扩展成功
/// - [`LinkedListError`]: 扩展失败
fn extend_after<I>(self, ctx: &mut Self::Ctx, iter: I) -> Result<(), LinkedListError<Self>>
where
I: IntoIterator<Item = Self>,
{
let mut last = self;
for node in iter {
last.insert_after(ctx, node)?;
last = node;
}
Ok(())
}
/// 在这个节点前扩展链表,不改变本来的节点顺序
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `iter`: 扩展的迭代器
///
/// # 返回值
/// - [`Ok`]:扩展成功
/// - [`LinkedListError`]: 扩展失败
fn extend_before<I>(self, ctx: &mut Self::Ctx, iter: I) -> Result<(), LinkedListError<Self>>
where
I: IntoIterator<Item = Self>,
{
for node in iter {
self.insert_before(ctx, node)?;
}
Ok(())
}
}
///链表的双端迭代器
/// # Lifetimes
/// - `a`: 迭代器生命周期
///
/// # 参数类型
/// - `T`: 链表节点类型
pub struct LinkedListIterator<'a, T: LinkedListNode> {
ctx: &'a T::Ctx,
curr_forward: Option<T>,
curr_backward: Option<T>,
}
impl<'a, T: LinkedListNode> Iterator for LinkedListIterator<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let curr = self.curr_forward;
self.curr_forward = curr.and_then(|node| node.succ(self.ctx));
curr
}
}
impl<'a, T: LinkedListNode> DoubleEndedIterator for LinkedListIterator<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let curr = self.curr_backward;
self.curr_backward = curr.and_then(|node| node.pre(self.ctx));
curr
}
}
/// 游标获取下一个节点的策略
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CursorStrategy {
/// 先获取下一个节点,再访问当前节点
Pre,
/// 先访问当前节点,再获取下一个节点。第一个节点并不会在构建游标时被立即获取,而是在调用 LinkedListCursor::succ 方法时获取。
Post,
}
/// 链表游标移动的方向
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CursorDirection {
/// 正向移动
Forward,
/// 反向移动
Backward,
}
/// 链表的游标
/// # 参数类型
/// - `T`: 链表节点的类型
pub struct LinkedListCursor<T: LinkedListNode> {
/// 链表的容器
container: T::Container,
/// 当前的链表节点对于Pre这是下一个要访问的节点对于Post这是当前节点
curr: Option<T>,
/// 当前游标策略
strategy: CursorStrategy,
/// 当前游标方向
direction: CursorDirection,
///正向迭代结束的指示器
done: bool,
}
impl<T> LinkedListCursor<T>
where
T: LinkedListNode,
{
fn new(
container: T::Container,
ctx: &T::Ctx,
strategy: CursorStrategy,
direction: CursorDirection,
) -> Self {
let mut cursor = Self {
container,
curr: None,
strategy,
direction,
done: false,
};
match cursor.strategy {
CursorStrategy::Pre => match cursor.direction {
CursorDirection::Forward => cursor.curr = cursor.container.head(ctx),
CursorDirection::Backward => cursor.curr = cursor.container.tail(ctx),
},
CursorStrategy::Post => {}
}
cursor
}
/// 反转游标方向
pub fn rev(mut self, ctx: &T::Ctx) -> Self {
self.direction = match self.direction {
CursorDirection::Forward => CursorDirection::Backward,
CursorDirection::Backward => CursorDirection::Forward,
};
self.done = false;
match self.strategy {
CursorStrategy::Pre => match self.direction {
CursorDirection::Forward => self.curr = self.container.head(ctx),
CursorDirection::Backward => self.curr = self.container.tail(ctx),
},
CursorStrategy::Post => self.curr = None,
}
self
}
/// 迭代结束
pub fn is_done(&self) -> bool {
self.done
}
/// 移动游标访问下一个节点
pub fn succ(&mut self, ctx: &T::Ctx) -> Option<T> {
match self.strategy {
CursorStrategy::Pre => {
let curr = self.curr;
match curr {
Some(curr) => match self.direction {
CursorDirection::Forward => self.curr = curr.succ(ctx),
CursorDirection::Backward => self.curr = curr.pre(ctx),
},
None => self.done = true,
}
curr
}
CursorStrategy::Post => {
match self.curr {
Some(curr) => match self.direction {
CursorDirection::Forward => self.curr = curr.succ(ctx),
CursorDirection::Backward => self.curr = curr.pre(ctx),
},
None if self.done => return None,
// 初始状态
None => match self.direction {
CursorDirection::Forward => self.curr = self.container.head(ctx),
CursorDirection::Backward => self.curr = self.container.tail(ctx),
},
}
self.done = self.curr.is_none();
self.curr
}
}
}
/// 使用闭包迭代链表
/// # 参数列表
/// - `ctx`: 获取数据的环境如内存池Arena
/// - `f`: 每个节点的闭包
pub fn for_each<F: FnMut(&mut T::Ctx, T)>(self, ctx: &mut T::Ctx, mut f: F) {
let mut cursor = self;
while let Some(node) = cursor.succ(ctx) {
f(ctx, node);
}
}
}

@ -0,0 +1,2 @@
pub mod linked_list;
pub mod storage;

@ -0,0 +1,427 @@
use std::{fmt, mem};
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use std::hash::{DefaultHasher, Hash, Hasher};
/**Arena指针特性:
* `type Arena: Arena<Self>` [`Arena`]`<Ptr: ArenaPtr<Arena = Self>>`
* Ptr Arena Arena 使
* ```text
*
* Arena<Ptr> ArenaPtr
*
* () ()
* type Arena
*
*
*
*
* Ptr: ArenaPtr<Arena = Self>
* ```
*/
pub trait ArenaPtr: Copy + Eq + Hash {
type Arena: Arena<Self>;
type Data;
/**
* # Parameters
* self:
* arena:
* # Return
* Data
*
*/
fn deref(self, arena: &Self::Arena) -> Option<&Self::Data> {
arena.deref(self)
}
/**
* # Parameters
* self:
* arena:
* # Return
* Data
*/
fn deref_mut(self, arena: &mut Self::Arena) -> Option<&mut Self::Data> {
arena.deref_mut(self)
}
}
/* `Arena`特性 */
pub trait Arena<Ptr: ArenaPtr<Arena = Self>>{
/**
* # Parameters
* self:
* f: `Ptr``Ptr::Data`
* # Return
*
*/
fn alloc_with<F>(&mut self, f: F) -> Ptr
where
F: FnOnce(Ptr) -> Ptr::Data;
fn alloc(&mut self, data: Ptr::Data) -> Ptr { self.alloc_with(|_| data) }
fn dealloc(&mut self, ptr: Ptr) -> Option<Ptr::Data>;
fn deref(&self, ptr: Ptr) -> Option<&Ptr::Data>;
fn deref_mut(&mut self, ptr: Ptr) -> Option<&mut Ptr::Data>;
}
/* 实现了`ArenaPtr`特性的一个基础结构体 */
pub struct GenericPtr<Data> {
index: usize,
_phantom: PhantomData<Data>,
}
impl<Data> GenericPtr<Data> {
fn from_index(index: usize) -> Self {
Self {
index,
_phantom: PhantomData,
}
}
}
pub trait Idx: Copy + Ord + Hash {
fn index(self) -> usize;
}
impl<Data> Idx for GenericPtr<Data> {
fn index(self) -> usize { self.index }
}
impl<Data> Clone for GenericPtr<Data> {
fn clone(&self) -> Self { *self }
}
impl<Data> Copy for GenericPtr<Data> {}
impl<Data> Hash for GenericPtr<Data> {
fn hash<H: Hasher>(&self, state: &mut H) { self.index.hash(state) }
}
impl<Data> PartialEq for GenericPtr<Data> {
fn eq(&self, other: &Self) -> bool { self.index == other.index }
}
impl<Data> Eq for GenericPtr<Data> {}
impl<Data> PartialOrd for GenericPtr<Data> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl<Data> Ord for GenericPtr<Data> {
fn cmp(&self, other: &Self) -> Ordering { self.index.cmp(&other.index) }
}
impl<Data> fmt::Debug for GenericPtr<Data> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "*{}", self.index) }
}
impl<Data> fmt::Display for GenericPtr<Data> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "*{}", self.index) }
}
impl<Data> fmt::Pointer for GenericPtr<Data> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "*{:x}", self.index) }
}
impl<Data> fmt::LowerHex for GenericPtr<Data> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "*{:x}", self.index) }
}
impl<Data> fmt::UpperHex for GenericPtr<Data> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "*{:X}", self.index) }
}
pub enum GenericEntry<Data> {
/// 条目是空的,空闲列表并不是按照索引顺序进行排序的,而是按照内存释放的顺序来排序的,最后一个被释放的条目会成为空闲列表中的第一个条目。
Vacant {
/// 下一个空位的索引
next: Option<usize>,
},
/// 条目被占用
Occupied(Data),
}
/* 实现了`Arena`特性的一个基础结构体 */
pub struct GenericArena<Data> {
/* Arena中的所有条目 */
entries: Vec<GenericEntry<Data>>,
/* 空闲列表头部 */
free_head: Option<usize>,
}
/* `Default`特性,`GenericArena`的默认构造 */
impl<Data> Default for GenericArena<Data> {
fn default() -> Self {
Self {
entries: Vec::new(),
free_head: None,
}
}
}
impl<Data> GenericArena<Data> {
/**预留出额外的空间
* # Parameters
* self
* additional: usize
* # Return
* None
*/
pub fn reserve(&mut self, additional: usize) { self.entries.reserve(additional) }
/**创建一个容量为capacity的内存池
* # Parameters
* capacity
* # Return
* Self
*/
pub fn with_capacity(capacity: usize) -> Self {
Self {
entries: Vec::with_capacity(capacity),
free_head: None,
}
}
/** 迭代存储的数据的不可变引用
* # Parameters
* self
* # Return
* Iterator<Item = &Data>
*/
pub fn iter(&self) -> impl Iterator<Item = &Data> {
self.entries.iter().filter_map(|entry| match entry {
GenericEntry::Occupied(value) => Some(value),
GenericEntry::Vacant { .. } => None,
})
}
/** 迭代存储的数据的可变引用
* # Paramters
* self
* # Return
* Iterator<Item = &mut Data>
*/
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Data> {
self.entries.iter_mut().filter_map(|entry| match entry {
GenericEntry::Occupied(value) => Some(value),
GenericEntry::Vacant { .. } => None,
})
}
}
/* 为`GenericPtr`实现`ArenaPtr`特性 */
impl<Data> ArenaPtr for GenericPtr<Data> {
type Arena = GenericArena<Data>;
type Data = Data;
}
impl<Data> Arena<GenericPtr<Data>> for GenericArena<Data> {
fn alloc_with<F>(&mut self, f: F) -> GenericPtr<Data>
where
F: FnOnce(GenericPtr<Data>) -> Data,
{
match self.free_head.take() {
Some(index) => {
let entry = &mut self.entries[index];
self.free_head = match entry {
// 有空块,返回值空块位置
GenericEntry::Vacant { next } => *next,
// 有空块,但被占用是不允许的
GenericEntry::Occupied(_) => unreachable!(),
};
let ptr = GenericPtr::from_index(index);
*entry = GenericEntry::Occupied(f(ptr)); // 将内存块设置为占用
ptr
}
None => {
// 没有空块,需要创建空块
let index = self.entries.len();
let ptr = GenericPtr::from_index(index);
self.entries.push(GenericEntry::Occupied(f(ptr)));
ptr
}
}
}
/**
*
*/
fn dealloc(&mut self, ptr: GenericPtr<Data>) -> Option<Data> {
let idx = ptr.index();
// 超出项目范围,返回 None
if idx >= self.entries.len() {
return None;
}
// 将当前索引位置的内存条目替换为 Vacant并保存原有条目
let delete_entry = mem::replace(
&mut self.entries[idx],
GenericEntry::Vacant {
next: self.free_head, // 将 free_head 指向原来空闲链表的下一个
},
);
// 更新 free_head 为当前索引
self.free_head = Some(idx);
// 根据原条目的类型返回数据(如果是占用状态的话)
match delete_entry {
GenericEntry::Vacant { .. } => None, // 如果原条目已经是空闲的,返回 None
GenericEntry::Occupied(data) => Some(data), // 如果原条目是占用的,返回数据
}
}
/* 内存池中解引用一个指针,返回数据的不可变引用 */
fn deref(&self, ptr: GenericPtr<Data>) -> Option<&Data> {
match self.entries.get(ptr.index())? {
GenericEntry::Occupied(value) => Some(value),
GenericEntry::Vacant { .. } => None,
}
}
/* 内存池中解引用一个指针,返回数据的可变引用 */
fn deref_mut(&mut self, ptr: GenericPtr<Data>) -> Option<&mut Data> {
match self.entries.get_mut(ptr.index())? {
GenericEntry::Occupied(value) => Some(value),
GenericEntry::Vacant { .. } => None,
}
}
}
/* 表示 "Arena" 的唯一哈希值的结构体 */
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UniqueArenaHash(u64);
impl UniqueArenaHash {
pub fn new<T: Hash + 'static + ?Sized>(val: &T) -> Self {
let mut hasher = DefaultHasher::new();
val.hash(&mut hasher);
std::any::TypeId::of::<T>().hash(&mut hasher);
UniqueArenaHash(hasher.finish())
}
}
pub trait GetUniqueArenaHash {
fn unique_arena_hash(&self) -> UniqueArenaHash;
}
impl<T> GetUniqueArenaHash for T
where
T: Hash + 'static + ?Sized,
{
fn unique_arena_hash(&self) -> UniqueArenaHash { UniqueArenaHash::new(self) }
}
/// 唯一的内存此,每个值在内存池中都是唯一的
pub struct UniqueArena<T>
where
T: GetUniqueArenaHash + Eq,
{
arena: GenericArena<T>,
unique_map: HashMap<UniqueArenaHash, HashSet<GenericPtr<T>>>,
}
pub struct UniqueArenaPtr<T>(GenericPtr<T>);
impl<T> fmt::Debug for UniqueArenaPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "UniqueArenaPtr({})", self.0.index())
}
}
impl<T> Clone for UniqueArenaPtr<T> {
fn clone(&self) -> Self { *self }
}
impl<T> Copy for UniqueArenaPtr<T> {}
impl<T> Hash for UniqueArenaPtr<T> {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}
impl<T> PartialEq for UniqueArenaPtr<T> {
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<T> Eq for UniqueArenaPtr<T> {}
impl<T> Ord for UniqueArenaPtr<T> {
fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) }
}
impl<T> PartialOrd for UniqueArenaPtr<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl<T> Idx for UniqueArenaPtr<T> {
fn index(self) -> usize { self.0.index() }
}
impl<T> Default for UniqueArena<T>
where
T: GetUniqueArenaHash + Eq,
{
fn default() -> Self {
Self {
arena: GenericArena::default(),
unique_map: HashMap::default(),
}
}
}
impl<T> ArenaPtr for UniqueArenaPtr<T>
where
T: GetUniqueArenaHash + Eq,
{
type Arena = UniqueArena<T>;
type Data = T;
}
impl<T> Arena<UniqueArenaPtr<T>> for UniqueArena<T>
where
T: GetUniqueArenaHash + Eq,
{
fn alloc_with<F>(&mut self, _: F) -> UniqueArenaPtr<T>
where
F: FnOnce(UniqueArenaPtr<T>) -> T,
{
panic!("UniqueArena does not support alloc_with");
}
fn alloc(&mut self, data: T) -> UniqueArenaPtr<T> {
let cur = data.unique_arena_hash();
if let Some(ptrs) = self.unique_map.get(&cur) {
for &ptr in ptrs {
if &data == self.arena.deref(ptr).expect("invalid pointer present in unique map")
{
return UniqueArenaPtr(ptr);
}
}
}
let ptr = self.arena.alloc(data);
self.unique_map.entry(cur).or_default().insert(ptr);
UniqueArenaPtr(ptr)
}
fn dealloc(&mut self, ptr: UniqueArenaPtr<T>) -> Option<T> {
let data = self.arena.deref(ptr.0)?;
let cur = data.unique_arena_hash();
if !self.unique_map.entry(cur).or_default().remove(&ptr.0)
{
unreachable!("value present in arena but not in unique map");
}
Some(self.arena.dealloc(ptr.0).unwrap_or_else(|| unreachable!("pointer dereferenced but cannot be deallocated")),)
}
fn deref(&self, ptr: UniqueArenaPtr<T>) -> Option<&T> { self.arena.deref(ptr.0) }
fn deref_mut(&mut self, ptr: UniqueArenaPtr<T>) -> Option<&mut T> {
self.arena.deref_mut(ptr.0)
}
}

@ -0,0 +1,16 @@
@NUDT_GLOBAL_VAR_a = global i32 1
@NUDT_GLOBAL_VAR_b = global i32 2
define i32 @main() {
bb_0:
%v0 = alloca i32
%v2 = load i32, i32* @NUDT_GLOBAL_VAR_a
%v4 = load i32, i32* @NUDT_GLOBAL_VAR_b
%v5 = add i32 %v2, %v4
store i32 %v5, i32* %v0
br label %bb_1
bb_1:
%v6 = load i32, i32* %v0
ret i32 %v6
}

@ -0,0 +1,37 @@
.arch armv8-a
.text
.global main
.type main, %function
.p2align 3
main:
sub sp, sp, #272
adrp x19, NUDT_GLOBAL_VAR_a
add x19, x19, :lo12:NUDT_GLOBAL_VAR_a
ldr w22, [x19]
adrp x20, NUDT_GLOBAL_VAR_b
add x20, x20, :lo12:NUDT_GLOBAL_VAR_b
ldr w23, [x20]
add w21, w22, w23
str w21, [sp]
b bb_1
bb_1:
ldr w24, [sp]
mov w0, w24
add sp, sp, #272
ret
.section .data
.p2align 3
.global NUDT_GLOBAL_VAR_a
.type NUDT_GLOBAL_VAR_a, %object
NUDT_GLOBAL_VAR_a:
.word 1
.section .data
.p2align 3
.global NUDT_GLOBAL_VAR_b
.type NUDT_GLOBAL_VAR_b, %object
NUDT_GLOBAL_VAR_b:
.word 2

@ -0,0 +1,9 @@
int main(){
const int a[4][2] = {{1, 2}, {3, 4}, {}, 7};
const int N = 3;
int b[4][2] = {};
int c[4][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int d[N + 1][2] = {1, 2, {3}, {5}, a[3][0], 8};
int e[4][2][1] = {{d[2][1], {c[2][1]}}, {3, 4}, {5, 6}, {7, 8}};
return e[3][1][0] + e[0][0][0] + e[0][1][0] + d[3][0];
}

@ -0,0 +1,11 @@
int a;
int func(int p){
p = p - 1;
return p;
}
int main(){
int b;
a = 10;
b = func(a);
return b;
}

@ -0,0 +1,7 @@
//test add
int main(){
int a, b;
a = 10;
b = -1;
return a + b;
}

@ -0,0 +1,7 @@
//test sub
const int a = 10;
int main(){
int b;
b = 2;
return b - a;
}

@ -0,0 +1,69 @@
const int V = 4;
const int space = 32;
const int LF = 10;
void printSolution(int color[]) {
int i = 0;
while (i < V) {
putint(color[i]);
putch(space);
i = i + 1;
}
putch(LF);
}
void printMessage() {
putch(78);putch(111);putch(116);
putch(space);
putch(101);putch(120);putch(105);putch(115);putch(116);
}
int isSafe(int graph[][V], int color[]) {
int i = 0;
while (i < V) {
int j = i + 1;
while (j < V) {
if (graph[i][j] && color[j] == color[i])
return 0;
j = j + 1;
}
i = i + 1;
}
return 1;
}
int graphColoring(int graph[][V], int m, int i, int color[]) {
if (i == V) {
if (isSafe(graph, color)) {
printSolution(color);
return 1;
}
return 0;
}
int j = 1;
while (j <= m) {
color[i] = j;
if (graphColoring(graph, m, i + 1, color))
return 1;
color[i] = 0;
j = j + 1;
}
return 0;
}
int main() {
int graph[V][V] = {
{0, 1, 1, 1},
{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0}
}, m = 3;
int color[V], i = 0;
while (i < V) {
color[i] = 0;
i = i + 1;
}
if (!graphColoring(graph, m, 0, color))
printMessage();
return 0;
}

@ -0,0 +1,10 @@
4 4
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
4 3
9 5 1
10 6 2
11 7 3
12 8 4

@ -0,0 +1,60 @@
const int MAX_SIZE = 100;
int a[MAX_SIZE][MAX_SIZE], b[MAX_SIZE][MAX_SIZE];
int res[MAX_SIZE][MAX_SIZE];
int n1, m1, n2, m2;
void matrix_multiply() {
int i = 0;
while (i < m1) {
int j = 0;
while (j < n2) {
int k = 0;
while (k < n1) {
res[i][j] = res[i][j] + a[i][k] * b[k][j];
k = k + 1;
}
j = j + 1;
}
i = i + 1;
}
}
int main()
{
int i, j;
m1 = getint();
n1 = getint();
i = 0;
while (i < m1) {
j = 0;
while (j < n1) {
a[i][j] = getint();
j = j + 1;
}
i = i + 1;
}
m2 = getint();
n2 = getint();
i = 0;
while (i < m2) {
j = 0;
while (j < n2) {
b[i][j] = getint();
j = j + 1;
}
i = i + 1;
}
matrix_multiply();
i = 0;
while (i < m1) {
j = 0;
while (j < n2) {
putint(res[i][j]);
putch(32);
j = j + 1;
}
putch(10);
i = i + 1;
}
return 0;
}

@ -0,0 +1 @@
int main() { /* scope test */ putch(97); putch(10); int a = 1, putch = 0; { a = a + 2; int b = a + 3; b = b + 4; putch = putch + a + b; { b = b + 5; int main = b + 6; a = a + main; putch = putch + a + b + main; { b = b + a; int a = main + 7; a = a + 8; putch = putch + a + b + main; { b = b + a; int b = main + 9; a = a + 10; const int a = 11; b = b + 12; putch = putch + a + b + main; { main = main + b; int main = b + 13; main = main + a; putch = putch + a + b + main; } putch = putch - main; } putch = putch - b; } putch = putch - a; } } return putch % 77; }

@ -0,0 +1,15 @@
//test break
int main(){
int i;
i = 0;
int sum;
sum = 0;
while(i < 100){
if(i == 50){
break;
}
sum = sum + i;
i = i + 1;
}
return sum;
}

@ -0,0 +1,9 @@
//test the priority of add and mul
int main(){
int a, b, c, d;
a = 10;
b = 4;
c = 2;
d = 2;
return (c + a) * (b - d);
}

@ -0,0 +1,13 @@
10
0x1.999999999999ap-4 0x1.999999999999ap-3 0x1.3333333333333p-2 0x1.999999999999ap-2 0x1.0000000000000p-1
0x1.3333333333333p-1 0x1.6666666666666p-1 0x1.999999999999ap-1 0x1.ccccccccccccdp-1 0x1.0000000000000p+0
0x1.199999999999ap+0
0x1.199999999999ap+1
0x1.a666666666666p+1
0x1.199999999999ap+2
0x1.6000000000000p+2
0x1.a666666666666p+2
0x1.ecccccccccccdp+2
0x1.199999999999ap+3
0x1.3cccccccccccdp+3
0x1.4333333333333p+3

@ -0,0 +1,98 @@
// float global constants
const float RADIUS = 5.5, PI = 03.141592653589793, EPS = 1e-6;
// hexadecimal float constant
const float PI_HEX = 0x1.921fb6p+1, HEX2 = 0x.AP-3;
// float constant evaluation
const float FACT = -.33E+5, EVAL1 = PI * RADIUS * RADIUS, EVAL2 = 2 * PI_HEX * RADIUS, EVAL3 = PI * 2 * RADIUS;
// float constant implicit conversion
const float CONV1 = 233, CONV2 = 0xfff;
const int MAX = 1e9, TWO = 2.9, THREE = 3.2, FIVE = TWO + THREE;
// float -> float function
float float_abs(float x) {
if (x < 0) return -x;
return x;
}
// int -> float function & float/int expression
float circle_area(int radius) {
return (PI * radius * radius + (radius * radius) * PI) / 2;
}
// float -> float -> int function & float/int expression
int float_eq(float a, float b) {
if (float_abs(a - b) < EPS) {
return 1 * 2. / 2;
} else {
return 0;
}
}
void error() {
putch(101);
putch(114);
putch(114);
putch(111);
putch(114);
putch(10);
}
void ok() {
putch(111);
putch(107);
putch(10);
}
void assert(int cond) {
if (!cond) {
error();
} else {
ok();
}
}
void assert_not(int cond) {
if (cond) {
error();
} else {
ok();
}
}
int main() {
assert_not(float_eq(HEX2, FACT));
assert_not(float_eq(EVAL1, EVAL2));
assert(float_eq(EVAL2, EVAL3));
assert(float_eq(circle_area(RADIUS) /* f->i implicit conversion */,
circle_area(FIVE)));
assert_not(float_eq(CONV1, CONV2) /* i->f implicit conversion */);
// float conditional expressions
if (1.5) ok();
if (!!3.3) ok();
if (.0 && 3) error();
if (0 || 0.3) ok();
// float array & I/O functions
int i = 1, p = 0;
float arr[10] = {1., 2};
int len = getfarray(arr);
while (i < MAX) {
float input = getfloat();
float area = PI * input * input, area_trunc = circle_area(input);
arr[p] = arr[p] + input;
putfloat(area);
putch(32);
putint(area_trunc); // f->i implicit conversion
putch(10);
i = i * - -1e1;
p = p + 1;
}
putfarray(len, arr);
return 0;
}

@ -0,0 +1,5 @@
int main() {
int a = 1;
int b = 2;
return a + b;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,89 @@
const int N = 1024;
void mm(int n, int A[][N], int B[][N], int C[][N]){
int i, j, k;
i = 0; j = 0;
while (i < n){
j = 0;
while (j < n){
C[i][j] = 0;
j = j + 1;
}
i = i + 1;
}
i = 0; j = 0; k = 0;
while (k < n){
i = 0;
while (i < n){
if (A[i][k] == 0){
i = i + 1;
continue;
}
j = 0;
while (j < n){
C[i][j] = C[i][j] + A[i][k] * B[k][j];
j = j + 1;
}
i = i + 1;
}
k = k + 1;
}
}
int A[N][N];
int B[N][N];
int C[N][N];
int main(){
int n = getint();
int i, j;
i = 0;
j = 0;
while (i < n){
j = 0;
while (j < n){
A[i][j] = getint();
j = j + 1;
}
i = i + 1;
}
i = 0;
j = 0;
while (i < n){
j = 0;
while (j < n){
B[i][j] = getint();
j = j + 1;
}
i = i + 1;
}
starttime();
i = 0;
while (i < 5){
mm(n, A, B, C);
mm(n, A, C, B);
i = i + 1;
}
int ans = 0;
i = 0;
while (i < n){
j = 0;
while (j < n){
ans = ans + B[i][j];
j = j + 1;
}
i = i + 1;
}
stoptime();
putint(ans);
putch(10);
return 0;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,71 @@
int x;
const int N = 2010;
void mv(int n, int A[][N], int b[], int res[]){
int x, y;
y = 0;
x = 11;
int i, j;
i = 0;
while(i < n){
res[i] = 0;
i = i + 1;
}
i = 0;
j = 0;
while (i < n){
j = 0;
while (j < n){
if (A[i][j] == 0){
x = x * b[i] + b[j];
y = y - x;
}else{
res[i] = res[i] + A[i][j] * b[j];
}
j = j + 1;
}
i = i + 1;
}
}
int A[N][N];
int B[N];
int C[N];
int main(){
int n = getint();
int i, j;
i = 0;
while (i < n){
j = 0;
while (j < n){
A[i][j] = getint();
j = j + 1;
}
i = i + 1;
}
i = 0;
while (i < n){
B[i] = getint();
i = i + 1;
}
starttime();
i = 0;
while (i < 50){
mv(n, A, B, C);
mv(n, A, C, B);
i = i + 1;
}
stoptime();
putarray(n, C);
return 0;
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,106 @@
const int base = 16;
int getMaxNum(int n, int arr[]){
int ret = 0;
int i = 0;
while (i < n){
if (arr[i] > ret) ret = arr[i];
i = i + 1;
}
return ret;
}
int getNumPos(int num, int pos){
int tmp = 1;
int i = 0;
while (i < pos){
num = num / base;
i = i + 1;
}
return num % base;
}
void radixSort(int bitround, int a[], int l, int r){
int head[base] = {};
int tail[base] = {};
int cnt[base] = {};
if (bitround == -1 || l + 1 >= r) return;
{
int i = l;
while (i < r){
cnt[getNumPos(a[i], bitround)]
= cnt[getNumPos(a[i], bitround)] + 1;
i = i + 1;
}
head[0] = l;
tail[0] = l + cnt[0];
i = 1;
while (i < base){
head[i] = tail[i - 1];
tail[i] = head[i] + cnt[i];
i = i + 1;
}
i = 0;
while (i < base){
while (head[i] < tail[i]){
int v = a[head[i]];
while (getNumPos(v, bitround) != i){
int t = v;
v = a[head[getNumPos(t, bitround)]];
a[head[getNumPos(t, bitround)]] = t;
head[getNumPos(t, bitround)] = head[getNumPos(t, bitround)] + 1;
}
a[head[i]] = v;
head[i] = head[i] + 1;
}
i = i + 1;
}
}
{
int i = l;
head[0] = l;
tail[0] = l + cnt[0];
i = 0;
while (i < base){
if (i > 0){
head[i] = tail[i - 1];
tail[i] = head[i] + cnt[i];
}
radixSort(bitround - 1, a, head[i], tail[i]);
i = i + 1;
}
}
return;
}
int a[30000010];
int ans;
int main(){
int n = getarray(a);
starttime();
radixSort(8, a, 0, n);
int i = 0;
while (i < n){
ans = ans + i * (a[i] % (2 + i));
i = i + 1;
}
if (ans < 0)
ans = -ans;
stoptime();
putint(ans);
putch(10);
return 0;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +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;
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,82 @@
const int mod = 998244353;
int d;
int multiply(int a, int b){
if (b == 0) return 0;
if (b == 1) return a % mod;
int cur = multiply(a, b/2);
cur = (cur + cur) % mod;
if (b % 2 == 1) return (cur + a) % mod;
else return cur;
}
int power(int a, int b){
if (b == 0) return 1;
int cur = power(a, b/2);
cur = multiply(cur, cur);
if (b % 2 == 1) return multiply(cur, a);
else return cur;
}
const int maxlen = 2097152;
int temp[maxlen], a[maxlen], b[maxlen], c[maxlen];
int memmove(int dst[], int dst_pos, int src[], int len){
int i = 0;
while (i < len){
dst[dst_pos + i] = src[i];
i = i + 1;
}
return i;
}
int fft(int arr[], int begin_pos, int n, int w){
if (n == 1) return 1;
int i = 0;
while (i < n){
if (i % 2 == 0) temp[i / 2] = arr[i + begin_pos];
else temp[n / 2 + i / 2] = arr[i + begin_pos];
i = i + 1;
}
memmove(arr, begin_pos, temp, n);
fft(arr, begin_pos, n / 2, multiply(w, w));
fft(arr, begin_pos + n / 2, n / 2, multiply(w, w));
i = 0;
int wn = 1;
while (i < n / 2){
int x = arr[begin_pos + i];
int y = arr[begin_pos + i + n / 2];
arr[begin_pos + i] = (x + multiply(wn, y)) % mod;
arr[begin_pos + i + n / 2] = (x - multiply(wn, y) + mod) % mod;
wn = multiply(wn, w);
i = i + 1;
}
return 0;
}
int main(){
int n = getarray(a);
int m = getarray(b);
starttime();
d = 1;
while (d < n + m - 1){
d = d * 2;
}
fft(a, 0, d, power(3, (mod - 1) / d));
fft(b, 0, d, power(3, (mod - 1) / d));
int i = 0;
while (i < d){
a[i] = multiply(a[i], b[i]);
i = i + 1;
}
fft(a, 0, d, power(3, mod-1 - (mod-1)/d));
i = 0;
while (i < d){
a[i] = multiply(a[i], power(d, mod-2));
i = i + 1;
}
stoptime();
putarray(n + m - 1, a);
return 0;
}

@ -0,0 +1,51 @@
50 50 353434
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
.....................#..#.........................
.....................#..#.........................
...................##.##.##.......................
.....................#..#.........................
.....................#..#.........................
...................##.##.##.......................
.....................#..#.........................
.....................#..#.........................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................
..................................................

@ -0,0 +1,112 @@
int sheet1[500][500] = {};
int sheet2[500][500] = {};
int active = 1;
int width;
int height;
int steps;
void read_map() {
width = getint();
height = getint();
// width <= 498, height <= 498
steps = getint();
getch();
int i = 1;
int j = 1;
while (j <= height) {
i = 1;
while (i <= width) {
int get = getch();
if (get == 35) {
sheet1[j][i] = 1;
} else {
sheet1[j][i] = 0;
}
i = i + 1;
}
// line feed
getch();
j = j + 1;
}
}
void put_map() {
int i = 1;
int j = 1;
while (j <= height) {
i = 1;
while (i <= width) {
if (sheet1[j][i] == 1) {
putch(35);
} else {
putch(46);
}
i = i + 1;
}
// line feed
putch(10);
j = j + 1;
}
}
void swap12() {
int i = 1;
int j = 1;
while (j <= height) {
i = 1;
while (i <= width) {
sheet1[j][i] = sheet2[j][i];
i = i + 1;
}
j = j + 1;
}
}
void step(int source[][500], int target[][500]) {
int i = 1;
int j = 1;
while (j <= height) {
i = 1;
while (i <= width) {
int alive_count = source[j - 1][i - 1] + source[j - 1][i] +
source[j - 1][i + 1] + source[j][i - 1] +
source[j][i + 1] + source[j + 1][i - 1] +
source[j + 1][i] + source[j + 1][i + 1];
if (source[j][i] == 1 && alive_count == 2 ) {
target[j][i] = 1;
} else if (alive_count == 3) {
target[j][i] = 1;
} else {
target[j][i] = 0;
}
i = i + 1;
}
j = j + 1;
}
}
int main() {
read_map();
starttime();
while (steps > 0) {
if (active == 1) {
step(sheet1, sheet2);
active = 2;
} else {
step(sheet2, sheet1);
active = 1;
}
steps = steps - 1;
}
stoptime();
if (active == 2) {
swap12();
}
put_map();
return 0;
}

@ -0,0 +1,331 @@
int func(int n) {
int sum = 0;
int i = 200;
int j = 0;
int s[100];
int m = 0;
while (m < 100){
s[m] = 0;
m=m+1;
}
while(j < n) {
if (i > 1){
s[1] = 1;
if (i > 2){
s[2] = 2;
if (i > 3){
s[3] = 3;
if (i > 4){
s[4] = 4;
if (i > 5){
s[5] = 5;
if (i > 6){
s[6] = 6;
if (i > 7){
s[7] = 7;
if (i > 8){
s[8] = 8;
if (i > 9){
s[9] = 9;
if (i > 10){
s[10] = 10;
if (i > 11){
s[11] = 11;
if (i > 12){
s[12] = 12;
if (i > 13){
s[13] = 13;
if (i > 14){
s[14] = 14;
if (i > 15){
s[15] = 15;
if (i > 16){
s[16] = 16;
if (i > 17){
s[17] = 17;
if (i > 18){
s[18] = 18;
if (i > 19){
s[19] = 19;
if (i > 20){
s[20] = 20;
if (i > 21){
s[21] = 21;
if (i > 22){
s[22] = 22;
if (i > 23){
s[23] = 23;
if (i > 24){
s[24] = 24;
if (i > 25){
s[25] = 25;
if (i > 26){
s[26] = 26;
if (i > 27){
s[27] = 27;
if (i > 28){
s[28] = 28;
if (i > 29){
s[29] = 29;
if (i > 30){
s[30] = 30;
if (i > 31){
s[31] = 31;
if (i > 32){
s[32] = 32;
if (i > 33){
s[33] = 33;
if (i > 34){
s[34] = 34;
if (i > 35){
s[35] = 35;
if (i > 36){
s[36] = 36;
if (i > 37){
s[37] = 37;
if (i > 38){
s[38] = 38;
if (i > 39){
s[39] = 39;
if (i > 40){
s[40] = 40;
if (i > 41){
s[41] = 41;
if (i > 42){
s[42] = 42;
if (i > 43){
s[43] = 43;
if (i > 44){
s[44] = 44;
if (i > 45){
s[45] = 45;
if (i > 46){
s[46] = 46;
if (i > 47){
s[47] = 47;
if (i > 48){
s[48] = 48;
if (i > 49){
s[49] = 49;
if (i > 50){
s[50] = 50;
if (i > 51){
s[51] = 51;
if (i > 52){
s[52] = 52;
if (i > 53){
s[53] = 53;
if (i > 54){
s[54] = 54;
if (i > 55){
s[55] = 55;
if (i > 56){
s[56] = 56;
if (i > 57){
s[57] = 57;
if (i > 58){
s[58] = 58;
if (i > 59){
s[59] = 59;
if (i > 60){
s[60] = 60;
if (i > 61){
s[61] = 61;
if (i > 62){
s[62] = 62;
if (i > 63){
s[63] = 63;
if (i > 64){
s[64] = 64;
if (i > 65){
s[65] = 65;
if (i > 66){
s[66] = 66;
if (i > 67){
s[67] = 67;
if (i > 68){
s[68] = 68;
if (i > 69){
s[69] = 69;
if (i > 70){
s[70] = 70;
if (i > 71){
s[71] = 71;
if (i > 72){
s[72] = 72;
if (i > 73){
s[73] = 73;
if (i > 74){
s[74] = 74;
if (i > 75){
s[75] = 75;
if (i > 76){
s[76] = 76;
if (i > 77){
s[77] = 77;
if (i > 78){
s[78] = 78;
if (i > 79){
s[79] = 79;
if (i > 80){
s[80] = 80;
if (i > 81){
s[81] = 81;
if (i > 82){
s[82] = 82;
if (i > 83){
s[83] = 83;
if (i > 84){
s[84] = 84;
if (i > 85){
s[85] = 85;
if (i > 86){
s[86] = 86;
if (i > 87){
s[87] = 87;
if (i > 88){
s[88] = 88;
if (i > 89){
s[89] = 89;
if (i > 90){
s[90] = 90;
if (i > 91){
s[91] = 91;
if (i > 92){
s[92] = 92;
if (i > 93){
s[93] = 93;
if (i > 94){
s[94] = 94;
if (i > 95){
s[95] = 95;
if (i > 96){
s[96] = 96;
if (i > 97){
s[97] = 97;
if (i > 98){
s[98] = 98;
if (i > 99){
s[99] = 99;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
j=j+1;
int m = 0;
while (m < 100){
sum = sum + s[m];
m=m+1;
}
sum = sum % 65535;
}
return sum;
}
int main() {
starttime();
int loopcount = getint();
putint(func(loopcount));
putch(10);
stoptime();
return 0;
}

@ -0,0 +1,49 @@
int COUNT = 500000;
float loop(float x[], float y[], int length) {
int i = 0;
float accumulator = 0.0;
while (i < length) {
accumulator = accumulator + x[i] * y[i];
i = i + 1;
}
return accumulator;
}
int main() {
int i = 0, j = 0;
int len = getint();
float x[4096];
float y[4096];
float total = 0.0;
float a = 0.0;
float b = 1.0;
starttime();
while ( i < COUNT) {
if (i % 10) {
a = 0.0;
b = 1.0;
} else {
a = a + 0.1;
b = b + 0.2;
}
while ( j < len) {
x[j] = a + j;
y[j] = b + j;
j = j + 1;
}
total = total + loop(x, y, len);
i = i + 1;
}
stoptime();
if ((total - 11442437121638400.000000) <=0.000001 || (total - 11442437121638400.000000) >= -0.000001) {
putint(0);
return 0;
}
else {
putint(1);
return 1;
}
}

@ -0,0 +1,2 @@
10000000
30 2 5 4 25 8 125 16 625 32 3125 2 5 4 25 8 125 16 625 32 3125 2 5 4 25 8 125 16 625 32 3125

@ -0,0 +1,51 @@
int matrix[20000000];
int a[100000];
int transpose(int n, int matrix[], int rowsize){
int colsize = n / rowsize;
int i = 0;
int j = 0;
while (i < colsize){
j = 0;
while (j < rowsize){
if (i < j){
j = j + 1;
continue;
}
int curr = matrix[i * rowsize + j];
matrix[j * colsize + i] = matrix[i * rowsize + j];
matrix[i * rowsize + j] = curr;
j = j + 1;
}
i = i + 1;
}
return -1;
}
int main(){
int n = getint();
int len = getarray(a);
starttime();
int i = 0;
while (i < n){
matrix[i] = i;
i = i + 1;
}
i = 0;
while (i < len){
transpose(n, matrix, a[i]);
i = i + 1;
}
int ans = 0;
i = 0;
while (i < len){
ans = ans + i * i * matrix[i];
i = i + 1;
}
if (ans < 0) ans = -ans;
stoptime();
putint(ans);
putch(10);
return 0;
}

@ -0,0 +1,85 @@
int func(int i, int j) {
return ((i+j) * (i+j+1) / 2 + i + 1);
}
float Vectordot(float v[], float u[], int n) {
int i = 0;
float sum = 0;
while (i < n) {
sum =sum+ v[i] * u[i];
i=i+1;
}
return sum;
}
void mult1(float v[], float out[],int n) {
int i = 0, j = 0;
float sum = 0;
while (i < n) {
while (j < n) {
sum =sum+ v[j] / func(i,j);
j=j+1;
}
out[i] = sum;
i=i+1;
}
}
void mult2(float v[], float out[], int n) {
int i = 0, j = 0;
float sum = 0;
while (i < n) {
while (j < n) {
sum =sum+ v[j] / func(j,i);
j=j+1;
}
out[i] = sum;
i=i+1;
}
}
void mult_combin(float v[], float out[], int n, float tmp[]) {
mult1(v, tmp, n);
mult2(tmp, out, n);
}
float temp = 1;
float my_sqrt(float input) {
while (temp - input / temp > 1e-6 || temp - input / temp < -1e-6){
temp = (temp+input/temp)/2;
}
return temp;
}
int main() {
int n = 100000;
if (n <= 0) {
n = 2000;
}
starttime();
float vectorA[100000], vectorB[100000], Vectortmp[100000];
int i;
while(i < n) {
vectorA[i] = 1;
i=i+1;
}
i = 0;
while(i < 1000) {
mult_combin(vectorA, vectorB, n, Vectortmp);
mult_combin(vectorB, vectorA, n, Vectortmp);
i=i+1;
}
stoptime();
float result = my_sqrt(Vectordot(vectorA,vectorB, n) / Vectordot(vectorB,vectorB,n));
if(result - 1.000000 <= 1e-6 && result - 1.000000 >= -1e-6){
putint(1);
}else{
putint(0);
}
putch(10);
return 0;
}

@ -0,0 +1,5 @@
int a = 1;
int b = 2;
int main(){
return a+b;
}
Loading…
Cancel
Save