summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGBuiltin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 50535d386e7..e2bd9fc2c9b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -238,10 +238,20 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
llvm::Type *IntTy = llvm::IntegerType::get(C, Width);
V = CGF.Builder.CreateBitCast(V, IntTy);
if (Ty->isPPC_FP128Ty()) {
- // The higher-order double comes first, and so we need to truncate the
- // pair to extract the overall sign. The order of the pair is the same
- // in both little- and big-Endian modes.
+ // We want the sign bit of the higher-order double. The bitcast we just
+ // did works as if the double-double was stored to memory and then
+ // read as an i128. The "store" will put the higher-order double in the
+ // lower address in both little- and big-Endian modes, but the "load"
+ // will treat those bits as a different part of the i128: the low bits in
+ // little-Endian, the high bits in big-Endian. Therefore, on big-Endian
+ // we need to shift the high bits down to the low before truncating.
Width >>= 1;
+ if (CGF.getTarget().isBigEndian()) {
+ Value *ShiftCst = llvm::ConstantInt::get(IntTy, Width);
+ V = CGF.Builder.CreateLShr(V, ShiftCst);
+ }
+ // We are truncating value in order to extract the higher-order
+ // double, which we will be using to extract the sign from.
IntTy = llvm::IntegerType::get(C, Width);
V = CGF.Builder.CreateTrunc(V, IntTy);
}
OpenPOWER on IntegriCloud