1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use llvm_sys::core::*;
use llvm_sys::LLVMAttributeFunctionIndex;

use crate::codegen::const_gen::annotate_private_global;
use crate::codegen::fun_gen::FunCtx;
use crate::codegen::mod_gen::ModCtx;
use crate::codegen::target_gen::TargetCtx;
use crate::libcstr;

pub(crate) fn gen_panic(
    tcx: &mut TargetCtx,
    mcx: &mut ModCtx<'_, '_, '_>,
    fcx: &mut FunCtx,
    message: &str,
) {
    unsafe {
        let llvm_i8 = LLVMInt8TypeInContext(tcx.llx);
        let llvm_i32 = LLVMInt32TypeInContext(tcx.llx);

        let llvm_param_types = &mut [
            tcx.task_llvm_ptr_type(),
            LLVMPointerType(llvm_i8, 0),
            llvm_i32,
        ];

        let panic_with_string_llvm_type = LLVMFunctionType(
            LLVMVoidTypeInContext(tcx.llx),
            llvm_param_types.as_mut_ptr(),
            llvm_param_types.len() as u32,
            0,
        );

        let panic_with_string_fun = mcx.get_function_or_insert(
            panic_with_string_llvm_type,
            b"arret_runtime_panic_with_string\0",
            |panic_with_string_fun| {
                LLVMAddAttributeAtIndex(
                    panic_with_string_fun,
                    LLVMAttributeFunctionIndex,
                    tcx.llvm_enum_attr_for_name("cold", 0),
                );

                LLVMAddAttributeAtIndex(
                    panic_with_string_fun,
                    LLVMAttributeFunctionIndex,
                    tcx.llvm_enum_attr_for_name("noreturn", 0),
                );
            },
        );

        let llvm_message_string =
            LLVMConstStringInContext(tcx.llx, message.as_ptr() as *mut _, message.len() as u32, 1);

        let llvm_message_global = LLVMAddGlobal(
            mcx.module,
            LLVMTypeOf(llvm_message_string),
            libcstr!("panic_message"),
        );
        LLVMSetInitializer(llvm_message_global, llvm_message_string);
        annotate_private_global(llvm_message_global);

        let llvm_first_byte_gep_indices =
            &mut [LLVMConstInt(llvm_i32, 0, 0), LLVMConstInt(llvm_i32, 0, 0)];

        let message_pointer = LLVMConstInBoundsGEP(
            llvm_message_global,
            llvm_first_byte_gep_indices.as_mut_ptr(),
            llvm_first_byte_gep_indices.len() as u32,
        );

        let panic_with_string_args = &mut [
            fcx.current_task,
            message_pointer,
            LLVMConstInt(llvm_i32, message.len() as u64, 0),
        ];

        LLVMBuildCall(
            fcx.builder,
            panic_with_string_fun,
            panic_with_string_args.as_mut_ptr(),
            panic_with_string_args.len() as u32,
            libcstr!(""),
        );

        LLVMBuildUnreachable(fcx.builder);
    }
}