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