I'm writing a programming language called PPL.
In PPL integer literals are arbitrary width by default. This is archived with using pointer to GMP's mpz_class
for integers.
However, when compiling -1
, there is an error from address sanitiser:
==92833==ERROR: AddressSanitizer: SEGV on unknown address 0x000100000006 (pc 0x000105564bc4 bp 0x000105019f14 sp 0x00016ce45e50 T0)
==92833==The signal is caused by a UNKNOWN memory access.
#0 0x105564bc4 in __gmpz_neg+0x14 (libgmp.10.dylib:arm64+0x14bc4) (BuildId: efc29ca33b2a3664976db890d76d3d0832000000200000000100000000000c00)
Here are parts of runtime, related to the problem:
// Temporary solution for not leaking memory,
// as I haven't implemented memory management yet
std::unordered_set<mpz_class> values;
// PPL's big integer type
using Integer = const mpz_class *;
extern "C" {
// Used to create integer from literal
Integer _IntegerConstructorFromCString(const char *string)
{
assert(string);
// Inserts value and returns pointer to it
return &*values.emplace(mpz_class(string)).first;
}
/// - <:Integer> -> Integer
Integer _MinusInteger(Integer value)
{
// I checked in debugger, here value is 0x000100000006,
// which isn't a pointer I returned from _IntegerConstructorFromCString
assert(value);
// Inserts value and returns pointer to it
return &*values.emplace(-*value).first;
}
} // extern "C"
Here is LLVM IR generated by PPL's compiler:
@.str = private unnamed_addr constant [2 x i8] c"1\00", align 1
// Code for "-1" top level expression
define void @_top_level_code() {
// Create integer from "1"
%1 = call ptr @_IntegerConstructorFromCString(ptr getelementptr inbounds ([2 x i8], ptr @.str, i32 0, i32 0))
// Get -1
%2 = call ptr @"- <:Integer>"(ptr %1)
ret void
}
// Function from runtime
declare ptr @_MinusInteger(ptr %0)
// PPL's operator that hides runtime function invokation
define ptr @"- <:Integer>"(ptr %a) {
%1 = load ptr, ptr %a, align 8
%2 = call ptr @_MinusInteger(ptr %1)
ret ptr %2
}
What's wrong with my code?
P.S: may the problem be in the way I access function argument without alloca? Or I don't dereference a pointer somewhere? (hard to say for me, as all of them are opaque)
I solved the problem with removing load of function arguments.
Instead of:
define ptr @"- <:Integer>"(ptr %a) {
%1 = load ptr, ptr %a, align 8 // This is wrong for some reason.
// Looks like arguments aren't pointers themself
%2 = call ptr @_MinusInteger(ptr %1)
ret ptr %2
}
Compiler now generates:
define ptr @"- <:Integer>"(ptr %a) {
%1 = call ptr @_MinusInteger(ptr %a)
ret ptr %1
}