brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · 88a7e85 Raw
137 lines · cpp
1//===--- CIRGenAsm.cpp - Inline Assembly Support for CIR CodeGen ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains code to emit inline assembly.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenFunction.h"14#include "clang/CIR/MissingFeatures.h"15 16using namespace clang;17using namespace clang::CIRGen;18using namespace cir;19 20static AsmFlavor inferFlavor(const CIRGenModule &cgm, const AsmStmt &s) {21  AsmFlavor gnuAsmFlavor =22      cgm.getCodeGenOpts().getInlineAsmDialect() == CodeGenOptions::IAD_ATT23          ? AsmFlavor::x86_att24          : AsmFlavor::x86_intel;25 26  return isa<MSAsmStmt>(&s) ? AsmFlavor::x86_intel : gnuAsmFlavor;27}28 29static void collectClobbers(const CIRGenFunction &cgf, const AsmStmt &s,30                            std::string &constraints, bool &hasUnwindClobber,31                            bool &readOnly, bool readNone) {32 33  hasUnwindClobber = false;34  const CIRGenModule &cgm = cgf.getCIRGenModule();35 36  // Clobbers37  for (unsigned i = 0, e = s.getNumClobbers(); i != e; i++) {38    std::string clobber = s.getClobber(i);39    if (clobber == "memory") {40      readOnly = readNone = false;41    } else if (clobber == "unwind") {42      hasUnwindClobber = true;43      continue;44    } else if (clobber != "cc") {45      clobber = cgf.getTarget().getNormalizedGCCRegisterName(clobber);46      if (cgm.getCodeGenOpts().StackClashProtector &&47          cgf.getTarget().isSPRegName(clobber))48        cgm.getDiags().Report(s.getAsmLoc(),49                              diag::warn_stack_clash_protection_inline_asm);50    }51 52    if (isa<MSAsmStmt>(&s)) {53      if (clobber == "eax" || clobber == "edx") {54        if (constraints.find("=&A") != std::string::npos)55          continue;56        std::string::size_type position1 =57            constraints.find("={" + clobber + "}");58        if (position1 != std::string::npos) {59          constraints.insert(position1 + 1, "&");60          continue;61        }62        std::string::size_type position2 = constraints.find("=A");63        if (position2 != std::string::npos) {64          constraints.insert(position2 + 1, "&");65          continue;66        }67      }68    }69    if (!constraints.empty())70      constraints += ',';71 72    constraints += "~{";73    constraints += clobber;74    constraints += '}';75  }76 77  // Add machine specific clobbers78  std::string_view machineClobbers = cgf.getTarget().getClobbers();79  if (!machineClobbers.empty()) {80    if (!constraints.empty())81      constraints += ',';82    constraints += machineClobbers;83  }84}85 86mlir::LogicalResult CIRGenFunction::emitAsmStmt(const AsmStmt &s) {87  // Assemble the final asm string.88  std::string asmString = s.generateAsmString(getContext());89 90  bool isGCCAsmGoto = false;91 92  std::string constraints;93  std::vector<mlir::Value> outArgs;94  std::vector<mlir::Value> inArgs;95  std::vector<mlir::Value> inOutArgs;96 97  // An inline asm can be marked readonly if it meets the following conditions:98  //  - it doesn't have any sideeffects99  //  - it doesn't clobber memory100  //  - it doesn't return a value by-reference101  // It can be marked readnone if it doesn't have any input memory constraints102  // in addition to meeting the conditions listed above.103  bool readOnly = true, readNone = true;104 105  if (s.getNumInputs() != 0 || s.getNumOutputs() != 0) {106    assert(!cir::MissingFeatures::asmInputOperands());107    assert(!cir::MissingFeatures::asmOutputOperands());108    cgm.errorNYI(s.getAsmLoc(), "asm with operands");109  }110 111  bool hasUnwindClobber = false;112  collectClobbers(*this, s, constraints, hasUnwindClobber, readOnly, readNone);113 114  std::array<mlir::ValueRange, 3> operands = {outArgs, inArgs, inOutArgs};115 116  mlir::Type resultType;117 118  bool hasSideEffect = s.isVolatile() || s.getNumOutputs() == 0;119 120  cir::InlineAsmOp ia = cir::InlineAsmOp::create(121      builder, getLoc(s.getAsmLoc()), resultType, operands, asmString,122      constraints, hasSideEffect, inferFlavor(cgm, s), mlir::ArrayAttr());123 124  if (isGCCAsmGoto) {125    assert(!cir::MissingFeatures::asmGoto());126  } else if (hasUnwindClobber) {127    assert(!cir::MissingFeatures::asmUnwindClobber());128  } else {129    assert(!cir::MissingFeatures::asmMemoryEffects());130  }131 132  llvm::SmallVector<mlir::Attribute> operandAttrs;133  ia.setOperandAttrsAttr(builder.getArrayAttr(operandAttrs));134 135  return mlir::success();136}137