forked from M-Labs/nac3
1
0
Fork 0

use alloca for variables

This commit is contained in:
Sebastien Bourdeauducq 2020-03-30 16:19:35 +08:00
parent c5efa615a2
commit f9dbf68875
1 changed files with 12 additions and 7 deletions

View File

@ -73,7 +73,7 @@ struct CodeGen<'ctx> {
module: Module<'ctx>, module: Module<'ctx>,
builder: Builder<'ctx>, builder: Builder<'ctx>,
current_source_location: ast::Location, current_source_location: ast::Location,
namespace: HashMap<String, values::BasicValueEnum<'ctx>>, namespace: HashMap<String, values::PointerValue<'ctx>>,
} }
impl<'ctx> CodeGen<'ctx> { impl<'ctx> CodeGen<'ctx> {
@ -165,7 +165,10 @@ impl<'ctx> CodeGen<'ctx> {
self.builder.position_at_end(basic_block); self.builder.position_at_end(basic_block);
for (n, arg) in args.args.iter().enumerate() { for (n, arg) in args.args.iter().enumerate() {
self.namespace.insert(arg.arg.clone(), function.get_nth_param(n as u32).unwrap()); let param = function.get_nth_param(n as u32).unwrap();
let alloca = self.builder.build_alloca(param.get_type(), &arg.arg);
self.builder.build_store(alloca, param);
self.namespace.insert(arg.arg.clone(), alloca);
} }
for statement in body.iter() { for statement in body.iter() {
@ -197,7 +200,7 @@ impl<'ctx> CodeGen<'ctx> {
}, },
ast::ExpressionType::Identifier { name } => { ast::ExpressionType::Identifier { name } => {
match self.namespace.get(name) { match self.namespace.get(name) {
Some(value) => Ok(*value), Some(value) => Ok(self.builder.build_load(*value, name).into()),
None => Err(self.compile_error(CompileErrorKind::UnboundIdentifier)) None => Err(self.compile_error(CompileErrorKind::UnboundIdentifier))
} }
}, },
@ -370,11 +373,13 @@ impl<'ctx> CodeGen<'ctx> {
for target in targets.iter() { for target in targets.iter() {
self.set_source_location(target.location); self.set_source_location(target.location);
if let ast::ExpressionType::Identifier { name } = &target.node { if let ast::ExpressionType::Identifier { name } = &target.node {
if let Some(existing) = self.namespace.insert(name.clone(), value) { let builder = &self.builder;
if existing.get_type() != value.get_type() { let target = self.namespace.entry(name.clone()).or_insert_with(
|| builder.build_alloca(value.get_type(), name));
if target.get_type() != value.get_type().ptr_type(inkwell::AddressSpace::Generic) {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes)); return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
} }
} builder.build_store(*target, value);
} else { } else {
return Err(self.compile_error(CompileErrorKind::Unsupported("assignment target must be an identifier"))) return Err(self.compile_error(CompileErrorKind::Unsupported("assignment target must be an identifier")))
} }