diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-11-23 21:23:07 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-11-23 21:23:07 -0800 |
commit | fec33965e0ef1ce9f1e81483f758e8807ba63992 (patch) | |
tree | a3251561b53da849663858bb0b3030e32a482003 /lib/Target/CppBackend/CPPBackend.cpp | |
parent | 56fad62c5e983b81343f3d3335b64f9bafe70eb6 (diff) |
handle unaligned stores
Diffstat (limited to 'lib/Target/CppBackend/CPPBackend.cpp')
-rw-r--r-- | lib/Target/CppBackend/CPPBackend.cpp | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 079f792d93..6d5af3ebaa 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -1497,12 +1497,66 @@ std::string CppWriter::generateInstruction(const Instruction *I) { const Value *P = SI->getPointerOperand(); const Value *V = SI->getValueOperand(); std::string VS = getValueAsStr(V); - if (V->getType()->isDoubleTy() && SI->getAlignment() == 4) { - // only 4-byte aligned, copy carefully - std::string PS = getOpName(P); - text = "HEAPF64[tempDoublePtr>>3]=" + VS + ";HEAPF32[" + PS + ">>2]=HEAPF32[tempDoublePtr>>2];HEAPF32[" + PS + "+4>>2]=HEAPF32[tempDoublePtr+4>>2];"; - } else { + unsigned Bytes = V->getType()->getIntegerBitWidth()/8; + unsigned Alignment = SI->getAlignment(); + if (Bytes <= Alignment) { text = getPtrUse(P) + " = " + VS + ";"; + } else { + // unaligned in some manner + std::string PS = getOpName(P); + switch (Bytes) { + case 8: { + switch (Alignment) { + case 4: { + text = "HEAPF64[tempDoublePtr>>3]=" + VS + ";HEAP32[" + PS + ">>2]=HEAP32[tempDoublePtr>>2];HEAP32[" + PS + "+4>>2]=HEAP32[tempDoublePtr+4>>2];"; + break; + } + default: assert(0 && "bad 8 store"); + } + break; + } + case 4: { + if (V->getType()->isIntegerTy()) { + switch (Alignment) { + case 2: { + text = "HEAP16[" + PS + ">>1]=" + VS + "&65535;" + + "HEAP16[" + PS + "+2>>1]=" + VS + ">>2;"; + break; + } + case 1: { + text = "HEAP8[" + PS + "]=" + VS + "&255;" + + "HEAP8[" + PS + "+1]=(" + VS + ">>8)&255;" + + "HEAP8[" + PS + "+2]=(" + VS + ">>16)&255;" + + "HEAP8[" + PS + "+3]=" + VS + ">>24;"; + } + default: assert(0 && "bad 4i store"); + } + } else { // float + text = "HEAPF32[tempDoublePtr>>2]=" + VS + ';'; + switch (Alignment) { + case 2: { + text = "HEAP16[" + PS + ">>1]=HEAP16[tempDoublePtr>>1];" + + "HEAP16[" + PS + "+2>>1]=HEAP16[tempDoublePtr+2>>1];"; + break; + } + case 1: { + text = "HEAP8[" + PS + "]=HEAP8[tempDoublePtr];" + + "HEAP8[" + PS + "+1]=HEAP8[tempDoublePtr+1];" + + "HEAP8[" + PS + "+2]=HEAP8[tempDoublePtr+2];" + + "HEAP8[" + PS + "+3]=HEAP8[tempDoublePtr+3];"; + } + default: assert(0 && "bad 4f store"); + } + } + break; + } + case 2: { + text = "HEAP8[" + PS + "]=" + VS + "&255;" + + "HEAP8[" + PS + "+1]=" + VS + ">>8;"; + break; + } + default: assert(0 && "bad store"); + } } break; } |