CBackend: Implement unaligned load/store.
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 1 Feb 2008 21:25:59 +0000 (21:25 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 1 Feb 2008 21:25:59 +0000 (21:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46646 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/CBackend/CBackend.cpp
test/CodeGen/CBackend/2008-02-01-UnalignedLoadStore.ll [new file with mode: 0644]

index 2de608953d5e7d6b6a2c9458df1a046b01961527..d434eb9786df8c7f081839a256a813e186073908 100644 (file)
@@ -147,6 +147,9 @@ namespace {
     void writeOperandWithCast(Value* Operand, const ICmpInst &I);
     bool writeInstructionCast(const Instruction &I);
 
+    void writeMemoryAccess(Value *Operand, const Type *OperandType,
+                           bool IsVolatile, unsigned Alignment);
+
   private :
     std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c);
 
@@ -2935,29 +2938,47 @@ void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I,
     }
 }
 
-void CWriter::visitLoadInst(LoadInst &I) {
-  Out << '*';
-  if (I.isVolatile()) {
+void CWriter::writeMemoryAccess(Value *Operand, const Type *OperandType,
+                                bool IsVolatile, unsigned Alignment) {
+
+  bool IsUnaligned = Alignment &&
+    Alignment < TD->getABITypeAlignment(OperandType);
+
+  if (!IsUnaligned)
+    Out << '*';
+  if (IsVolatile || IsUnaligned) {
     Out << "((";
-    printType(Out, I.getType(), false, "volatile*");
+    if (IsUnaligned)
+      Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {";
+    printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*");
+    if (IsUnaligned) {
+      Out << "; } ";
+      if (IsVolatile) Out << "volatile ";
+      Out << "*";
+    }
     Out << ")";
   }
 
-  writeOperand(I.getOperand(0));
+  writeOperand(Operand);
 
-  if (I.isVolatile())
+  if (IsVolatile || IsUnaligned) {
     Out << ')';
+    if (IsUnaligned)
+      Out << "->data";
+  }
+}
+
+void CWriter::visitLoadInst(LoadInst &I) {
+
+  writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(),
+                    I.getAlignment());
+
 }
 
 void CWriter::visitStoreInst(StoreInst &I) {
-  Out << '*';
-  if (I.isVolatile()) {
-    Out << "((";
-    printType(Out, I.getOperand(0)->getType(), false, " volatile*");
-    Out << ")";
-  }
-  writeOperand(I.getPointerOperand());
-  if (I.isVolatile()) Out << ')';
+
+  writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(),
+                    I.isVolatile(), I.getAlignment());
   Out << " = ";
   Value *Operand = I.getOperand(0);
   Constant *BitMask = 0;
diff --git a/test/CodeGen/CBackend/2008-02-01-UnalignedLoadStore.ll b/test/CodeGen/CBackend/2008-02-01-UnalignedLoadStore.ll
new file mode 100644 (file)
index 0000000..269126d
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=c | \
+; RUN:          grep {struct __attribute__ ((packed, aligned(} | count 4
+
+define void @test(i32* %P) {
+        %X = load i32* %P, align 1
+        store i32 %X, i32* %P, align 1
+        ret void
+}
+
+define void @test2(i32* %P) {
+        %X = volatile load i32* %P, align 2
+        volatile store i32 %X, i32* %P, align 2
+        ret void
+}
+