1 IR builder. Kill greenland. Remove JTypeSpace.

Change-Id: I7d08cfd8c1fec46df4ce5f51706dff2e246695b5
diff --git a/src/compiler_llvm/intrinsic_helper.cc b/src/compiler_llvm/intrinsic_helper.cc
new file mode 100644
index 0000000..3bb6948
--- /dev/null
+++ b/src/compiler_llvm/intrinsic_helper.cc
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "intrinsic_helper.h"
+
+#include "ir_builder.h"
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/Support/IRBuilder.h>
+
+using namespace art;
+using namespace compiler_llvm;
+
+namespace {
+
+inline llvm::Type*
+GetLLVMTypeOfIntrinsicValType(IRBuilder& irb,
+                              IntrinsicHelper::IntrinsicValType type) {
+  switch (type) {
+    case IntrinsicHelper::kVoidTy: {
+      return irb.getVoidTy();
+    }
+    case IntrinsicHelper::kJavaObjectTy: {
+      return irb.getJObjectTy();
+    }
+    case IntrinsicHelper::kJavaMethodTy: {
+      return irb.getJMethodTy();
+    }
+    case IntrinsicHelper::kJavaThreadTy: {
+      return irb.getJThreadTy();
+    }
+    case IntrinsicHelper::kInt1Ty:
+    case IntrinsicHelper::kInt1ConstantTy: {
+      return irb.getInt1Ty();
+    }
+    case IntrinsicHelper::kInt8Ty:
+    case IntrinsicHelper::kInt8ConstantTy: {
+      return irb.getInt8Ty();
+    }
+    case IntrinsicHelper::kInt16Ty:
+    case IntrinsicHelper::kInt16ConstantTy: {
+      return irb.getInt16Ty();
+    }
+    case IntrinsicHelper::kInt32Ty:
+    case IntrinsicHelper::kInt32ConstantTy: {
+      return irb.getInt32Ty();
+    }
+    case IntrinsicHelper::kInt64Ty:
+    case IntrinsicHelper::kInt64ConstantTy: {
+      return irb.getInt64Ty();
+    }
+    case IntrinsicHelper::kFloatTy:
+    case IntrinsicHelper::kFloatConstantTy: {
+      return irb.getFloatTy();
+    }
+    case IntrinsicHelper::kDoubleTy:
+    case IntrinsicHelper::kDoubleConstantTy: {
+      return irb.getDoubleTy();
+    }
+    case IntrinsicHelper::kNone:
+    case IntrinsicHelper::kVarArgTy:
+    default: {
+      LOG(FATAL) << "Invalid intrinsic type " << type << "to get LLVM type!";
+      return NULL;
+    }
+  }
+  // unreachable
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace compiler_llvm {
+
+const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[] = {
+#define DEF_INTRINSICS_FUNC(_, NAME, ATTR, RET_TYPE, ARG1_TYPE, ARG2_TYPE, \
+                                                     ARG3_TYPE, ARG4_TYPE, \
+                                                     ARG5_TYPE) \
+  { #NAME, ATTR, RET_TYPE, { ARG1_TYPE, ARG2_TYPE, \
+                             ARG3_TYPE, ARG4_TYPE, \
+                             ARG5_TYPE} },
+#include "intrinsic_func_list.def"
+};
+
+IntrinsicHelper::IntrinsicHelper(llvm::LLVMContext& context,
+                                 llvm::Module& module) {
+  IRBuilder irb(context, module, *this);
+
+  ::memset(intrinsic_funcs_, 0, sizeof(intrinsic_funcs_));
+
+  // This loop does the following things:
+  // 1. Introduce the intrinsic function into the module
+  // 2. Add "nocapture" and "noalias" attribute to the arguments in all
+  //    intrinsics functions.
+  // 3. Initialize intrinsic_funcs_map_.
+  for (unsigned i = 0; i < MaxIntrinsicId; i++) {
+    IntrinsicId id = static_cast<IntrinsicId>(i);
+    const IntrinsicInfo& info = Info[i];
+
+    // Parse and construct the argument type from IntrinsicInfo
+    llvm::Type* arg_type[kIntrinsicMaxArgc];
+    unsigned num_args = 0;
+    bool is_var_arg = false;
+    for (unsigned arg_iter = 0; arg_iter < kIntrinsicMaxArgc; arg_iter++) {
+      IntrinsicValType type = info.arg_type_[arg_iter];
+
+      if (type == kNone) {
+        break;
+      } else if (type == kVarArgTy) {
+        // Variable argument type must be the last argument
+        is_var_arg = true;
+        break;
+      }
+
+      arg_type[num_args++] = GetLLVMTypeOfIntrinsicValType(irb, type);
+    }
+
+    // Construct the function type
+    llvm::Type* ret_type =
+        GetLLVMTypeOfIntrinsicValType(irb, info.ret_val_type_);
+
+    llvm::FunctionType* type =
+        llvm::FunctionType::get(ret_type,
+                                llvm::ArrayRef<llvm::Type*>(arg_type, num_args),
+                                is_var_arg);
+
+    // Declare the function
+    llvm::Function *fn = llvm::Function::Create(type,
+                                                llvm::Function::ExternalLinkage,
+                                                info.name_, &module);
+
+    fn->setOnlyReadsMemory(info.attr_ & kAttrReadOnly);
+    fn->setDoesNotAccessMemory(info.attr_ & kAttrReadNone);
+    // None of the intrinsics throws exception
+    fn->setDoesNotThrow(true);
+
+    intrinsic_funcs_[id] = fn;
+
+    DCHECK_NE(fn, static_cast<llvm::Function*>(NULL)) << "Intrinsic `"
+        << GetName(id) << "' was not defined!";
+
+    // Add "noalias" and "nocapture" attribute to all arguments of pointer type
+    for (llvm::Function::arg_iterator arg_iter = fn->arg_begin(),
+            arg_end = fn->arg_end(); arg_iter != arg_end; arg_iter++) {
+      if (arg_iter->getType()->isPointerTy()) {
+        arg_iter->addAttr(llvm::Attribute::NoCapture);
+        arg_iter->addAttr(llvm::Attribute::NoAlias);
+      }
+    }
+
+    // Insert the newly created intrinsic to intrinsic_funcs_map_
+    if (!intrinsic_funcs_map_.insert(std::make_pair(fn, id)).second) {
+      LOG(FATAL) << "Duplicate entry in intrinsic functions map?";
+    }
+  }
+
+  return;
+}
+
+} // namespace compiler_llvm
+} // namespace art