diff --git a/crates/cyrusc_codegen_llvm/src/builder/builder.rs b/crates/cyrusc_codegen_llvm/src/builder/builder.rs index 8378583a3..607ec8916 100644 --- a/crates/cyrusc_codegen_llvm/src/builder/builder.rs +++ b/crates/cyrusc_codegen_llvm/src/builder/builder.rs @@ -24,6 +24,10 @@ use cyrusc_typed_ast::LabelID; use inkwell::{ basic_block::BasicBlock, builder::Builder, context::Context, module::Module, targets::TargetMachine, values::FunctionValue, + llvm_sys::{ + core::{LLVMGetCurrentDebugLocation2, LLVMSetCurrentDebugLocation2}, + prelude::{LLVMBuilderRef, LLVMMetadataRef}, + }, }; use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; @@ -238,3 +242,43 @@ impl<'ll> Default for BlockRegistry<'ll> { } } } + +pub struct DebugLocationGuard { + builder: LLVMBuilderRef, + saved_loc: Option, +} + +impl DebugLocationGuard { + pub fn new(builder_ref: LLVMBuilderRef, dctx_exists: bool) -> Self { + let saved_loc = if dctx_exists { + unsafe { + let loc = LLVMGetCurrentDebugLocation2(builder_ref); + if !loc.is_null() { + Some(loc) + } else { + None + } + } + } else { + None + }; + + if saved_loc.is_some() { + unsafe { + LLVMSetCurrentDebugLocation2(builder_ref, std::ptr::null_mut()); + } + } + + Self { builder: builder_ref, saved_loc } + } +} + +impl Drop for DebugLocationGuard { + fn drop(&mut self) { + if let Some(loc) = self.saved_loc { + unsafe { + LLVMSetCurrentDebugLocation2(self.builder, loc); + } + } + } +} diff --git a/crates/cyrusc_codegen_llvm/src/builder/control_flow.rs b/crates/cyrusc_codegen_llvm/src/builder/control_flow.rs index 630d1a017..532b6cf4d 100644 --- a/crates/cyrusc_codegen_llvm/src/builder/control_flow.rs +++ b/crates/cyrusc_codegen_llvm/src/builder/control_flow.rs @@ -1078,8 +1078,11 @@ impl<'ll> CodeGenIRBuilder<'ll> { return; } + if self.blockreg.cur_block.unwrap().get_terminator().is_none() { + LLVMBuildBr(self.llvmbuilder.as_mut_ptr(), next_block); + } + self.blockreg.cur_block = None; - LLVMBuildBr(self.llvmbuilder.as_mut_ptr(), next_block); } } @@ -1088,8 +1091,12 @@ impl<'ll> CodeGenIRBuilder<'ll> { if !self.llvm_emit_check_block_branch() { return; } + + if self.blockreg.cur_block.unwrap().get_terminator().is_none() { + LLVMBuildCondBr(self.llvmbuilder.as_mut_ptr(), cond, then_block, else_block); + } + self.blockreg.cur_block = None; - LLVMBuildCondBr(self.llvmbuilder.as_mut_ptr(), cond, then_block, else_block); } } diff --git a/crates/cyrusc_codegen_llvm/src/builder/exprs.rs b/crates/cyrusc_codegen_llvm/src/builder/exprs.rs index df5100bdf..8acd05d41 100644 --- a/crates/cyrusc_codegen_llvm/src/builder/exprs.rs +++ b/crates/cyrusc_codegen_llvm/src/builder/exprs.rs @@ -1133,7 +1133,7 @@ impl<'ll> CodeGenIRBuilder<'ll> { let cir_pointee_type = lhs_rvalue.ty.pointer_inner().unwrap().clone(); let pointee_type: BasicTypeEnum<'ll> = if cir_pointee_type.is_void() { - self.llvm_ctx.ptr_type(AddressSpace::default()).into() + self.llvm_ctx.i8_type().into() } else { self.emit_type(cir_pointee_type).try_into().unwrap() }; @@ -1153,7 +1153,7 @@ impl<'ll> CodeGenIRBuilder<'ll> { let cir_pointee_type = result_type.pointer_inner().unwrap().clone(); let pointee_type: BasicTypeEnum<'ll> = if cir_pointee_type.is_void() { - self.llvm_ctx.ptr_type(AddressSpace::default()).into() + self.llvm_ctx.i8_type().into() } else { self.emit_type(cir_pointee_type).try_into().unwrap() }; @@ -1186,7 +1186,7 @@ impl<'ll> CodeGenIRBuilder<'ll> { let cir_pointee_type = result_type.pointer_inner().unwrap().clone(); let pointee_type: BasicTypeEnum<'ll> = if cir_pointee_type.is_void() { - self.llvm_ctx.ptr_type(AddressSpace::default()).into() + self.llvm_ctx.i8_type().into() } else { self.emit_type(cir_pointee_type).try_into().unwrap() }; diff --git a/crates/cyrusc_codegen_llvm/src/builder/intrinsics.rs b/crates/cyrusc_codegen_llvm/src/builder/intrinsics.rs index e09145d08..96099ed35 100644 --- a/crates/cyrusc_codegen_llvm/src/builder/intrinsics.rs +++ b/crates/cyrusc_codegen_llvm/src/builder/intrinsics.rs @@ -2,7 +2,7 @@ // Copyright (c) 2026 The Cyrus Language use crate::builder::{ - builder::CodeGenIRBuilder, + builder::{CodeGenIRBuilder, DebugLocationGuard}, values::{InternalValue, InternalValueKind}, }; use cyrusc_internal::cir::{ @@ -23,6 +23,7 @@ use inkwell::{ // These intrinsics published via builtin to user side. impl<'ll> CodeGenIRBuilder<'ll> { pub(crate) fn emit_builtin_call(&mut self, call: &CIRCall, builtin_spec: &TypedBuiltinSpec) -> InternalValue<'ll> { + let _guard = DebugLocationGuard::new(self.llvmbuilder.as_mut_ptr(), self.dctx.is_some()); debug_assert!(builtin_spec.phase == TypedBuiltinPhase::Codegen); debug_assert!(builtin_spec.form == TypedBuiltinForm::Expr); @@ -189,6 +190,7 @@ impl<'ll> CodeGenIRBuilder<'ll> { } pub(crate) fn emit_intrinsic_panic(&mut self, args: &[CIRExpr], loc: Loc) -> InternalValue<'ll> { + let _guard = DebugLocationGuard::new(self.llvmbuilder.as_mut_ptr(), self.dctx.is_some()); let cir_void_ptr = CIRType::Pointer(Box::new(CIRType::Plain(PlainType::Void))); let ptr_type = self.llvm_ctx.ptr_type(inkwell::AddressSpace::default()); diff --git a/crates/cyrusc_codegen_llvm/src/builder/values.rs b/crates/cyrusc_codegen_llvm/src/builder/values.rs index ae3ef96bd..16aafdec2 100644 --- a/crates/cyrusc_codegen_llvm/src/builder/values.rs +++ b/crates/cyrusc_codegen_llvm/src/builder/values.rs @@ -116,7 +116,10 @@ impl<'ll> CodeGenIRBuilder<'ll> { rvalue = InternalValue::new(rvalue.ty.clone(), InternalValueKind::RValue(widened.into())); } - self.llvmbuilder.build_store(ptr, rvalue.as_basic_value()).unwrap(); + let store_inst = self.llvmbuilder.build_store(ptr, rvalue.as_basic_value()).unwrap(); + if layout.align > 0 { + store_inst.set_alignment(layout.align).unwrap(); + } } pub(crate) fn widen_int_arg(&self, value: InternalValue<'ll>, signed: bool) -> InternalValue<'ll> { @@ -202,6 +205,22 @@ impl<'ll> CodeGenIRBuilder<'ll> { let ty: BasicTypeEnum<'ll> = self.emit_type(internal_value.ty.clone()).try_into().unwrap(); let basic_value = self.llvmbuilder.build_load(ty, pointer_value, "rvalue").unwrap(); + let load_inst = match basic_value { + BasicValueEnum::ArrayValue(val) => val.as_instruction(), + BasicValueEnum::IntValue(val) => val.as_instruction(), + BasicValueEnum::FloatValue(val) => val.as_instruction(), + BasicValueEnum::PointerValue(val) => val.as_instruction(), + BasicValueEnum::StructValue(val) => val.as_instruction(), + BasicValueEnum::VectorValue(val) => val.as_instruction(), + _ => None, + }; + if let Some(inst) = load_inst { + let layout = self.tctx.layout_of(&internal_value.ty); + if layout.align > 0 { + inst.set_alignment(layout.align).unwrap(); + } + } + if internal_value.ty.is_bool() { InternalValue::new( internal_value.ty, diff --git a/crates/cyrusc_codegen_llvm/src/llvm/debug_info.rs b/crates/cyrusc_codegen_llvm/src/llvm/debug_info.rs index bdab78050..39546cfc5 100644 --- a/crates/cyrusc_codegen_llvm/src/llvm/debug_info.rs +++ b/crates/cyrusc_codegen_llvm/src/llvm/debug_info.rs @@ -606,6 +606,8 @@ pub unsafe fn debug_func_type( if let Some(ret) = ret_type { types.push(ret); + } else { + types.push(std::ptr::null_mut()); } for p in params {