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