diff --git a/compiler/gen_llvm/src/llvm/bitcode.rs b/compiler/gen_llvm/src/llvm/bitcode.rs index 713ef042c8..6db5633286 100644 --- a/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/compiler/gen_llvm/src/llvm/bitcode.rs @@ -9,14 +9,17 @@ use crate::llvm::refcounting::{ decrement_refcount_layout, increment_n_refcount_layout, increment_refcount_layout, }; use inkwell::attributes::{Attribute, AttributeLoc}; -use inkwell::types::{BasicType, BasicTypeEnum}; +use inkwell::context::Context; +use inkwell::types::{AnyType, BasicType, BasicTypeEnum}; use inkwell::values::{BasicValue, BasicValueEnum, CallSiteValue, FunctionValue, InstructionValue}; use inkwell::AddressSpace; +use roc_builtins::bitcode; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; use roc_mono::layout::{LambdaSet, Layout, LayoutIds, UnionLayout}; use super::build::create_entry_block_alloca; +use super::convert::zig_str_type; use std::convert::TryInto; @@ -98,6 +101,21 @@ pub fn call_void_bitcode_fn<'a, 'ctx, 'env>( .unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {:?}", fn_name)) } +fn type_attribute<'ctx>( + context: &Context, + name: &str, + basic_type: BasicTypeEnum<'ctx>, +) -> inkwell::attributes::Attribute { + let kind_id = Attribute::get_named_enum_kind_id(name); + context.create_type_attribute(kind_id, basic_type.as_any_type_enum()) +} + +fn enum_attribute<'ctx>(context: &Context, name: &str) -> inkwell::attributes::Attribute { + let kind_id = Attribute::get_named_enum_kind_id(name); + debug_assert!(kind_id > 0); + context.create_enum_attribute(kind_id, 1) +} + fn call_bitcode_fn_help<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, args: &[BasicValueEnum<'ctx>], @@ -113,6 +131,34 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>( let call = env.builder.build_call(fn_val, &arguments, "call_builtin"); + match fn_name { + bitcode::STR_NUMBER_OF_BYTES | bitcode::STR_COUNT_GRAPEHEME_CLUSTERS => { + // hacks + + let i = 0; + call.add_attribute( + AttributeLoc::Param(0), + type_attribute(env.context, "byval", zig_str_type(env).into()), + ); + + call.add_attribute( + AttributeLoc::Param(i as u32), + enum_attribute(env.context, "nonnull"), + ); + + call.add_attribute( + AttributeLoc::Param(i as u32), + enum_attribute(env.context, "nocapture"), + ); + + call.add_attribute( + AttributeLoc::Param(i as u32), + enum_attribute(env.context, "readonly"), + ); + } + _ => {} + } + call.set_call_convention(fn_val.get_call_conventions()); call }