From 7779aeab21ae911fdd4847723c2f3846a841b7ec Mon Sep 17 00:00:00 2001
From: Arina Neshlyaeva <arina.neshlyaeva@intel.com>
Date: Wed, 7 Sep 2022 15:30:56 -0700
Subject: [PATCH] Extract collecting of llvm types for function args to
 separate function

---
 src/ctx.cpp  |  5 ++++-
 src/func.cpp | 14 +++++++++-----
 src/type.cpp | 19 ++++++++++++-------
 src/type.h   |  7 ++++++-
 4 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/src/ctx.cpp b/src/ctx.cpp
index 81de19b0b..171c9931d 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -3637,7 +3637,10 @@ llvm::Value *FunctionEmitContext::LaunchInst(llvm::Value *callee, std::vector<ll
     llvm::PointerType *pt = llvm::dyn_cast<llvm::PointerType>(argType);
     AssertPos(currentPos, pt);
     AssertPos(currentPos, llvm::StructType::classof(pt->PTR_ELT_TYPE()));
-    llvm::StructType *argStructType = static_cast<llvm::StructType *>(pt->PTR_ELT_TYPE());
+
+    std::vector<llvm::Type *> llvmArgTypes = funcType->LLVMFunctionArgTypes(g->ctx);
+    llvm::StructType *argStructType = llvm::StructType::get(*g->ctx, llvmArgTypes);
+    AssertPos(currentPos, argStructType != NULL);
 
     llvm::Function *falloc = m->module->getFunction("ISPCAlloc");
     AssertPos(currentPos, falloc != NULL);
diff --git a/src/func.cpp b/src/func.cpp
index 140e54366..5d846e4bd 100644
--- a/src/func.cpp
+++ b/src/func.cpp
@@ -239,15 +239,15 @@ const FunctionType *Function::GetType() const {
     local stack-allocated variables.  (Which we expect that LLVM's
     'mem2reg' pass will in turn promote to SSA registers..
  */
-static void lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const std::vector<Symbol *> &args,
+static void lCopyInTaskParameter(int i, AddressInfo *structArgPtrInfo, const std::vector<Symbol *> &args,
                                  FunctionEmitContext *ctx) {
     // We expect the argument structure to come in as a poitner to a
     // structure.  Confirm and figure out its type here.
-    const llvm::Type *structArgType = structArgPtr->getType();
+    const llvm::Type *structArgType = structArgPtrInfo->getPointer()->getType();
     Assert(llvm::isa<llvm::PointerType>(structArgType));
     const llvm::PointerType *pt = llvm::dyn_cast<const llvm::PointerType>(structArgType);
     Assert(pt);
-    Assert(llvm::isa<llvm::StructType>(pt->PTR_ELT_TYPE()));
+    Assert(llvm::isa<llvm::StructType>(structArgPtrInfo->getElementType()));
 
     // Get the type of the argument we're copying in and its Symbol pointer
     Symbol *sym = args[i];
@@ -260,7 +260,7 @@ static void lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const std::ve
     sym->storageInfo = ctx->AllocaInst(sym->type, sym->name.c_str());
 
     // get a pointer to the value in the struct
-    llvm::Value *ptr = ctx->AddElementOffset(structArgPtr, i, NULL, sym->name.c_str());
+    llvm::Value *ptr = ctx->AddElementOffset(structArgPtrInfo->getPointer(), i, NULL, sym->name.c_str());
 
     // and copy the value from the struct and into the local alloca'ed
     // memory
@@ -313,10 +313,14 @@ void Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function, Sour
         llvm::Value *taskCount0 = &*(argIter++);
         llvm::Value *taskCount1 = &*(argIter++);
         llvm::Value *taskCount2 = &*(argIter++);
+
+        std::vector<llvm::Type *> llvmArgTypes = type->LLVMFunctionArgTypes(g->ctx);
+        llvm::Type *st = llvm::StructType::get(*g->ctx, llvmArgTypes);
+
         // Copy the function parameter values from the structure into local
         // storage
         for (unsigned int i = 0; i < args.size(); ++i)
-            lCopyInTaskParameter(i, structParamPtr, args, ctx);
+            lCopyInTaskParameter(i, new AddressInfo(structParamPtr, st), args, ctx);
 
         if (type->isUnmasked == false) {
             // Copy in the mask as well.
diff --git a/src/type.cpp b/src/type.cpp
index 7880e4793..65515f98a 100644
--- a/src/type.cpp
+++ b/src/type.cpp
@@ -2518,17 +2518,13 @@ FunctionType::FunctionMangledName FunctionType::GetFunctionMangledName(bool appF
     return mangle;
 }
 
-llvm::FunctionType *FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
-    if (!g->target->isXeTarget() && isTask == true) {
-        Assert(removeMask == false);
-    }
-
+std::vector<llvm::Type *> FunctionType::LLVMFunctionArgTypes(llvm::LLVMContext *ctx, bool removeMask) const {
     // Get the LLVM Type *s for the function arguments
     std::vector<llvm::Type *> llvmArgTypes;
     for (unsigned int i = 0; i < paramTypes.size(); ++i) {
         if (paramTypes[i] == NULL) {
             Assert(m->errorCount > 0);
-            return NULL;
+            return llvmArgTypes;
         }
         Assert(paramTypes[i]->IsVoidType() == false);
 
@@ -2559,7 +2555,7 @@ llvm::FunctionType *FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool
 
         if (castedArgType == NULL) {
             Assert(m->errorCount > 0);
-            return NULL;
+            return llvmArgTypes;
         }
         llvmArgTypes.push_back(castedArgType);
     }
@@ -2568,6 +2564,15 @@ llvm::FunctionType *FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool
     if (!(removeMask || isUnmasked || IsISPCKernel())) {
         llvmArgTypes.push_back(LLVMTypes::MaskType);
     }
+    return llvmArgTypes;
+}
+
+llvm::FunctionType *FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
+    if (!g->target->isXeTarget() && isTask == true) {
+        Assert(removeMask == false);
+    }
+
+    std::vector<llvm::Type *> llvmArgTypes = LLVMFunctionArgTypes(ctx, removeMask);
 
     std::vector<llvm::Type *> callTypes;
     if (isTask && (!g->target->isXeTarget())) {
diff --git a/src/type.h b/src/type.h
index ba59f6213..7633e0da8 100644
--- a/src/type.h
+++ b/src/type.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2010-2021, Intel Corporation
+  Copyright (c) 2010-2022, Intel Corporation
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
@@ -888,6 +888,11 @@ class FunctionType : public Type {
         internal ISPC call or for external call from application.*/
     FunctionMangledName GetFunctionMangledName(bool appFunction) const;
 
+    /** This method returns std::vector of LLVM types of function arguments.
+        The \c disableMask parameter indicates whether the mask parameter should be
+        included to the list of arguments types. */
+    std::vector<llvm::Type *> LLVMFunctionArgTypes(llvm::LLVMContext *ctx, bool disableMask = false) const;
+
     /** This method returns the LLVM FunctionType that corresponds to this
         function type.  The \c disableMask parameter indicates whether the
         llvm::FunctionType should have the trailing mask parameter, if
