1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
25e3b677a3041c86a7f860238dd1f5ff9d111b507Stephen Hines * Copyright 2010-2012, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_backend.h"
18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <vector>
213a6750f246eed4168351786074691e8eeee5b175David Gross#include <iostream>
22462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
23e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/AST/ASTContext.h"
2465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross#include "clang/AST/Attr.h"
259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/Decl.h"
269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/DeclGroup.h"
273a6750f246eed4168351786074691e8eeee5b175David Gross#include "clang/AST/RecordLayout.h"
28462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Basic/Diagnostic.h"
30e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/Basic/TargetInfo.h"
319ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Basic/TargetOptions.h"
32462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/CodeGen/ModuleBuilder.h"
34e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
353a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang#include "clang/Frontend/CodeGenOptions.h"
369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Frontend/FrontendDiagnostic.h"
37462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
388024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/ADT/Twine.h"
398024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/ADT/StringExtras.h"
40e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
41e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Bitcode/ReaderWriter.h"
42e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
43e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/CodeGen/RegAllocRegistry.h"
44e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/CodeGen/SchedulerRegistry.h"
45e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/Constant.h"
478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/Constants.h"
488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/DataLayout.h"
498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/DebugLoc.h"
508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/DerivedTypes.h"
518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/Function.h"
528024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/IRBuilder.h"
538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/IRPrintingPasses.h"
5423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/LLVMContext.h"
5523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/Metadata.h"
568024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "llvm/IR/Module.h"
57e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
589207a2e495c8363606861e4f034504ec5c153dabLogan Chien#include "llvm/Transforms/IPO/PassManagerBuilder.h"
59fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao
60e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Target/TargetMachine.h"
61e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Target/TargetOptions.h"
629207a2e495c8363606861e4f034504ec5c153dabLogan Chien#include "llvm/Support/TargetRegistry.h"
6377703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao
6477703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao#include "llvm/MC/SubtargetFeature.h"
65462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
666e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang.h"
68dabd246c169fe8bc7d80a31779311bfc583b2ea0Matt Wala#include "slang_bitcode_gen.h"
698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_context.h"
708024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_export_foreach.h"
718024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_export_func.h"
72c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala#include "slang_rs_export_reduce.h"
738024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_export_type.h"
748024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_export_var.h"
758024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang_rs_metadata.h"
768024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
772770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross#include "rs_cc_options.h"
782770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross
7988cd94d5165bf8a266d3f3095946fc25bc4809afDavid Gross#include "StripUnkAttr/strip_unknown_attributes_pass.h"
806315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
813c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummondnamespace {
823c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummondclass VersionInfoPass : public llvm::ModulePass {
833c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  const clang::CodeGenOptions &mCodeGenOpts;
843c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond
853c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  const char *getSlangLLVMVersion() const {
863c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    if (mCodeGenOpts.getDebugInfo() != clang::codegenoptions::NoDebugInfo)
873c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      return LLVM_VERSION_STRING;
883c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    return nullptr;
893c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  }
903c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond
913c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummondpublic:
923c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  static char ID;
933c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  VersionInfoPass(const clang::CodeGenOptions &codegenOpts)
943c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      : ModulePass(ID), mCodeGenOpts(codegenOpts) {}
953c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  virtual bool runOnModule(llvm::Module &M) override {
963c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    const char *versionString = getSlangLLVMVersion();
973c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    if (!versionString)
983c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      return false;
993c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    auto &ctx = M.getContext();
1003c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    auto md = M.getOrInsertNamedMetadata("slang.llvm.version");
1013c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    auto ver = llvm::MDString::get(ctx, versionString);
1023c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    md->addOperand(
1033c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond        llvm::MDNode::get(ctx, llvm::ArrayRef<llvm::Metadata *>(ver)));
1043c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    return true;
1053c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  }
1063c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond};
1073c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond
1083c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummondchar VersionInfoPass::ID = 0;
1093c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond
1103c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummondllvm::ModulePass *createVersionInfoPass(const clang::CodeGenOptions &cgo) {
1113c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond  return new VersionInfoPass(cgo);
1123c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond}
1133c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond}
1143c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond
115e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
116462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1173a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Changvoid Backend::CreateFunctionPasses() {
1183a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  if (!mPerFunctionPasses) {
119c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines    mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
1203a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang
121fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    llvm::PassManagerBuilder PMBuilder;
122fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
123fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
1243a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  }
1253a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang}
1263a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang
1273a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Changvoid Backend::CreateModulePasses() {
1283a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  if (!mPerModulePasses) {
129c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines    mPerModulePasses = new llvm::legacy::PassManager();
1303a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang
131fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    llvm::PassManagerBuilder PMBuilder;
132fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
133fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
134b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar    PMBuilder.DisableUnitAtATime = 0; // TODO Pirama confirm if this is right
135fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao
136fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    if (mCodeGenOpts.UnrollLoops) {
137fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao      PMBuilder.DisableUnrollLoops = 0;
138fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    } else {
139fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao      PMBuilder.DisableUnrollLoops = 1;
140fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    }
141fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao
142fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao    PMBuilder.populateModulePassManager(*mPerModulePasses);
143552d872e5cdc883d9f8e76d8c67d3a82e3ece488Stephen Hines    // Add a pass to strip off unknown/unsupported attributes.
144552d872e5cdc883d9f8e76d8c67d3a82e3ece488Stephen Hines    mPerModulePasses->add(createStripUnknownAttributesPass());
1453c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    if (!mContext->isCompatLib()) {
1463c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      // The version info pass is used to ensure that debugging
1473c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      // is matched between slang and bcc.
1483c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond      mPerModulePasses->add(createVersionInfoPass(mCodeGenOpts));
1493c11a752490bc5221a123623b9c7a07845b51ce1Luke Drummond    }
1503a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  }
1513a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang}
1523a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang
153462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaobool Backend::CreateCodeGenPasses() {
1543a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
1559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return true;
156462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Now we add passes for code emitting
1589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mCodeGenPasses) {
159462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    return true;
1609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
161c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines    mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule);
1629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create the TargetMachine for generating code.
1659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  std::string Triple = mpModule->getTargetTriple();
1669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  std::string Error;
1689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const llvm::Target* TargetInfo =
1699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      llvm::TargetRegistry::lookupTarget(Triple, Error);
1705abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (TargetInfo == nullptr) {
1719207a2e495c8363606861e4f034504ec5c153dabLogan Chien    mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
1729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
1739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
175ac4e18584b8768b3f68535fa5f16232e03974323Logan Chien  // Target Machine Options
176ac4e18584b8768b3f68535fa5f16232e03974323Logan Chien  llvm::TargetOptions Options;
177ac4e18584b8768b3f68535fa5f16232e03974323Logan Chien
178167bd79e95d496474346fcb9b2905d42ab55d750Pirama Arumuga Nainar  // Use soft-float ABI for ARM (which is the target used by Slang during code
179167bd79e95d496474346fcb9b2905d42ab55d750Pirama Arumuga Nainar  // generation).  Codegen still uses hardware FPU by default.  To use software
180167bd79e95d496474346fcb9b2905d42ab55d750Pirama Arumuga Nainar  // floating point, add 'soft-float' feature to FeaturesStr below.
181167bd79e95d496474346fcb9b2905d42ab55d750Pirama Arumuga Nainar  Options.FloatABIType = llvm::FloatABI::Soft;
1829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // BCC needs all unknown symbols resolved at compilation time. So we don't
1849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // need any relocation model.
185ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien  llvm::Reloc::Model RM = llvm::Reloc::Static;
1869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
18741ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang  // This is set for the linker (specify how large of the virtual addresses we
18841ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang  // can access for all unknown symbols.)
1899207a2e495c8363606861e4f034504ec5c153dabLogan Chien  llvm::CodeModel::Model CM;
1900b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines  if (mpModule->getDataLayout().getPointerSize() == 4) {
1919207a2e495c8363606861e4f034504ec5c153dabLogan Chien    CM = llvm::CodeModel::Small;
1929207a2e495c8363606861e4f034504ec5c153dabLogan Chien  } else {
19341ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang    // The target may have pointer size greater than 32 (e.g. x86_64
19441ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang    // architecture) may need large data address model
1959207a2e495c8363606861e4f034504ec5c153dabLogan Chien    CM = llvm::CodeModel::Medium;
1969207a2e495c8363606861e4f034504ec5c153dabLogan Chien  }
1979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Setup feature string
1999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  std::string FeaturesStr;
2009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
2019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    llvm::SubtargetFeatures Features;
2029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    for (std::vector<std::string>::const_iterator
2049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao             I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
2059ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I != E;
2069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I++)
2079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      Features.AddFeature(*I);
2089ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    FeaturesStr = Features.getString();
2109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
2119207a2e495c8363606861e4f034504ec5c153dabLogan Chien
2129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::TargetMachine *TM =
2139207a2e495c8363606861e4f034504ec5c153dabLogan Chien    TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
214ac4e18584b8768b3f68535fa5f16232e03974323Logan Chien                                    Options, RM, CM);
2159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2169ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Register allocation policy:
2179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  //  createFastRegisterAllocator: fast but bad quality
2182c6bad5038d8509466b9e0f9aa6a8ae533c0e029Logan Chien  //  createGreedyRegisterAllocator: not so fast but good quality
2199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
2209ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     llvm::createFastRegisterAllocator :
2212c6bad5038d8509466b9e0f9aa6a8ae533c0e029Logan Chien                                     llvm::createGreedyRegisterAllocator);
2229ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
22477703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao  if (mCodeGenOpts.OptimizationLevel == 0) {
2259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    OptLevel = llvm::CodeGenOpt::None;
22677703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao  } else if (mCodeGenOpts.OptimizationLevel == 3) {
2279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    OptLevel = llvm::CodeGenOpt::Aggressive;
22877703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao  }
2299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2309ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::TargetMachine::CodeGenFileType CGFT =
2316315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      llvm::TargetMachine::CGFT_AssemblyFile;
23277703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao  if (mOT == Slang::OT_Object) {
2339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    CGFT = llvm::TargetMachine::CGFT_ObjectFile;
23477703262b9c2fecc22287ca236daa72b2cea7d27Shih-wei Liao  }
23521cc01860b95cad7ae60c686e511e8f4ae034e39Pirama Arumuga Nainar  if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream,
2369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                              CGFT, OptLevel)) {
2379207a2e495c8363606861e4f034504ec5c153dabLogan Chien    mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
2389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
2399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
2409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
2419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return true;
242462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
243462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc BrouilletBackend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
2458f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar                 const RSCCOptions &Opts,
2468f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar                 const clang::HeaderSearchOptions &HeaderSearchOpts,
2478f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar                 const clang::PreprocessorOptions &PreprocessorOpts,
2488f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar                 const clang::CodeGenOptions &CodeGenOpts,
2498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                 const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
2508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                 llvm::raw_ostream *OS, Slang::OutputType OT,
2518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                 clang::SourceManager &SourceMgr, bool AllowRSPrefix,
2528024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                 bool IsFilterscript)
2538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
2548024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
25521cc01860b95cad7ae60c686e511e8f4ae034e39Pirama Arumuga Nainar      mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
25621cc01860b95cad7ae60c686e511e8f4ae034e39Pirama Arumuga Nainar      mBufferOutStream(*mpOS), mContext(Context),
2572770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross      mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
2588024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
2598024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
260dbf5b61ea24012f883e238fd17bdca0758f181d6David Gross      mExportForEachSignatureMetadata(nullptr),
2618ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      mExportReduceMetadata(nullptr),
262c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
263c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      mRefCount(mContext->getASTContext()),
2648024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
265fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mForEachHandler(Context),
266b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar      mLLVMContext(slang::getGlobalLLVMContext()), mDiagEngine(*DiagEngine),
2678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
2688f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar  mGen = CreateLLVMCodeGen(mDiagEngine, "", HeaderSearchOpts, PreprocessorOpts,
2698f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar      mCodeGenOpts, mLLVMContext);
270462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
271462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid Backend::Initialize(clang::ASTContext &Ctx) {
2739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  mGen->Initialize(Ctx);
274462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  mpModule = mGen->GetModule();
276462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
277462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
27968fc02ca4a7235e2981be5eee4ad968a9d3928c0Zonr Chang  HandleTranslationUnitPre(Ctx);
28068fc02ca4a7235e2981be5eee4ad968a9d3928c0Zonr Chang
2812770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross  if (mASTPrint)
2822770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross    Ctx.getTranslationUnitDecl()->dump();
2832770d0e31ef3b14cd51ca07273240ad0995dc5cdDavid Gross
2849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  mGen->HandleTranslationUnit(Ctx);
285462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Here, we complete a translation unit (whole translation unit is now in LLVM
2879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // IR). Now, interact with LLVM backend to generate actual machine code (asm
2889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // or machine code, whatever.)
289462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Silently ignore if we weren't initialized for some reason.
29141ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang  if (!mpModule)
2929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
293462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::Module *M = mGen->ReleaseModule();
2959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!M) {
2969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // The module has been released by IR gen on failures, do not double free.
2975abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    mpModule = nullptr;
2989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
2999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
3009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3016e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(mpModule == M &&
3026e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "Unexpected module change during LLVM IR generation");
3039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Insert #pragma information into metadata section of module
3053fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines  if (!mPragmas->empty()) {
3069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    llvm::NamedMDNode *PragmaMetadata =
3079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
3083fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
3099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I != E;
3109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I++) {
311c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines      llvm::SmallVector<llvm::Metadata*, 2> Pragma;
3129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Name goes first
3139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
3149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // And then value
3159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
31683f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao
3179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Create MDNode and insert into PragmaMetadata
3189ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      PragmaMetadata->addOperand(
31918c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines          llvm::MDNode::get(mLLVMContext, Pragma));
320462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
3219ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
322462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
32368fc02ca4a7235e2981be5eee4ad968a9d3928c0Zonr Chang  HandleTranslationUnitPost(mpModule);
324462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create passes for optimization and code emission
326462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create and run per-function passes
3289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  CreateFunctionPasses();
3299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mPerFunctionPasses) {
3309ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mPerFunctionPasses->doInitialization();
331462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3329ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
3339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I != E;
3349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao         I++)
3359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      if (!I->isDeclaration())
3369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        mPerFunctionPasses->run(*I);
337462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mPerFunctionPasses->doFinalization();
3399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
340462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create and run module passes
3429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  CreateModulePasses();
3439ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mPerModulePasses)
3449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mPerModulePasses->run(*mpModule);
3459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3463a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang  switch (mOT) {
3473a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang    case Slang::OT_Assembly:
3483a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang    case Slang::OT_Object: {
3496315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      if (!CreateCodeGenPasses())
3509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        return;
351462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      mCodeGenPasses->doInitialization();
353462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
3559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          I != E;
3569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          I++)
3576315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr        if (!I->isDeclaration())
3589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          mCodeGenPasses->run(*I);
3599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      mCodeGenPasses->doFinalization();
3619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
3629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
3633a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang    case Slang::OT_LLVMAssembly: {
364c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines      llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
36521cc01860b95cad7ae60c686e511e8f4ae034e39Pirama Arumuga Nainar      LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
3669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      LLEmitPM->run(*mpModule);
3679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
368462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
3693a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang    case Slang::OT_Bitcode: {
370dabd246c169fe8bc7d80a31779311bfc583b2ea0Matt Wala      writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
371b130e157d3a5c2256e7aa0005d7134f3ac060c56Stephen McGroarty                   mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
3729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
3739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
3743a9ca1f0d6bd8f12c2bb2adea51f95c255996180Zonr Chang    case Slang::OT_Nothing: {
3759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      return;
3769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
3779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    default: {
3786e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Unknown output type");
3799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
3809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
381462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
382462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
3833a6750f246eed4168351786074691e8eeee5b175David Gross// Insert explicit padding fields into struct to follow the current layout.
3843a6750f246eed4168351786074691e8eeee5b175David Gross//
3853a6750f246eed4168351786074691e8eeee5b175David Gross// A similar algorithm is present in PadHelperFunctionStruct().
3863a6750f246eed4168351786074691e8eeee5b175David Grossvoid Backend::PadStruct(clang::RecordDecl* RD) {
3873a6750f246eed4168351786074691e8eeee5b175David Gross  // Example of padding:
3883a6750f246eed4168351786074691e8eeee5b175David Gross  //
3893a6750f246eed4168351786074691e8eeee5b175David Gross  //   // ORIGINAL CODE                   // TRANSFORMED CODE
3903a6750f246eed4168351786074691e8eeee5b175David Gross  //   struct foo {                       struct foo {
3913a6750f246eed4168351786074691e8eeee5b175David Gross  //     int a;                             int a;
3923a6750f246eed4168351786074691e8eeee5b175David Gross  //     // 4 bytes of padding              char <RS_PADDING_FIELD_NAME>[4];
3933a6750f246eed4168351786074691e8eeee5b175David Gross  //     long b;                            long b;
3943a6750f246eed4168351786074691e8eeee5b175David Gross  //     int c;                             int c;
3953a6750f246eed4168351786074691e8eeee5b175David Gross  //     // 4 bytes of (tail) padding       char <RS_PADDING_FIELD_NAME>[4];
3963a6750f246eed4168351786074691e8eeee5b175David Gross  //   };                                 };
3973a6750f246eed4168351786074691e8eeee5b175David Gross
3983a6750f246eed4168351786074691e8eeee5b175David Gross  // We collect all of RD's fields in a vector FieldsInfo.  We
3993a6750f246eed4168351786074691e8eeee5b175David Gross  // represent tail padding as an entry in the FieldsInfo vector with a
4003a6750f246eed4168351786074691e8eeee5b175David Gross  // null FieldDecl.
4013a6750f246eed4168351786074691e8eeee5b175David Gross  typedef std::pair<size_t, clang::FieldDecl*> FieldInfoType;  // (pre-field padding bytes, field)
4023a6750f246eed4168351786074691e8eeee5b175David Gross  std::vector<FieldInfoType> FieldsInfo;
4033a6750f246eed4168351786074691e8eeee5b175David Gross
4043a6750f246eed4168351786074691e8eeee5b175David Gross  // RenderScript is C99-based, so we only expect to see fields.  We
4053a6750f246eed4168351786074691e8eeee5b175David Gross  // could iterate over fields, but instead let's iterate over
4063a6750f246eed4168351786074691e8eeee5b175David Gross  // everything, to verify that there are only fields.
4073a6750f246eed4168351786074691e8eeee5b175David Gross  for (clang::Decl* D : RD->decls()) {
4083a6750f246eed4168351786074691e8eeee5b175David Gross    clang::FieldDecl* FD = clang::dyn_cast<clang::FieldDecl>(D);
4093a6750f246eed4168351786074691e8eeee5b175David Gross    slangAssert(FD && "found a non field declaration within a struct");
4103a6750f246eed4168351786074691e8eeee5b175David Gross    FieldsInfo.push_back(std::make_pair(size_t(0), FD));
4113a6750f246eed4168351786074691e8eeee5b175David Gross  }
4123a6750f246eed4168351786074691e8eeee5b175David Gross
4133a6750f246eed4168351786074691e8eeee5b175David Gross  clang::ASTContext& ASTC = mContext->getASTContext();
4143a6750f246eed4168351786074691e8eeee5b175David Gross
4153a6750f246eed4168351786074691e8eeee5b175David Gross  // ASTContext caches record layout.  We may transform the record in a way
4163a6750f246eed4168351786074691e8eeee5b175David Gross  // that would render this cached information incorrect.  clang does
4173a6750f246eed4168351786074691e8eeee5b175David Gross  // not provide any way to invalidate this cached information.  We
4183a6750f246eed4168351786074691e8eeee5b175David Gross  // take the following approach:
4193a6750f246eed4168351786074691e8eeee5b175David Gross  //
4203a6750f246eed4168351786074691e8eeee5b175David Gross  // 1. ASSUME that record layout has not yet been computed for RD.
4213a6750f246eed4168351786074691e8eeee5b175David Gross  //
4223a6750f246eed4168351786074691e8eeee5b175David Gross  // 2. Create a temporary clone of RD, and compute its layout.
4233a6750f246eed4168351786074691e8eeee5b175David Gross  //    ASSUME that we know how to clone RD in a way that copies all the
4243a6750f246eed4168351786074691e8eeee5b175David Gross  //    properties that are relevant to its layout.
4253a6750f246eed4168351786074691e8eeee5b175David Gross  //
4263a6750f246eed4168351786074691e8eeee5b175David Gross  // 3. Use the layout information from the temporary clone to
4273a6750f246eed4168351786074691e8eeee5b175David Gross  //    transform RD.
4283a6750f246eed4168351786074691e8eeee5b175David Gross  //
4293a6750f246eed4168351786074691e8eeee5b175David Gross  // NOTE: ASTContext also caches TypeInfo (see
4303a6750f246eed4168351786074691e8eeee5b175David Gross  //       ASTContext::getTypeInfo()).  ASSUME that inserting padding
4313a6750f246eed4168351786074691e8eeee5b175David Gross  //       fields doesn't change the type in any way that affects
4323a6750f246eed4168351786074691e8eeee5b175David Gross  //       TypeInfo.
4333a6750f246eed4168351786074691e8eeee5b175David Gross  //
4343a6750f246eed4168351786074691e8eeee5b175David Gross  // NOTE: A RecordType knows its associated RecordDecl -- so even
4353a6750f246eed4168351786074691e8eeee5b175David Gross  //       while we're manipulating RD, the associated RecordType
4363a6750f246eed4168351786074691e8eeee5b175David Gross  //       still recognizes RD as its RecordDecl.  ASSUME that we
4373a6750f246eed4168351786074691e8eeee5b175David Gross  //       don't do anything during our manipulation that would cause
4383a6750f246eed4168351786074691e8eeee5b175David Gross  //       the RecordType to be followed to RD while RD is in a
4393a6750f246eed4168351786074691e8eeee5b175David Gross  //       partially transformed state.
4403a6750f246eed4168351786074691e8eeee5b175David Gross
4413a6750f246eed4168351786074691e8eeee5b175David Gross  // The assumptions above may be brittle, and if they are incorrect,
4423a6750f246eed4168351786074691e8eeee5b175David Gross  // we may get mysterious failures.
4433a6750f246eed4168351786074691e8eeee5b175David Gross
4443a6750f246eed4168351786074691e8eeee5b175David Gross  // create a temporary clone
4453a6750f246eed4168351786074691e8eeee5b175David Gross  clang::RecordDecl* RDForLayout =
4463a6750f246eed4168351786074691e8eeee5b175David Gross      clang::RecordDecl::Create(ASTC, clang::TTK_Struct, RD->getDeclContext(),
4473a6750f246eed4168351786074691e8eeee5b175David Gross                                clang::SourceLocation(), clang::SourceLocation(),
4483a6750f246eed4168351786074691e8eeee5b175David Gross                                nullptr /* IdentifierInfo */);
4493a6750f246eed4168351786074691e8eeee5b175David Gross  RDForLayout->startDefinition();
4503a6750f246eed4168351786074691e8eeee5b175David Gross  RDForLayout->setTypeForDecl(RD->getTypeForDecl());
451352e62d65caa48251d9c69cc8b5a82ddfea6b014I-Jui (Ray) Sung  if (RD->hasAttrs())
452352e62d65caa48251d9c69cc8b5a82ddfea6b014I-Jui (Ray) Sung    RDForLayout->setAttrs(RD->getAttrs());
4533a6750f246eed4168351786074691e8eeee5b175David Gross  RDForLayout->completeDefinition();
4543a6750f246eed4168351786074691e8eeee5b175David Gross
4553a6750f246eed4168351786074691e8eeee5b175David Gross  // move all fields from RD to RDForLayout
4563a6750f246eed4168351786074691e8eeee5b175David Gross  for (const auto &info : FieldsInfo) {
4573a6750f246eed4168351786074691e8eeee5b175David Gross    RD->removeDecl(info.second);
458352e62d65caa48251d9c69cc8b5a82ddfea6b014I-Jui (Ray) Sung    info.second->setLexicalDeclContext(RDForLayout);
4593a6750f246eed4168351786074691e8eeee5b175David Gross    RDForLayout->addDecl(info.second);
4603a6750f246eed4168351786074691e8eeee5b175David Gross  }
4613a6750f246eed4168351786074691e8eeee5b175David Gross
4623a6750f246eed4168351786074691e8eeee5b175David Gross  const clang::ASTRecordLayout& RL = ASTC.getASTRecordLayout(RDForLayout);
4633a6750f246eed4168351786074691e8eeee5b175David Gross
4643a6750f246eed4168351786074691e8eeee5b175David Gross  // An exportable type cannot contain a bitfield.  However, it's
4653a6750f246eed4168351786074691e8eeee5b175David Gross  // possible that this current type might have a bitfield and yet
4663a6750f246eed4168351786074691e8eeee5b175David Gross  // share a common initial sequence with an exportable type, so even
4673a6750f246eed4168351786074691e8eeee5b175David Gross  // if the current type has a bitfield, the current type still
4683a6750f246eed4168351786074691e8eeee5b175David Gross  // needs to have explicit padding inserted (in case the two types
4693a6750f246eed4168351786074691e8eeee5b175David Gross  // under discussion are members of a union).  We don't need to
4703a6750f246eed4168351786074691e8eeee5b175David Gross  // insert any padding after the bitfield, however, because that
4713a6750f246eed4168351786074691e8eeee5b175David Gross  // would be beyond the common initial sequence.
4723a6750f246eed4168351786074691e8eeee5b175David Gross  bool foundBitField = false;
4733a6750f246eed4168351786074691e8eeee5b175David Gross
4743a6750f246eed4168351786074691e8eeee5b175David Gross  // Is there any padding in this struct?
4753a6750f246eed4168351786074691e8eeee5b175David Gross  bool foundPadding = false;
4763a6750f246eed4168351786074691e8eeee5b175David Gross
4773a6750f246eed4168351786074691e8eeee5b175David Gross  unsigned fieldNo = 0;
4783a6750f246eed4168351786074691e8eeee5b175David Gross  uint64_t fieldPrePaddingOffset = 0;  // byte offset of pre-field padding within struct
4793a6750f246eed4168351786074691e8eeee5b175David Gross  for (auto &info : FieldsInfo) {
4803a6750f246eed4168351786074691e8eeee5b175David Gross    const clang::FieldDecl* FD = info.second;
4813a6750f246eed4168351786074691e8eeee5b175David Gross
4823a6750f246eed4168351786074691e8eeee5b175David Gross    if ((foundBitField = FD->isBitField()))
4833a6750f246eed4168351786074691e8eeee5b175David Gross      break;
4843a6750f246eed4168351786074691e8eeee5b175David Gross
4853a6750f246eed4168351786074691e8eeee5b175David Gross    const uint64_t fieldOffset = RL.getFieldOffset(fieldNo) >> 3;
4863a6750f246eed4168351786074691e8eeee5b175David Gross    const size_t prePadding = fieldOffset - fieldPrePaddingOffset;
4873a6750f246eed4168351786074691e8eeee5b175David Gross    foundPadding |= (prePadding != 0);
4883a6750f246eed4168351786074691e8eeee5b175David Gross    info.first = prePadding;
4893a6750f246eed4168351786074691e8eeee5b175David Gross
4903a6750f246eed4168351786074691e8eeee5b175David Gross    // get ready for the next field
4913a6750f246eed4168351786074691e8eeee5b175David Gross    //
4923a6750f246eed4168351786074691e8eeee5b175David Gross    //   assumes that getTypeSize() is the storage size of the Type -- for example,
4933a6750f246eed4168351786074691e8eeee5b175David Gross    //   that it includes a struct's tail padding (if any)
4943a6750f246eed4168351786074691e8eeee5b175David Gross    //
4953a6750f246eed4168351786074691e8eeee5b175David Gross    fieldPrePaddingOffset = fieldOffset + (ASTC.getTypeSize(FD->getType()) >> 3);
4963a6750f246eed4168351786074691e8eeee5b175David Gross    ++fieldNo;
4973a6750f246eed4168351786074691e8eeee5b175David Gross  }
4983a6750f246eed4168351786074691e8eeee5b175David Gross
4993a6750f246eed4168351786074691e8eeee5b175David Gross  if (!foundBitField) {
5003a6750f246eed4168351786074691e8eeee5b175David Gross    // In order to ensure that the front end (including reflected
5013a6750f246eed4168351786074691e8eeee5b175David Gross    // code) and back end agree on struct size (not just field
5023a6750f246eed4168351786074691e8eeee5b175David Gross    // offsets) we may need to add explicit tail padding, just as we'e
5033a6750f246eed4168351786074691e8eeee5b175David Gross    // added explicit padding between fields.
5043a6750f246eed4168351786074691e8eeee5b175David Gross    slangAssert(RL.getSize().getQuantity() >= fieldPrePaddingOffset);
5053a6750f246eed4168351786074691e8eeee5b175David Gross    if (const size_t tailPadding = RL.getSize().getQuantity() - fieldPrePaddingOffset) {
5063a6750f246eed4168351786074691e8eeee5b175David Gross      foundPadding = true;
5073a6750f246eed4168351786074691e8eeee5b175David Gross      FieldsInfo.push_back(std::make_pair(tailPadding, nullptr));
5083a6750f246eed4168351786074691e8eeee5b175David Gross    }
5093a6750f246eed4168351786074691e8eeee5b175David Gross  }
5103a6750f246eed4168351786074691e8eeee5b175David Gross
5113a6750f246eed4168351786074691e8eeee5b175David Gross  if (false /* change to "true" for extra debugging output */) {
5123a6750f246eed4168351786074691e8eeee5b175David Gross   if (foundPadding) {
5133a6750f246eed4168351786074691e8eeee5b175David Gross     std::cout << "PadStruct(" << RD->getNameAsString() << "):" << std::endl;
5143a6750f246eed4168351786074691e8eeee5b175David Gross     for (const auto &info : FieldsInfo)
5153a6750f246eed4168351786074691e8eeee5b175David Gross       std::cout << "  " << info.first << ", " << (info.second ? info.second->getNameAsString() : "<tail>") << std::endl;
5163a6750f246eed4168351786074691e8eeee5b175David Gross   }
5173a6750f246eed4168351786074691e8eeee5b175David Gross  }
5183a6750f246eed4168351786074691e8eeee5b175David Gross
5193a6750f246eed4168351786074691e8eeee5b175David Gross  if (foundPadding && Slang::IsLocInRSHeaderFile(RD->getLocation(), mSourceMgr)) {
5203a6750f246eed4168351786074691e8eeee5b175David Gross    mContext->ReportError(RD->getLocation(), "system structure contains padding: '%0'")
5213a6750f246eed4168351786074691e8eeee5b175David Gross        << RD->getName();
5223a6750f246eed4168351786074691e8eeee5b175David Gross  }
5233a6750f246eed4168351786074691e8eeee5b175David Gross
5243a6750f246eed4168351786074691e8eeee5b175David Gross  // now move fields from RDForLayout to RD, and add any necessary
5253a6750f246eed4168351786074691e8eeee5b175David Gross  // padding fields
5263a6750f246eed4168351786074691e8eeee5b175David Gross  const clang::QualType byteType = ASTC.getIntTypeForBitwidth(8, false /* not signed */);
5273a6750f246eed4168351786074691e8eeee5b175David Gross  clang::IdentifierInfo* const paddingIdentifierInfo = &ASTC.Idents.get(RS_PADDING_FIELD_NAME);
5283a6750f246eed4168351786074691e8eeee5b175David Gross  for (const auto &info : FieldsInfo) {
5293a6750f246eed4168351786074691e8eeee5b175David Gross    if (info.first != 0) {
5303a6750f246eed4168351786074691e8eeee5b175David Gross      // Create a padding field: "char <RS_PADDING_FIELD_NAME>[<info.first>];"
5313a6750f246eed4168351786074691e8eeee5b175David Gross
5323a6750f246eed4168351786074691e8eeee5b175David Gross      // TODO: Do we need to do anything else to keep this field from being shown in debugger?
5333a6750f246eed4168351786074691e8eeee5b175David Gross      //       There's no source location, and the field is marked as implicit.
5343a6750f246eed4168351786074691e8eeee5b175David Gross      const clang::QualType paddingType =
5353a6750f246eed4168351786074691e8eeee5b175David Gross          ASTC.getConstantArrayType(byteType,
5363a6750f246eed4168351786074691e8eeee5b175David Gross                                    llvm::APInt(sizeof(info.first) << 3, info.first),
5373a6750f246eed4168351786074691e8eeee5b175David Gross                                    clang::ArrayType::Normal, 0 /* IndexTypeQuals */);
5383a6750f246eed4168351786074691e8eeee5b175David Gross      clang::FieldDecl* const FD =
5393a6750f246eed4168351786074691e8eeee5b175David Gross          clang::FieldDecl::Create(ASTC, RD, clang::SourceLocation(), clang::SourceLocation(),
5403a6750f246eed4168351786074691e8eeee5b175David Gross                                   paddingIdentifierInfo,
5413a6750f246eed4168351786074691e8eeee5b175David Gross                                   paddingType,
5423a6750f246eed4168351786074691e8eeee5b175David Gross                                   nullptr,  // TypeSourceInfo*
5433a6750f246eed4168351786074691e8eeee5b175David Gross                                   nullptr,  // BW (bitwidth)
5443a6750f246eed4168351786074691e8eeee5b175David Gross                                   false,    // Mutable = false
5453a6750f246eed4168351786074691e8eeee5b175David Gross                                   clang::ICIS_NoInit);
5463a6750f246eed4168351786074691e8eeee5b175David Gross      FD->setImplicit(true);
5473a6750f246eed4168351786074691e8eeee5b175David Gross      RD->addDecl(FD);
5483a6750f246eed4168351786074691e8eeee5b175David Gross    }
5493a6750f246eed4168351786074691e8eeee5b175David Gross    if (info.second != nullptr) {
5503a6750f246eed4168351786074691e8eeee5b175David Gross      RDForLayout->removeDecl(info.second);
551352e62d65caa48251d9c69cc8b5a82ddfea6b014I-Jui (Ray) Sung      info.second->setLexicalDeclContext(RD);
5523a6750f246eed4168351786074691e8eeee5b175David Gross      RD->addDecl(info.second);
5533a6750f246eed4168351786074691e8eeee5b175David Gross    }
5543a6750f246eed4168351786074691e8eeee5b175David Gross  }
5553a6750f246eed4168351786074691e8eeee5b175David Gross
5563a6750f246eed4168351786074691e8eeee5b175David Gross  // There does not appear to be any safe way to delete a RecordDecl
5573a6750f246eed4168351786074691e8eeee5b175David Gross  // -- for example, there is no RecordDecl destructor to invalidate
5583a6750f246eed4168351786074691e8eeee5b175David Gross  // cached record layout, and if we were to get unlucky, some future
5593a6750f246eed4168351786074691e8eeee5b175David Gross  // RecordDecl could be allocated in the same place as a deleted
5603a6750f246eed4168351786074691e8eeee5b175David Gross  // RDForLayout and "inherit" the cached record layout from
5613a6750f246eed4168351786074691e8eeee5b175David Gross  // RDForLayout.
5623a6750f246eed4168351786074691e8eeee5b175David Gross}
5633a6750f246eed4168351786074691e8eeee5b175David Gross
5649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
5653a6750f246eed4168351786074691e8eeee5b175David Gross  // we want to insert explicit padding fields into structs per http://b/29154200 and http://b/28070272
5663a6750f246eed4168351786074691e8eeee5b175David Gross  switch (D->getTagKind()) {
5673a6750f246eed4168351786074691e8eeee5b175David Gross    case clang::TTK_Struct:
5683a6750f246eed4168351786074691e8eeee5b175David Gross      PadStruct(llvm::cast<clang::RecordDecl>(D));
5693a6750f246eed4168351786074691e8eeee5b175David Gross      break;
5703a6750f246eed4168351786074691e8eeee5b175David Gross
5713a6750f246eed4168351786074691e8eeee5b175David Gross    case clang::TTK_Union:
5723a6750f246eed4168351786074691e8eeee5b175David Gross      // cannot be part of an exported type
5733a6750f246eed4168351786074691e8eeee5b175David Gross      break;
5743a6750f246eed4168351786074691e8eeee5b175David Gross
5753a6750f246eed4168351786074691e8eeee5b175David Gross    case clang::TTK_Enum:
5763a6750f246eed4168351786074691e8eeee5b175David Gross      // a scalar
5773a6750f246eed4168351786074691e8eeee5b175David Gross      break;
5783a6750f246eed4168351786074691e8eeee5b175David Gross
5793a6750f246eed4168351786074691e8eeee5b175David Gross    case clang::TTK_Class:
5803a6750f246eed4168351786074691e8eeee5b175David Gross    case clang::TTK_Interface:
5813a6750f246eed4168351786074691e8eeee5b175David Gross    default:
5823a6750f246eed4168351786074691e8eeee5b175David Gross      slangAssert(false && "Unexpected TagTypeKind");
5833a6750f246eed4168351786074691e8eeee5b175David Gross      break;
5843a6750f246eed4168351786074691e8eeee5b175David Gross  }
5859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  mGen->HandleTagDeclDefinition(D);
586462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
587462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
5889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
5899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  mGen->CompleteTentativeDefinition(D);
590462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
591462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
592462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei LiaoBackend::~Backend() {
5939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mpModule;
5949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mGen;
5959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mPerFunctionPasses;
5969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mPerModulePasses;
5979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mCodeGenPasses;
598462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
599e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
6008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet// 1) Add zero initialization of local RS object types
6018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::AnnotateFunction(clang::FunctionDecl *FD) {
6028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (FD &&
6038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      FD->hasBody() &&
604c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung      !FD->isImplicit() &&
6058024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
6068024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mRefCount.Init();
607283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    mRefCount.SetDeclContext(FD);
608579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    mRefCount.HandleParamsAndLocals(FD);
6098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
6108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
6118024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
6128024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletbool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
6132615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  // Find and remember the types for rs_allocation and rs_script_call_t so
6142615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  // they can be used later for translating rsForEach() calls.
6152615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
6162615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni       (mContext->getAllocationType().isNull() ||
6172615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        mContext->getScriptCallType().isNull()) &&
6182615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni       I != E; I++) {
6192615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    if (clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I)) {
6202615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      clang::StringRef TypeName = TD->getName();
6212615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      if (TypeName.equals("rs_allocation")) {
62288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        mContext->setAllocationType(TD);
6232615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      } else if (TypeName.equals("rs_script_call_t")) {
6242615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        mContext->setScriptCallType(TD);
62588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      }
62688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    }
62788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  }
62888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
6298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // Disallow user-defined functions with prefix "rs"
6308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (!mAllowRSPrefix) {
6318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Iterate all function declarations in the program.
6328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
6338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet         I != E; I++) {
6348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
6358024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      if (FD == nullptr)
6368024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        continue;
6378024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      if (!FD->getName().startswith("rs"))  // Check prefix
6388024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        continue;
6398024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
6408024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mContext->ReportError(FD->getLocation(),
6418024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                              "invalid function name prefix, "
6428024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                              "\"rs\" is reserved: '%0'")
6438024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            << FD->getName();
6448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
6458024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
6468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
6478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
6488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
64965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (FD) {
6505e306b944425a952fe744f59d828538137a59375David Gross      // Handle forward reference from pragma (see
6515e306b944425a952fe744f59d828538137a59375David Gross      // RSReducePragmaHandler::HandlePragma for backward reference).
6525e306b944425a952fe744f59d828538137a59375David Gross      mContext->markUsedByReducePragma(FD, RSContext::CheckNameYes);
65365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (FD->isGlobal()) {
65465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        // Check that we don't have any array parameters being misinterpreted as
65565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        // kernel pointers due to the C type system's array to pointer decay.
65665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        size_t numParams = FD->getNumParams();
65765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        for (size_t i = 0; i < numParams; i++) {
65865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross          const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
65965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross          clang::QualType QT = PVD->getOriginalType();
66065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross          if (QT->isArrayType()) {
66165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross            mContext->ReportError(
66265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross                PVD->getTypeSpecStartLoc(),
66365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross                "exported function parameters may not have array type: %0")
66465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross                << QT;
66565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross          }
6668024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
66765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        AnnotateFunction(FD);
6688024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
6698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
670fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
67140bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    if (getTargetAPI() >= SLANG_FEATURE_SINGLE_SOURCE_API) {
672c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung      if (FD && FD->hasBody() && !FD->isImplicit() &&
6739319dfc974a82794d46e9f474f316590f480b976Yang Ni          !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
674b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar        if (FD->hasAttr<clang::RenderScriptKernelAttr>()) {
67540bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni          // Log functions with attribute "kernel" by their names, and assign
67640bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni          // them slot numbers. Any other function cannot be used in a
67740bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni          // rsForEach() or rsForEachWithOptions() call, including old-style
67840bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni          // kernel functions which are defined without the "kernel" attribute.
6799319dfc974a82794d46e9f474f316590f480b976Yang Ni          mContext->addForEach(FD);
6801946749cebf4a64341d8210890688fef7d958c22Yang Ni        }
6811946749cebf4a64341d8210890688fef7d958c22Yang Ni        // Look for any kernel launch calls and translate them into using the
6821946749cebf4a64341d8210890688fef7d958c22Yang Ni        // internal API.
68340bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni        // Report a compiler error on kernel launches inside a kernel.
6849319dfc974a82794d46e9f474f316590f480b976Yang Ni        mForEachHandler.handleForEachCalls(FD, getTargetAPI());
685fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      }
686fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
6878024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
688fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
6898024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  return mGen->HandleTopLevelDecl(D);
6908024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
6918024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
6928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
6938024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
6948024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
6955e306b944425a952fe744f59d828538137a59375David Gross  if (!mContext->processReducePragmas(this))
69665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    return;
69765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
6988024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // If we have an invalid RS/FS AST, don't check further.
6998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (!mASTChecker.Validate()) {
7008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    return;
7018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mIsFilterscript) {
7048024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mContext->addPragma("rs_fp_relaxed", "");
7058024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7068024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7078024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  int version = mContext->getVersion();
7088024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (version == 0) {
7098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Not setting a version is an error
7108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mDiagEngine.Report(
7118024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
7128024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mDiagEngine.getCustomDiagID(
7138024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            clang::DiagnosticsEngine::Error,
7148024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            "missing pragma for version in source file"));
7158024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  } else {
7168024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    slangAssert(version == 1);
7178024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7188024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7198024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mContext->getReflectJavaPackageName().empty()) {
7208024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mDiagEngine.Report(
7218024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
7228024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
7238024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                    "missing \"#pragma rs "
7248024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                    "java_package_name(com.foo.bar)\" "
7258024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                    "in source file"));
7268024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    return;
7278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7288024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // Create a static global destructor if necessary (to handle RS object
7308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // runtime cleanup).
7318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
7328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (FD) {
7338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    HandleTopLevelDecl(clang::DeclGroupRef(FD));
7348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7358024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7368024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // Process any static function declarations
7378024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
7388024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          E = TUDecl->decls_end(); I != E; I++) {
7398024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if ((I->getKind() >= clang::Decl::firstFunction) &&
7408024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        (I->getKind() <= clang::Decl::lastFunction)) {
7418024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
7428024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      if (FD && !FD->isGlobal()) {
7438024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        AnnotateFunction(FD);
7448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
7458024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
7468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
7478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
7488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet///////////////////////////////////////////////////////////////////////////////
7508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::dumpExportVarInfo(llvm::Module *M) {
7518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  int slotCount = 0;
7528024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mExportVarMetadata == nullptr)
7538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
7548024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7558024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
7568024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7578024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // We emit slot information (#rs_object_slots) for any reference counted
7588024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  // RS type or pointer (which can also be bound).
7598024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7608024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
7618024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          E = mContext->export_vars_end();
7628024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I != E;
7638024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I++) {
7648024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    const RSExportVar *EV = *I;
7658024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    const RSExportType *ET = EV->getType();
7668024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    bool countsAsRSObject = false;
7678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7688024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Variable name
7698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportVarInfo.push_back(
7708024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
7718024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
7728024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Type name
7738024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    switch (ET->getClass()) {
7748024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassPrimitive: {
7758024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        const RSExportPrimitiveType *PT =
7768024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            static_cast<const RSExportPrimitiveType*>(ET);
7778024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        ExportVarInfo.push_back(
7788024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDString::get(
779b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar              mLLVMContext, llvm::utostr(PT->getType())));
7808024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        if (PT->isRSObjectType()) {
7818024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          countsAsRSObject = true;
7828024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
7838024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        break;
7848024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
7858024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassPointer: {
7868024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        ExportVarInfo.push_back(
7878024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDString::get(
7888024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
7898024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                ->getPointeeType()->getName()).c_str()));
7908024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        break;
7918024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
7928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassMatrix: {
7938024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        ExportVarInfo.push_back(
7948024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDString::get(
795b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar              mLLVMContext, llvm::utostr(
7968024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  /* TODO Strange value.  This pushes just a number, quite
7978024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   * different than the other cases.  What is this used for?
7988024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   * These are the metadata values that some partner drivers
7998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   * want to reference (for TBAA, etc.). We may want to look
8008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   * at whether these provide any reasonable value (or have
8018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   * distinct enough values to actually depend on).
8028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   */
8038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                DataTypeRSMatrix2x2 +
8048024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
8058024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        break;
8068024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
8078024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassVector:
8088024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassConstantArray:
8098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      case RSExportType::ExportClassRecord: {
8108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        ExportVarInfo.push_back(
8118024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDString::get(mLLVMContext,
8128024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              EV->getType()->getName().c_str()));
8138024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        break;
8148024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
8158024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
8168024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8178024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportVarMetadata->addOperand(
8188024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDNode::get(mLLVMContext, ExportVarInfo));
8198024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportVarInfo.clear();
8208024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8218024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if (mRSObjectSlotsMetadata == nullptr) {
8228024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mRSObjectSlotsMetadata =
8238024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
8248024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
8258024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8268024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if (countsAsRSObject) {
8278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
828b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar          llvm::MDString::get(mLLVMContext, llvm::utostr(slotCount))));
8298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
8308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    slotCount++;
8328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
8338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
8348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8353a6750f246eed4168351786074691e8eeee5b175David Gross// A similar algorithm is present in Backend::PadStruct().
8363a6750f246eed4168351786074691e8eeee5b175David Grossstatic void PadHelperFunctionStruct(llvm::Module *M,
8373a6750f246eed4168351786074691e8eeee5b175David Gross                                    llvm::StructType **paddedStructType,
8383a6750f246eed4168351786074691e8eeee5b175David Gross                                    std::vector<unsigned> *origFieldNumToPaddedFieldNum,
8393a6750f246eed4168351786074691e8eeee5b175David Gross                                    llvm::StructType *origStructType) {
8403a6750f246eed4168351786074691e8eeee5b175David Gross  slangAssert(origFieldNumToPaddedFieldNum->empty());
8413a6750f246eed4168351786074691e8eeee5b175David Gross  origFieldNumToPaddedFieldNum->resize(2 * origStructType->getNumElements());
8423a6750f246eed4168351786074691e8eeee5b175David Gross
8433a6750f246eed4168351786074691e8eeee5b175David Gross  llvm::LLVMContext &llvmContext = M->getContext();
8443a6750f246eed4168351786074691e8eeee5b175David Gross
8453a6750f246eed4168351786074691e8eeee5b175David Gross  const llvm::DataLayout *DL = &M->getDataLayout();
8463a6750f246eed4168351786074691e8eeee5b175David Gross  const llvm::StructLayout *SL = DL->getStructLayout(origStructType);
8473a6750f246eed4168351786074691e8eeee5b175David Gross
8483a6750f246eed4168351786074691e8eeee5b175David Gross  // Field types -- including any padding fields we need to insert.
8493a6750f246eed4168351786074691e8eeee5b175David Gross  std::vector<llvm::Type *> paddedFieldTypes;
8503a6750f246eed4168351786074691e8eeee5b175David Gross  paddedFieldTypes.reserve(2 * origStructType->getNumElements());
8513a6750f246eed4168351786074691e8eeee5b175David Gross
8523a6750f246eed4168351786074691e8eeee5b175David Gross  // Is there any padding in this struct?
8533a6750f246eed4168351786074691e8eeee5b175David Gross  bool foundPadding = false;
8543a6750f246eed4168351786074691e8eeee5b175David Gross
8553a6750f246eed4168351786074691e8eeee5b175David Gross  llvm::Type *const byteType = llvm::Type::getInt8Ty(llvmContext);
8563a6750f246eed4168351786074691e8eeee5b175David Gross  unsigned origFieldNum = 0, paddedFieldNum = 0;
8573a6750f246eed4168351786074691e8eeee5b175David Gross  uint64_t fieldPrePaddingOffset = 0;  // byte offset of pre-field padding within struct
8583a6750f246eed4168351786074691e8eeee5b175David Gross  for (llvm::Type *fieldType : origStructType->elements()) {
8593a6750f246eed4168351786074691e8eeee5b175David Gross    const uint64_t fieldOffset = SL->getElementOffset(origFieldNum);
8603a6750f246eed4168351786074691e8eeee5b175David Gross    const size_t prePadding = fieldOffset - fieldPrePaddingOffset;
8613a6750f246eed4168351786074691e8eeee5b175David Gross    if (prePadding != 0) {
8623a6750f246eed4168351786074691e8eeee5b175David Gross      foundPadding = true;
8633a6750f246eed4168351786074691e8eeee5b175David Gross      paddedFieldTypes.push_back(llvm::ArrayType::get(byteType, prePadding));
8643a6750f246eed4168351786074691e8eeee5b175David Gross      ++paddedFieldNum;
8653a6750f246eed4168351786074691e8eeee5b175David Gross    }
8663a6750f246eed4168351786074691e8eeee5b175David Gross    paddedFieldTypes.push_back(fieldType);
8673a6750f246eed4168351786074691e8eeee5b175David Gross    (*origFieldNumToPaddedFieldNum)[origFieldNum] = paddedFieldNum;
8683a6750f246eed4168351786074691e8eeee5b175David Gross
8693a6750f246eed4168351786074691e8eeee5b175David Gross    // get ready for the next field
8703a6750f246eed4168351786074691e8eeee5b175David Gross    fieldPrePaddingOffset = fieldOffset + DL->getTypeAllocSize(fieldType);
8713a6750f246eed4168351786074691e8eeee5b175David Gross    ++origFieldNum;
8723a6750f246eed4168351786074691e8eeee5b175David Gross    ++paddedFieldNum;
8733a6750f246eed4168351786074691e8eeee5b175David Gross  }
8743a6750f246eed4168351786074691e8eeee5b175David Gross
8753a6750f246eed4168351786074691e8eeee5b175David Gross  // In order to ensure that the front end (including reflected code)
8763a6750f246eed4168351786074691e8eeee5b175David Gross  // and back end agree on struct size (not just field offsets) we may
8773a6750f246eed4168351786074691e8eeee5b175David Gross  // need to add explicit tail padding, just as we'e added explicit
8783a6750f246eed4168351786074691e8eeee5b175David Gross  // padding between fields.
8793a6750f246eed4168351786074691e8eeee5b175David Gross  slangAssert(SL->getSizeInBytes() >= fieldPrePaddingOffset);
8803a6750f246eed4168351786074691e8eeee5b175David Gross  if (const size_t tailPadding = SL->getSizeInBytes() - fieldPrePaddingOffset) {
8813a6750f246eed4168351786074691e8eeee5b175David Gross    foundPadding = true;
8823a6750f246eed4168351786074691e8eeee5b175David Gross    paddedFieldTypes.push_back(llvm::ArrayType::get(byteType, tailPadding));
8833a6750f246eed4168351786074691e8eeee5b175David Gross  }
8843a6750f246eed4168351786074691e8eeee5b175David Gross
8853a6750f246eed4168351786074691e8eeee5b175David Gross  *paddedStructType = (foundPadding
8863a6750f246eed4168351786074691e8eeee5b175David Gross                       ? llvm::StructType::get(llvmContext, paddedFieldTypes)
8873a6750f246eed4168351786074691e8eeee5b175David Gross                       : origStructType);
8883a6750f246eed4168351786074691e8eeee5b175David Gross}
8893a6750f246eed4168351786074691e8eeee5b175David Gross
8908024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::dumpExportFunctionInfo(llvm::Module *M) {
8918024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mExportFuncMetadata == nullptr)
8928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportFuncMetadata =
8938024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
8948024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8958024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
8968024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
8978024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (RSContext::const_export_func_iterator
8988024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          I = mContext->export_funcs_begin(),
8998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          E = mContext->export_funcs_end();
9008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I != E;
9018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I++) {
9028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    const RSExportFunc *EF = *I;
9038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9048024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Function name
9058024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if (!EF->hasParam()) {
9068024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
9078024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                                   EF->getName().c_str()));
9088024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    } else {
9098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      llvm::Function *F = M->getFunction(EF->getName());
9108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      llvm::Function *HelperFunction;
9118024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      const std::string HelperFunctionName(".helper_" + EF->getName());
9128024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9138024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      slangAssert(F && "Function marked as exported disappeared in Bitcode");
9148024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9158024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      // Create helper function
9168024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      {
9173a6750f246eed4168351786074691e8eeee5b175David Gross        llvm::StructType *OrigHelperFunctionParameterTy = nullptr;
9183a6750f246eed4168351786074691e8eeee5b175David Gross        llvm::StructType *PaddedHelperFunctionParameterTy = nullptr;
9193a6750f246eed4168351786074691e8eeee5b175David Gross
9203a6750f246eed4168351786074691e8eeee5b175David Gross        std::vector<unsigned> OrigFieldNumToPaddedFieldNum;
9218024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        std::vector<bool> isStructInput;
9228024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9238024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        if (!F->getArgumentList().empty()) {
9248024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          std::vector<llvm::Type*> HelperFunctionParameterTys;
9258024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          for (llvm::Function::arg_iterator AI = F->arg_begin(),
9268024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                   AE = F->arg_end(); AI != AE; AI++) {
9278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
9288024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
9298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  isStructInput.push_back(true);
9308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              } else {
9318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  HelperFunctionParameterTys.push_back(AI->getType());
9328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  isStructInput.push_back(false);
9338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              }
9348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          }
9353a6750f246eed4168351786074691e8eeee5b175David Gross          OrigHelperFunctionParameterTy =
9368024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
9373a6750f246eed4168351786074691e8eeee5b175David Gross          PadHelperFunctionStruct(M,
9383a6750f246eed4168351786074691e8eeee5b175David Gross                                  &PaddedHelperFunctionParameterTy, &OrigFieldNumToPaddedFieldNum,
9393a6750f246eed4168351786074691e8eeee5b175David Gross                                  OrigHelperFunctionParameterTy);
9408024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
9418024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9423a6750f246eed4168351786074691e8eeee5b175David Gross        if (!EF->checkParameterPacketType(OrigHelperFunctionParameterTy)) {
9438024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          fprintf(stderr, "Failed to export function %s: parameter type "
9448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                          "mismatch during creation of helper function.\n",
9458024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  EF->getName().c_str());
9468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          const RSExportRecordType *Expected = EF->getParamPacketType();
9488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          if (Expected) {
9498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            fprintf(stderr, "Expected:\n");
9508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            Expected->getLLVMType()->dump();
9518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          }
9523a6750f246eed4168351786074691e8eeee5b175David Gross          if (OrigHelperFunctionParameterTy) {
9538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            fprintf(stderr, "Got:\n");
9543a6750f246eed4168351786074691e8eeee5b175David Gross            OrigHelperFunctionParameterTy->dump();
9558024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          }
9568024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
9578024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9588024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        std::vector<llvm::Type*> Params;
9593a6750f246eed4168351786074691e8eeee5b175David Gross        if (PaddedHelperFunctionParameterTy) {
9608024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::PointerType *HelperFunctionParameterTyP =
9613a6750f246eed4168351786074691e8eeee5b175David Gross              llvm::PointerType::getUnqual(PaddedHelperFunctionParameterTy);
9628024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          Params.push_back(HelperFunctionParameterTyP);
9638024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
9648024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9658024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::FunctionType * HelperFunctionType =
9668024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::FunctionType::get(F->getReturnType(),
9678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                    Params,
9688024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                    /* IsVarArgs = */false);
9698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9708024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        HelperFunction =
9718024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::Function::Create(HelperFunctionType,
9728024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                   llvm::GlobalValue::ExternalLinkage,
9738024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                   HelperFunctionName,
9748024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                   M);
9758024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9768024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        HelperFunction->addFnAttr(llvm::Attribute::NoInline);
9778024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        HelperFunction->setCallingConv(F->getCallingConv());
9788024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9798024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        // Create helper function body
9808024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        {
9818024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::Argument *HelperFunctionParameter =
9828024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              &(*HelperFunction->arg_begin());
9838024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::BasicBlock *BB =
9848024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
9858024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
9868024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::SmallVector<llvm::Value*, 6> Params;
9878024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::Value *Idx[2];
9888024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9898024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          Idx[0] =
9908024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
9918024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          // getelementptr and load instruction for all elements in
9938024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          // parameter .p
9943a6750f246eed4168351786074691e8eeee5b175David Gross          for (size_t origFieldNum = 0; origFieldNum < EF->getNumParameters(); origFieldNum++) {
9958024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            // getelementptr
9968024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            Idx[1] = llvm::ConstantInt::get(
9973a6750f246eed4168351786074691e8eeee5b175David Gross              llvm::Type::getInt32Ty(mLLVMContext), OrigFieldNumToPaddedFieldNum[origFieldNum]);
9988024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
9998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::Value *Ptr = NULL;
10008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
10028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            // Load is only required for non-struct ptrs
10043a6750f246eed4168351786074691e8eeee5b175David Gross            if (isStructInput[origFieldNum]) {
10058024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                Params.push_back(Ptr);
10068024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            } else {
10078024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                llvm::Value *V = IB->CreateLoad(Ptr);
10088024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                Params.push_back(V);
10098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            }
10108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          }
10118024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10128024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          // Call and pass the all elements as parameter to F
10138024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::CallInst *CI = IB->CreateCall(F, Params);
10148024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10158024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          CI->setCallingConv(F->getCallingConv());
10168024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
1017fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni          if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
10188024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            IB->CreateRetVoid();
1019fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni          } else {
10208024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            IB->CreateRet(CI);
1021fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni          }
10228024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10238024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          delete IB;
10248024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        }
10258024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
10268024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      ExportFuncInfo.push_back(
10288024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
10298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }
10308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportFuncMetadata->addOperand(
10328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
10338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportFuncInfo.clear();
10348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
10358024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
10368024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10378024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::dumpExportForEachInfo(llvm::Module *M) {
10388024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mExportForEachNameMetadata == nullptr) {
10398024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportForEachNameMetadata =
10408024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
10418024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
10428024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mExportForEachSignatureMetadata == nullptr) {
10438024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportForEachSignatureMetadata =
10448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
10458024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
10468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
10488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
10498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (RSContext::const_export_foreach_iterator
10518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          I = mContext->export_foreach_begin(),
10528024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          E = mContext->export_foreach_end();
10538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I != E;
10548024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I++) {
10558024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    const RSExportForEach *EFE = *I;
10568024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10578024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportForEachName.push_back(
10588024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
10598024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10608024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportForEachNameMetadata->addOperand(
10618024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDNode::get(mLLVMContext, ExportForEachName));
10628024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportForEachName.clear();
10638024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10648024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportForEachInfo.push_back(
10658024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDString::get(mLLVMContext,
1066b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar                            llvm::utostr(EFE->getSignatureMetadata())));
10678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10688024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    mExportForEachSignatureMetadata->addOperand(
10698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
10708024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportForEachInfo.clear();
10718024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
10728024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
10738024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
10748ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Grossvoid Backend::dumpExportReduceInfo(llvm::Module *M) {
10758ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  if (!mExportReduceMetadata) {
10768ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    mExportReduceMetadata =
10778ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
107815e44e66adc350adb4fe0533a442092c64333ab5David Gross  }
107915e44e66adc350adb4fe0533a442092c64333ab5David Gross
10808ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  llvm::SmallVector<llvm::Metadata *, 6> ExportReduceInfo;
10818ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  // Add operand to ExportReduceInfo, padding out missing operands with
108215e44e66adc350adb4fe0533a442092c64333ab5David Gross  // nullptr.
10838ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  auto addOperand = [&ExportReduceInfo](uint32_t Idx, llvm::Metadata *N) {
10848ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    while (Idx > ExportReduceInfo.size())
10858ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      ExportReduceInfo.push_back(nullptr);
10868ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    ExportReduceInfo.push_back(N);
108715e44e66adc350adb4fe0533a442092c64333ab5David Gross  };
10888ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  // Add string operand to ExportReduceInfo, padding out missing operands
108915e44e66adc350adb4fe0533a442092c64333ab5David Gross  // with nullptr.
109015e44e66adc350adb4fe0533a442092c64333ab5David Gross  // If string is empty, then do not add it unless Always is true.
109115e44e66adc350adb4fe0533a442092c64333ab5David Gross  auto addString = [&addOperand, this](uint32_t Idx, const std::string &S,
109215e44e66adc350adb4fe0533a442092c64333ab5David Gross                                       bool Always = true) {
109315e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (Always || !S.empty())
109415e44e66adc350adb4fe0533a442092c64333ab5David Gross      addOperand(Idx, llvm::MDString::get(mLLVMContext, S));
109515e44e66adc350adb4fe0533a442092c64333ab5David Gross  };
109615e44e66adc350adb4fe0533a442092c64333ab5David Gross
109715e44e66adc350adb4fe0533a442092c64333ab5David Gross  // Add the description of the reduction kernels to the metadata node.
10988ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  for (auto I = mContext->export_reduce_begin(),
10998ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross            E = mContext->export_reduce_end();
110015e44e66adc350adb4fe0533a442092c64333ab5David Gross       I != E; ++I) {
11018ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    ExportReduceInfo.clear();
110215e44e66adc350adb4fe0533a442092c64333ab5David Gross
110365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    int Idx = 0;
110465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
110565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addString(Idx++, (*I)->getNameReduce());
110665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
1107b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar    addOperand(Idx++, llvm::MDString::get(mLLVMContext, llvm::utostr((*I)->getAccumulatorTypeSize())));
110815e44e66adc350adb4fe0533a442092c64333ab5David Gross
110915e44e66adc350adb4fe0533a442092c64333ab5David Gross    llvm::SmallVector<llvm::Metadata *, 2> Accumulator;
111015e44e66adc350adb4fe0533a442092c64333ab5David Gross    Accumulator.push_back(
111115e44e66adc350adb4fe0533a442092c64333ab5David Gross      llvm::MDString::get(mLLVMContext, (*I)->getNameAccumulator()));
111215e44e66adc350adb4fe0533a442092c64333ab5David Gross    Accumulator.push_back(llvm::MDString::get(
111315e44e66adc350adb4fe0533a442092c64333ab5David Gross      mLLVMContext,
1114b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar      llvm::utostr((*I)->getAccumulatorSignatureMetadata())));
111565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addOperand(Idx++, llvm::MDTuple::get(mLLVMContext, Accumulator));
111615e44e66adc350adb4fe0533a442092c64333ab5David Gross
111765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addString(Idx++, (*I)->getNameInitializer(), false);
111865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addString(Idx++, (*I)->getNameCombiner(), false);
111965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addString(Idx++, (*I)->getNameOutConverter(), false);
112065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    addString(Idx++, (*I)->getNameHalter(), false);
112115e44e66adc350adb4fe0533a442092c64333ab5David Gross
11228ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    mExportReduceMetadata->addOperand(
11238ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      llvm::MDTuple::get(mLLVMContext, ExportReduceInfo));
112415e44e66adc350adb4fe0533a442092c64333ab5David Gross  }
112515e44e66adc350adb4fe0533a442092c64333ab5David Gross}
112615e44e66adc350adb4fe0533a442092c64333ab5David Gross
11278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::dumpExportTypeInfo(llvm::Module *M) {
11288024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
11298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  for (RSContext::const_export_type_iterator
11318024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          I = mContext->export_types_begin(),
11328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          E = mContext->export_types_end();
11338024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I != E;
11348024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet       I++) {
11358024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // First, dump type name list to export
11368024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    const RSExportType *ET = I->getValue();
11378024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11388024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportTypeInfo.clear();
11398024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    // Type name
11408024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    ExportTypeInfo.push_back(
11418024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
11428024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11438024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if (ET->getClass() == RSExportType::ExportClassRecord) {
11448024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      const RSExportRecordType *ERT =
11458024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          static_cast<const RSExportRecordType*>(ET);
11468024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      if (mExportTypeMetadata == nullptr)
11488024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        mExportTypeMetadata =
11498024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
11508024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11518024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      mExportTypeMetadata->addOperand(
11528024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
11538024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11548024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      // Now, export struct field information to %[struct name]
11558024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      std::string StructInfoMetadataName("%");
11568024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      StructInfoMetadataName.append(ET->getName());
11578024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      llvm::NamedMDNode *StructInfoMetadata =
11588024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet          M->getOrInsertNamedMetadata(StructInfoMetadataName);
11598024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
11608024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11618024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
11628024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                  "Metadata with same name was created before");
11638024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
11648024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet              FE = ERT->fields_end();
11658024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet           FI != FE;
11668024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet           FI++) {
11678024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        const RSExportRecordType::Field *F = *FI;
11688024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11698024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        // 1. field name
11708024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
11718024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                                F->getName().c_str()));
11728024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11738024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        // 2. field type name
11748024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        FieldInfo.push_back(
11758024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDString::get(mLLVMContext,
11768024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet                                F->getType()->getName().c_str()));
11778024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11788024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        StructInfoMetadata->addOperand(
11798024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet            llvm::MDNode::get(mLLVMContext, FieldInfo));
11808024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet        FieldInfo.clear();
11818024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      }
11828024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    }   // ET->getClass() == RSExportType::ExportClassRecord
11838024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
11848024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
11858024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11868024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouilletvoid Backend::HandleTranslationUnitPost(llvm::Module *M) {
11878024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11888024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (!mContext->is64Bit()) {
11898024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
11908024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  }
11918024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
119265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  if (!mContext->processExports())
11938024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    return;
11948024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11958024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mContext->hasExportVar())
11968024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    dumpExportVarInfo(M);
11978024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
11988024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mContext->hasExportFunc())
11998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    dumpExportFunctionInfo(M);
12008024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
12018024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mContext->hasExportForEach())
12028024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    dumpExportForEachInfo(M);
12038024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
12048ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  if (mContext->hasExportReduce())
12058ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    dumpExportReduceInfo(M);
120615e44e66adc350adb4fe0533a442092c64333ab5David Gross
12078024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (mContext->hasExportType())
12088024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    dumpExportTypeInfo(M);
12098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet}
12108024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet
1211e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1212