Skip to content

Instantly share code, notes, and snippets.

@dtzWill
Created February 25, 2013 00:44
Show Gist options
  • Save dtzWill/5026537 to your computer and use it in GitHub Desktop.
Save dtzWill/5026537 to your computer and use it in GitHub Desktop.
Examples of ways LLVM IR does not capture signedness information in a way that's recoverable through analysis.
#include <stdio.h>
#include <limits.h>
// Easy example where IR doesn't contain source-level overflow
// -O1: 'return a + 3*b' (no nsw flags)
int test1(int a, int b) {
return a + b + b + b;
}
// Example where signedness is lost.
// -O1: 'return a + b', (no nsw flags)
int test2(int a, int b, char test) {
if (a > 0 && b > 0) {
unsigned c = a, d = b;
return c + d;
} else
return a + b;
}
// Trunc/extension errors due to promotion are generally lost:
// 'add' in this example does not have 'nsw' flag.
// -O0: signext/trunc intructions exist, 32bit add has nsw flag
// -O1: 16bit add w/o nsw flag
short a, b;
void test3() {
a = b + 1;
}
// Signedness conversions don't exist at the IR level:
// (this is lost as soon as clang converts the code to IR)
int test4(unsigned a) {
return a + 1U;
}
// PHI's make it impossible to statically
// give an SSA value a single signedness:
char test5(unsigned a, unsigned b) {
int c;
if (a > 0)
c = a + b; // Unsigned add
else
c = (int)a * (int)b; // Signed multiplication
// c = phi(c_sign, c_unsign) <-- Signedness?
return (char)c; // Emit signed or unsigned truncation check?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment