Skip to content

Commit

Permalink
feat: top level variable back reference
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <xpf6677@163.com>
  • Loading branch information
Peefy committed May 6, 2024
1 parent 5da1278 commit 7567ee5
Show file tree
Hide file tree
Showing 26 changed files with 430 additions and 37 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.7
0.9.0-alpha.1
1 change: 1 addition & 0 deletions kclvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 95 additions & 4 deletions kclvm/compiler/src/codegen/llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub struct LLVMCodeGenContext<'ctx> {
pub program: &'ctx ast::Program,
pub functions: RefCell<Vec<Rc<FunctionValue<'ctx>>>>,
pub imported: RefCell<HashSet<String>>,
pub setter_keys: RefCell<HashSet<String>>,
pub schema_stack: RefCell<Vec<value::SchemaType>>,
pub lambda_stack: RefCell<Vec<usize>>,
pub schema_expr_stack: RefCell<Vec<()>>,
Expand Down Expand Up @@ -365,6 +366,20 @@ impl<'ctx> BuilderMethods for LLVMCodeGenContext<'ctx> {
self.module.add_function(name, fn_ty, None)
}
}

/// Add a setter function named `name`.
fn add_setter_function(&self, name: &str) -> Self::Function {
let fn_ty = self.setter_func_type();
if self.no_link {
let pkgpath = self.current_pkgpath();
let msg = format!("pkgpath {} is not found", pkgpath);
let modules = self.modules.borrow_mut();
let module = modules.get(&pkgpath).expect(&msg).borrow_mut();
module.inner.add_function(name, fn_ty, None)
} else {
self.module.add_function(name, fn_ty, None)
}
}
}

/* Value methods */
Expand Down Expand Up @@ -604,6 +619,16 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> {
.get_first_param()
.expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG)
}
/// Get the global evaluation scope pointer.
fn current_scope_ptr(&self) -> Self::Value {
self.builder
.get_insert_block()
.unwrap()
.get_parent()
.unwrap()
.get_nth_param(1)
.expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG)
}
}

impl<'ctx> ValueCalculationMethods for LLVMCodeGenContext<'ctx> {
Expand Down Expand Up @@ -1255,6 +1280,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
functions: RefCell::new(vec![]),
imported: RefCell::new(HashSet::new()),
local_vars: RefCell::new(HashSet::new()),
setter_keys: RefCell::new(HashSet::new()),
schema_stack: RefCell::new(vec![]),
// 1 denotes the top global main function lambda and 0 denotes the builtin scope.
// Any user-defined lambda scope greater than 1.
Expand Down Expand Up @@ -1285,8 +1311,10 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let tpe = self.value_ptr_type().into_pointer_type();
let void_type = self.context.void_type();
let context_ptr_type = self.context_ptr_type();
let fn_type = tpe.fn_type(&[context_ptr_type.into()], false);
let void_fn_type = void_type.fn_type(&[context_ptr_type.into()], false);
let scope_ptr_type = self.scope_ptr_type();
let fn_type = tpe.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false);
let void_fn_type =
void_type.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false);
let has_main_pkg = self.program.pkgs.contains_key(MAIN_PKG_PATH);
let function = if self.no_link {
let mut modules = self.modules.borrow_mut();
Expand Down Expand Up @@ -1714,7 +1742,12 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
}

/// Append a variable or update the existed variable
pub fn add_or_update_global_variable(&self, name: &str, value: BasicValueEnum<'ctx>) {
pub fn add_or_update_global_variable(
&self,
name: &str,
value: BasicValueEnum<'ctx>,
save_scope: bool,
) {
// Find argument name in the scope
let current_pkgpath = self.current_pkgpath();
let mut pkg_scopes = self.pkg_scopes.borrow_mut();
Expand All @@ -1725,6 +1758,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let variables = last.variables.borrow();
if let Some(var) = variables.get(&name.to_string()) {
self.builder.build_store(*var, value);
if save_scope {
self.build_void_call(
&ApiFunc::kclvm_scope_set.name(),
&[
self.current_runtime_ctx_ptr(),
self.current_scope_ptr(),
self.native_global_string(&current_pkgpath, "").into(),
self.native_global_string(name, "").into(),
value,
],
);
}
existed = true;
}
}
Expand All @@ -1735,6 +1780,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let var_name = format!("${}.${}", pkgpath_without_prefix!(pkgpath), name);
let pointer = self.new_global_kcl_value_ptr(&var_name);
self.builder.build_store(pointer, value);
if save_scope {
self.build_void_call(
&ApiFunc::kclvm_scope_set.name(),
&[
self.current_runtime_ctx_ptr(),
self.current_scope_ptr(),
self.native_global_string(&current_pkgpath, "").into(),
self.native_global_string(name, "").into(),
value,
],
);
}
if !variables.contains_key(name) {
variables.insert(name.to_string(), pointer);
}
Expand Down Expand Up @@ -1962,7 +2019,41 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
}
}
} else {
self.builder.build_load(*var, name)
// Not a local schema attribute or a global type.
let key = format!("{}.{name}", pkgpath_without_prefix!(pkgpath));
let is_in_lambda = self.is_in_lambda();
if !is_in_schema
&& !is_in_lambda
&& index <= GLOBAL_LEVEL
&& !self.local_vars.borrow().contains(name)
&& self.setter_keys.borrow().contains(&key)
{
let target = self
.target_vars
.borrow_mut()
.last()
.expect(kcl_error::INTERNAL_ERROR_MSG)
.clone();
self.build_call(
&ApiFunc::kclvm_scope_get.name(),
&[
// Runtime context ptr
self.current_runtime_ctx_ptr(),
// Scope ptr
self.current_scope_ptr(),
// Package path
self.native_global_string(&pkgpath, "").into(),
// Attribute name
self.native_global_string(name, "").into(),
// Target
self.native_global_string(&target, "").into(),
// Default
self.builder.build_load(*var, name),
],
)
} else {
self.builder.build_load(*var, name)
}
};
result = Ok(value);
break;
Expand Down
Loading

0 comments on commit 7567ee5

Please sign in to comment.