From 91d6c8a987516b27bb9a08a352386191bf4bd9d7 Mon Sep 17 00:00:00 2001
From: Akash Kothari <akashk4@tyler.cs.illinois.edu>
Date: Fri, 17 Jan 2020 12:34:07 -0600
Subject: [PATCH] Added bug fixes to DFG2LLVM_X86 pass

---
 .../Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp  | 60 +++++++++++++++++--
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/hpvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp b/hpvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
index fb16c28c13..06e4e79183 100644
--- a/hpvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
+++ b/hpvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
@@ -827,12 +827,60 @@ void CGT_X86::codeGenLaunch(DFInternalNode* Root) {
   switchToTimer(visc_TimerID_COMPUTATION, CI);
   switchToTimer(visc_TimerID_OUTPUT_PACK, RI);
 
-  // Code for returning the output
-  CastInst* OutputAddrCast = CastInst::CreatePointerCast(data,
-                             CI->getType()->getPointerTo(),
-                             CI->getName()+".addr",
-                             RI);
-  new StoreInst(CI, OutputAddrCast, RI);
+  StructType *RootRetTy = cast<StructType>(RootF_X86->getFunctionType()->getReturnType());
+
+  // if Root has non empty return 
+  if (RootRetTy->getNumElements()) {
+    // We can't access the type of the arg struct - build it
+    std::vector<Type*> TyList;
+    for(Function::arg_iterator ai = RootF_X86->arg_begin(), ae = RootF_X86->arg_end();
+        ai != ae; ++ai) {
+      TyList.push_back(ai->getType());
+    }
+    TyList.push_back(CI->getType());
+
+    StructType* ArgStructTy = StructType::create(M.getContext(),
+                                                 ArrayRef<Type*>(TyList),
+                                 (RootF_X86->getName()+".arg.struct.ty").str(), true);
+
+    // Cast the data pointer to the type of the arg struct
+    CastInst* OutputAddrCast = CastInst::CreatePointerCast(data,
+                                 ArgStructTy->getPointerTo(),
+                                 "argStructCast.addr",
+                                 RI);
+
+    // Result struct is the last element of the packed struct passed to launch
+    unsigned outStructIdx = ArgStructTy->getNumElements() - 1;
+
+    ConstantInt *IntZero = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0);
+    ConstantInt *IntIdx = ConstantInt::get(Type::getInt32Ty(M.getContext()),
+                                          outStructIdx);
+
+    Value* GEPIIdxList[] = { IntZero,
+                             IntIdx
+                           };
+    // Get data pointer to the last element of struct - result field
+    GetElementPtrInst *OutGEPI =
+      GetElementPtrInst::Create(ArgStructTy,
+                                OutputAddrCast,
+                                ArrayRef<Value*>(GEPIIdxList, 2),
+                                CI->getName()+".addr",
+                                RI);
+    // Store result there
+    new StoreInst(CI, OutGEPI, RI);
+  } else {
+    // There is no return - no need to actually code gen, but for fewer
+    // changes maintain what code was already doing
+    // We were casting the data pointer to the result type of Root, and
+    // returning result there. This would work at the LLVM level, but not
+    // at the C level, thus the rewrite.
+    CastInst* OutputAddrCast = CastInst::CreatePointerCast(data,
+                               CI->getType()->getPointerTo(),
+                               CI->getName()+".addr",
+                               RI);
+    new StoreInst(CI, OutputAddrCast, RI);
+  }
+
   switchToTimer(visc_TimerID_NONE, RI);
 
   DEBUG(errs() << "Application specific function:\n");
-- 
GitLab