aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_utility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm_backend_utility.cpp')
-rw-r--r--src/llvm_backend_utility.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index dbed32b82..a4ef61531 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -868,6 +868,45 @@ gb_internal lbValue lb_address_from_load(lbProcedure *p, lbValue value) {
return {};
}
+gb_internal lbValue lb_address_from_load_if_readonly_parameter(lbProcedure *p, lbValue x) {
+ if (!LLVMIsALoadInst(x.value)) {
+ return {};
+ }
+
+ LLVMValueRef optr = LLVMGetOperand(x.value, 0);
+ while (optr && LLVMIsABitCastInst(optr)) {
+ optr = LLVMGetOperand(optr, 0);
+ }
+ LLVMAttributeIndex param_index = 1;
+ if (p->return_ptr.addr.value) {
+ param_index++;
+ }
+
+ bool is_parameter = false;
+ for (LLVMValueRef param : p->raw_input_parameters) {
+ if (param == optr) {
+ is_parameter = true;
+ break;
+ }
+ param_index++;
+ }
+ if (is_parameter) {
+ unsigned readonly_attr_kind = LLVMGetEnumAttributeKindForName("readonly", 8);
+ unsigned n = LLVMGetAttributeCountAtIndex(p->value, param_index);
+ if (n) {
+ TEMPORARY_ALLOCATOR_GUARD();
+ LLVMAttributeRef *attrs = gb_alloc_array(temporary_allocator(), LLVMAttributeRef, n);
+ LLVMGetAttributesAtIndex(p->value, param_index, attrs);
+ for (unsigned i = 0; i < n; i++) {
+ if (LLVMGetEnumAttributeKind(attrs[i]) == readonly_attr_kind) {
+ return lb_address_from_load_or_generate_local(p, x);
+ }
+ }
+ }
+ }
+ return {};
+}
+
gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t) {
t = base_type(t);