Skip to content

Commit ced72cd

Browse files
authored
Merge pull request #381 from Pivot-Studio/griffin/improve/add-comments-5
improvement: add comments for builder
2 parents 7d80f12 + 8127d5b commit ced72cd

File tree

11 files changed

+165
-51
lines changed

11 files changed

+165
-51
lines changed

src/ast/builder/llvmbuilder.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,9 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> {
924924
self.block_table.borrow().get(&handle).copied()
925925
}
926926

927+
/// # get_pri_basic_type
928+
///
929+
/// get_pri_basic_type converts a pivot-lang primitive type into a llvm primitive type
927930
fn get_pri_basic_type(&self, tp: &PriType) -> BasicTypeEnum<'ctx> {
928931
match tp {
929932
PriType::I8 => self.context.i8_type().into(),
@@ -1686,6 +1689,10 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> {
16861689
*self.optimized.borrow_mut() = true;
16871690
}
16881691

1692+
/// # try_load2var_inner
1693+
///
1694+
/// it returns the element of a pointer,
1695+
/// or array, int, float, struct, vector, and function value rirectly
16891696
fn try_load2var_inner(&self, v: usize, tp: &PLType, ctx: &mut Ctx<'a>) -> Result<usize, ()> {
16901697
let handle = v;
16911698
let v = self.get_llvm_value(handle).unwrap();
@@ -1694,7 +1701,6 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> {
16941701
AnyValueEnum::ArrayValue(_)
16951702
| AnyValueEnum::IntValue(_)
16961703
| AnyValueEnum::FloatValue(_)
1697-
| AnyValueEnum::PointerValue(_)
16981704
| AnyValueEnum::StructValue(_)
16991705
| AnyValueEnum::VectorValue(_) => handle,
17001706
AnyValueEnum::FunctionValue(f) => {
@@ -1810,6 +1816,11 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
18101816
.as_debug_info_scope(),
18111817
);
18121818
}
1819+
1820+
/// # position_at_end_block
1821+
///
1822+
/// Set the position of the builder to the end of a basic block refered
1823+
/// by the block handle.
18131824
fn position_at_end_block(&self, block: BlockHandle) {
18141825
self.builder
18151826
.position_at_end(self.block_table.borrow()[&block]);
@@ -1829,7 +1840,6 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
18291840
self.get_llvm_value_handle(&f.as_any_value_enum())
18301841
}
18311842
}
1832-
18331843
fn get_or_add_global(
18341844
&self,
18351845
name: &str,
@@ -2032,6 +2042,10 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
20322042
) -> ValueHandle {
20332043
self.alloc_with_f(name, pltype, ctx, declare, "DioGC__malloc_no_collect")
20342044
}
2045+
2046+
/// # build_struct_gep
2047+
///
2048+
/// it builds a GEP(GetElementPtr) instructions and returns the value handle of the instruction.
20352049
fn build_struct_gep(
20362050
&self,
20372051
structv: ValueHandle,
@@ -2041,9 +2055,11 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
20412055
ctx: &mut Ctx<'a>,
20422056
) -> Result<ValueHandle, String> {
20432057
let structv = self.get_llvm_value(structv).unwrap();
2044-
let structv = structv.into_pointer_value();
2058+
let struct_val_ptr = structv.into_pointer_value();
20452059
let sttp = self.get_basic_type_op(tp, ctx).unwrap();
2046-
let gep = self.builder.build_struct_gep(sttp, structv, index, name);
2060+
let gep = self
2061+
.builder
2062+
.build_struct_gep(sttp, struct_val_ptr, index, name);
20472063
if let Ok(gep) = gep {
20482064
return Ok(self.get_llvm_value_handle(&gep.as_any_value_enum()));
20492065
} else {
@@ -2204,6 +2220,16 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
22042220
// dbg.map(|d| self.builder.set_current_debug_location(d));
22052221
}
22062222

2223+
/// # build_phi
2224+
///
2225+
/// it emits the phi node of LLVM and sets up the phi node.
2226+
/// it returns the value handle of emitted phi node
2227+
///
2228+
/// the pltype specifies the type of variable charged by the phi node.
2229+
/// for example, if a F64 is manupulated in different branches,
2230+
///
2231+
/// the pltype will be F64.
2232+
/// the vbs holds a list of tuple which maps the block and value.
22072233
fn build_phi(
22082234
&self,
22092235
pltype: &PLType,
@@ -2222,6 +2248,11 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
22222248
self.get_llvm_value_handle(&phi.as_any_value_enum())
22232249
}
22242250

2251+
/// # build_unconditional_branch
2252+
///
2253+
/// builds a unconditional branch by the value refered by the block handle to
2254+
/// terminates the current block of the builder, which adds a new block in the
2255+
/// builder as well.
22252256
fn build_unconditional_branch(&self, bb: BlockHandle) {
22262257
let bb = self.get_llvm_block(bb).unwrap();
22272258
self.builder.build_unconditional_branch(bb).unwrap();
@@ -2266,6 +2297,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
22662297
// run_immix_pass(self.module);
22672298
self.module.write_bitcode_to_path(path)
22682299
}
2300+
22692301
fn int_value(&self, ty: &PriType, v: u64, sign_ext: bool) -> ValueHandle {
22702302
let ty = self.get_pri_basic_type(ty).into_int_type();
22712303
let v = ty.const_int(v, sign_ext);
@@ -2431,6 +2463,11 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
24312463
let v = self.builder.build_int_truncate(v, dest_ty, name).unwrap();
24322464
self.get_llvm_value_handle(&v.as_any_value_enum())
24332465
}
2466+
2467+
/// # build_conditional_branch
2468+
///
2469+
/// it helps to build a conditional branch by the condition, then bacis block and else block
2470+
/// refered by the value handle and block handles.
24342471
fn build_conditional_branch(
24352472
&self,
24362473
cond: ValueHandle,

src/ast/builder/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ pub trait IRBuilder<'a, 'ctx> {
124124
v: ValueHandle,
125125
ctx: &mut Ctx<'a>,
126126
);
127+
128+
/// # int_value
129+
///
130+
/// int_value converts the [PriType] value into a integer format to emit code,
131+
/// ,stores the emitted value into the builder and returns its value handle.
127132
fn int_value(&self, ty: &PriType, v: u64, sign_ext: bool) -> ValueHandle;
128133
fn position_at(&self, v: ValueHandle);
129134
fn print_to_file(&self, file: &Path) -> Result<(), String>;
@@ -137,6 +142,11 @@ pub trait IRBuilder<'a, 'ctx> {
137142
vbs: &[(ValueHandle, BlockHandle)],
138143
) -> ValueHandle;
139144
fn build_unconditional_branch(&self, bb: BlockHandle);
145+
146+
/// # position_at_end_block
147+
///
148+
/// Set the position of the builder to the end of a basic block refered
149+
/// by the block handle.
140150
fn position_at_end_block(&self, block: BlockHandle);
141151
fn add_body_to_struct_type(&self, name: &str, sttype: &STType, ctx: &mut Ctx<'a>);
142152
fn get_or_insert_fn_handle(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> (ValueHandle, bool);
@@ -154,6 +164,11 @@ pub trait IRBuilder<'a, 'ctx> {
154164
tp: &PLType,
155165
ctx: &mut Ctx<'a>,
156166
) -> ValueHandle;
167+
168+
/// # try_load2var
169+
///
170+
/// it returns the element of a pointer,
171+
/// or array, int, float, struct, vector, and function value directly
157172
fn try_load2var(
158173
&self,
159174
range: Range,

src/ast/ctx.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,10 @@ impl<'a, 'ctx> Ctx<'a> {
942942
self.diagnose.borrow_mut().insert(dia);
943943
dia2
944944
}
945-
// load type* to type
945+
/// # try_load2var
946+
///
947+
/// load the element of a pointer from the builder,
948+
/// or get the ordinary types for the others
946949
pub fn try_load2var<'b>(
947950
&'b mut self,
948951
range: Range,
@@ -1067,6 +1070,11 @@ impl<'a, 'ctx> Ctx<'a> {
10671070
pub fn get_location(&self, range: Range) -> Location {
10681071
Location::new(self.get_file_url(), range.to_diag_range())
10691072
}
1073+
1074+
/// # position_at_end
1075+
///
1076+
/// it replace its current block field with the input block handle,
1077+
/// and inserts it at the end of current builder
10701078
pub fn position_at_end<'b>(
10711079
&'b mut self,
10721080
block: BlockHandle,
@@ -1076,9 +1084,10 @@ impl<'a, 'ctx> Ctx<'a> {
10761084
builder.position_at_end_block(block);
10771085
}
10781086

1079-
/// # auto_deref
1080-
/// 自动解引用,有几层解几层
1081-
pub fn auto_deref<'b>(
1087+
/// # deref_greedily
1088+
///
1089+
/// it de-references greedily until the result cannot be de-referenced anymore.
1090+
pub fn deref_greedily<'b>(
10821091
&'b mut self,
10831092
tp: Arc<RefCell<PLType>>,
10841093
value: ValueHandle,

src/ast/ctx/builtins.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -724,9 +724,9 @@ fn emit_for_fields<'a, 'b>(
724724
let tp = g.get_ty();
725725
let tp = get_type_deep(tp);
726726
let v = g.get_value();
727-
let (tp, v) = ctx.auto_deref(tp, v, builder);
727+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
728728
let tp = get_type_deep(tp);
729-
let (tp, v) = ctx.auto_deref(tp, v, builder);
729+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
730730
let mut code_gen = false;
731731
let stp = match &*tp.borrow() {
732732
PLType::Struct(_) => {
@@ -836,9 +836,9 @@ fn emit_if_arr<'a, 'b>(
836836
let tp = g.get_ty();
837837
let tp = get_type_deep(tp);
838838
let v = g.get_value();
839-
let (tp, v) = ctx.auto_deref(tp, v, builder);
839+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
840840
let tp = get_type_deep(tp);
841-
let (tp, v) = ctx.auto_deref(tp, v, builder);
841+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
842842
let mut code_gen = false;
843843
let stp = match &*tp.borrow() {
844844
PLType::Arr(_) => {
@@ -926,9 +926,9 @@ fn emit_if_union<'a, 'b>(
926926
let tp = g.get_ty();
927927
let tp = get_type_deep(tp);
928928
let v = g.get_value();
929-
let (tp, v) = ctx.auto_deref(tp, v, builder);
929+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
930930
let tp = get_type_deep(tp);
931-
let (tp, v) = ctx.auto_deref(tp, v, builder);
931+
let (tp, v) = ctx.deref_greedily(tp, v, builder);
932932
let mut code_gen = false;
933933
let stp = match &*tp.borrow() {
934934
PLType::Union(_) => {
@@ -1074,7 +1074,7 @@ fn emit_match_type<'a, 'b>(
10741074
if let Some(g) = &v {
10751075
let tp = g.get_ty();
10761076
let v = g.get_value();
1077-
let (tp, mut v) = ctx.auto_deref(tp, v, builder);
1077+
let (tp, mut v) = ctx.deref_greedily(tp, v, builder);
10781078
let tp = get_type_deep(tp);
10791079
if tp != generic {
10801080
// 类型不匹配

src/ast/ctx/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ impl<'a, 'ctx> Ctx<'a> {
331331
}
332332
}
333333
}
334-
let (st_pltype, st_value) = self.auto_deref(ori_pltype, ori_value, builder);
334+
let (st_pltype, st_value) = self.deref_greedily(ori_pltype, ori_value, builder);
335335
if let PLType::Trait(t) = &*target_pltype.borrow() {
336336
for f in t.list_trait_fields().iter() {
337337
if let TypeNodeEnum::Func(fu) = &*f.typenode {

src/ast/node/control.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,59 +47,84 @@ impl Node for IfNode {
4747
let cond_block = builder.append_basic_block(ctx.function.unwrap(), "if.cond");
4848
let then_block = builder.append_basic_block(ctx.function.unwrap(), "if.then");
4949
let else_block = builder.append_basic_block(ctx.function.unwrap(), "if.else");
50-
let after_block = builder.append_basic_block(ctx.function.unwrap(), "if.after");
50+
let merge_block = builder.append_basic_block(ctx.function.unwrap(), "if.after");
5151
builder.build_unconditional_branch(cond_block);
5252
ctx.position_at_end(cond_block, builder);
53-
let condrange = self.cond.range();
54-
let v = self.cond.emit(ctx, builder)?.get_value();
55-
let code = ErrorCode::IF_CONDITION_MUST_BE_BOOL;
56-
check_bool(&v, ctx, condrange, code)?;
57-
let v = v.unwrap();
53+
54+
let cond_range = self.cond.range();
55+
let cond_val = self.cond.emit(ctx, builder)?.get_value();
56+
check_bool(
57+
&cond_val,
58+
ctx,
59+
cond_range,
60+
ErrorCode::IF_CONDITION_MUST_BE_BOOL,
61+
)?;
62+
63+
let v = cond_val.unwrap();
5864
let cond = v.get_value();
59-
let cond = ctx.try_load2var(condrange, cond, builder, &v.get_ty().borrow())?;
65+
let cond = ctx.try_load2var(cond_range, cond, builder, &v.get_ty().borrow())?;
6066
let cond = builder.build_int_truncate(cond, &PriType::BOOL, "trunctemp");
67+
68+
//
6169
builder.build_conditional_branch(cond, then_block, else_block);
62-
// then block
70+
71+
// emit the else logic into the then block
6372
ctx.position_at_end(then_block, builder);
73+
// emit the code inside a child context because it belongs to a sub-block
6474
let then_terminator = self.then.emit_child(ctx, builder)?.get_term();
6575
if then_terminator.is_none() {
66-
builder.build_unconditional_branch(after_block);
76+
// there is no terminator(like return, yield and so forth) in the statement
77+
// create an unconditional branch to merge block to finish off the "then" block
78+
builder.build_unconditional_branch(merge_block);
6779
}
80+
81+
// emit the else logic into the else block
6882
ctx.position_at_end(else_block, builder);
6983
let terminator = if let Some(el) = &mut self.els {
7084
let mut child = ctx.new_child(el.range().start, builder);
7185
let else_terminator = el.emit(&mut child, builder)?.get_term();
7286
if else_terminator.is_none() {
73-
builder.build_unconditional_branch(after_block);
87+
// create an unconditional branch only if no terminator is detected
88+
// otherwise, the code to be executed might be the others instead of merge block
89+
// for example, if there is a 'return' statement in the if-then-else clause,
90+
// it won't execute the merge block as it returns directly
91+
builder.build_unconditional_branch(merge_block);
7492
}
93+
7594
if then_terminator.is_return() && else_terminator.is_return() {
7695
TerminatorEnum::Return
7796
} else {
7897
TerminatorEnum::None
7998
}
8099
} else {
81-
builder.build_unconditional_branch(after_block);
100+
builder.build_unconditional_branch(merge_block);
82101
TerminatorEnum::None
83102
};
84-
ctx.position_at_end(after_block, builder);
103+
104+
ctx.position_at_end(merge_block, builder);
85105
if terminator.is_return() {
86-
builder.build_unconditional_branch(after_block);
106+
builder.build_unconditional_branch(merge_block);
87107
}
88108
ctx.emit_comment_highlight(&self.comments[0]);
109+
89110
NodeOutput::default().with_term(terminator).to_result()
90111
}
91112
// ANCHOR_END: emit
92113
}
93114

115+
/// # check_bool
116+
///
117+
/// it ensures the input NodeValue represents a [PriType::BOOL],
118+
/// otheriwse it returns an error with the range and error code.
94119
fn check_bool(
95120
v: &Option<NodeValue>,
96121
ctx: &mut Ctx,
97-
condrange: Range,
122+
range: Range,
98123
code: ErrorCode,
99124
) -> Result<(), PLDiag> {
100125
if v.is_none() || !v.as_ref().unwrap().get_ty().borrow().is(&PriType::BOOL) {
101126
return Err(ctx.add_diag(
102-
condrange
127+
range
103128
.new_err(code)
104129
.add_help("use a bool variable instead")
105130
.clone(),

src/ast/node/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub trait Node: RangeTrait + FmtTrait + PrintTrait {
170170
) -> NodeResult;
171171
}
172172

173+
/// print trait to report the AST node structure
173174
#[enum_dispatch]
174175
pub trait PrintTrait {
175176
fn print(&self, tabs: usize, end: bool, line: Vec<bool>);
@@ -186,6 +187,7 @@ pub enum Num {
186187
impl Eq for Num {
187188
// FIXME: NaN https://stackoverflow.com/questions/39638363/how-can-i-use-a-hashmap-with-f64-as-key-in-rust
188189
}
190+
189191
#[macro_export]
190192
macro_rules! mismatch_err {
191193
($ctx:ident, $range:expr,$exprange:expr, $expect:expr,$got:expr) => {

src/ast/node/node_result.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ pub trait NodeResultBuilder {
3535
}
3636

3737
impl NodeResultBuilder for ValueHandle {
38+
/// new_output returns a [NodeOutput] with the type and its value handle
3839
fn new_output(&self, typ: Arc<RefCell<PLType>>) -> NodeOutput {
3940
NodeOutput::new_value_simple(*self, typ)
4041
}
4142
}
4243

4344
impl NodeOutput {
45+
/// # set_const
46+
///
47+
/// set_const marks a node refered by handle value is immutable
4448
pub fn set_const(&mut self) -> &mut Self {
4549
if let Some(value) = &mut self.value {
4650
value.set_const(true);
@@ -71,6 +75,9 @@ impl NodeOutput {
7175
self
7276
}
7377

78+
/// # to_result
79+
///
80+
/// to_result returns a cloned version of [NodeResult]
7481
pub fn to_result(&self) -> NodeResult {
7582
Ok(self.clone())
7683
}

0 commit comments

Comments
 (0)