LLVM: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

35#include

36using namespace llvm;

37

38#define DEBUG_TYPE "wasm"

39

40

41

42

43

45 "wasm-disable-explicit-locals", cl::Hidden,

46 cl::desc("WebAssembly: output implicit locals in"

47 " instruction output for test purposes only."),

49

51 "wasm-disable-fix-irreducible-control-flow-pass", cl::Hidden,

52 cl::desc("webassembly: disables the fix "

53 " irreducible control flow optimization pass"),

55

57

62

63

93}

94

95

96

97

98

101 if (!RM) {

102

103

104

106 }

107

108 return *RM;

109}

110

111

112

116 std::optionalCodeModel::Model CM, CodeGenOptLevel OL, bool JIT)

118 T,

119 TT.isArch64Bit()

120 ? (TT.isOSEmscripten() ? "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"

121 "i128:128-f128:64-n32:64-S128-ni:1:10:20"

122 : "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"

123 "i128:128-n32:64-S128-ni:1:10:20")

124 : (TT.isOSEmscripten() ? "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"

125 "i128:128-f128:64-n32:64-S128-ni:1:10:20"

126 : "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"

127 "i128:128-n32:64-S128-ni:1:10:20"),

131 UsesMultivalueABI(Options.MCOptions.getABIName() == "experimental-mv") {

132

133

134

135

136

137

138

141

142

143

147

149

150

151

152

153}

154

156

160}

161

164 std::string FS) const {

165 auto &I = SubtargetMap[CPU + FS];

166 if (I) {

167 I = std::make_unique(TargetTriple, CPU, FS, *this);

168 }

169 return I.get();

170}

171

174 Attribute CPUAttr = F.getFnAttribute("target-cpu");

175 Attribute FSAttr = F.getFnAttribute("target-features");

176

177 std::string CPU =

179 std::string FS =

181

182

183

184

186

188}

189

190namespace {

191

192class CoalesceFeaturesAndStripAtomics final : public ModulePass {

193

194

195

196

197 static char ID;

199

200public:

203

204 bool runOnModule(Module &M) override {

206

207 std::string FeatureStr = getFeatureString(Features);

209 for (auto &F : M)

210 replaceFeatures(F, FeatureStr);

211

212 bool StrippedAtomics = false;

213 bool StrippedTLS = false;

214

215 if (!Features[WebAssembly::FeatureAtomics]) {

216 StrippedAtomics = stripAtomics(M);

217 StrippedTLS = stripThreadLocals(M);

218 } else if (!Features[WebAssembly::FeatureBulkMemory]) {

219 StrippedTLS |= stripThreadLocals(M);

220 }

221

222 if (StrippedAtomics && !StrippedTLS)

223 stripThreadLocals(M);

224 else if (StrippedTLS && !StrippedAtomics)

225 stripAtomics(M);

226

227 recordFeatures(M, Features, StrippedAtomics || StrippedTLS);

228

229

230 return true;

231 }

232

233private:

235

236

237

238

240 bool AnyDefinedFuncs = false;

241 for (auto &F : M) {

242 if (F.isDeclaration())

243 continue;

244

246 AnyDefinedFuncs = true;

247 }

248

249

250

251 if (!AnyDefinedFuncs) {

252 Features =

253 WasmTM

256 ->getFeatureBits();

257 }

258

259 return Features;

260 }

261

262 static std::string getFeatureString(const FeatureBitset &Features) {

263 std::string Ret;

265 if (Features[KV.Value])

266 Ret += (StringRef("+") + KV.Key + ",").str();

267 else

268 Ret += (StringRef("-") + KV.Key + ",").str();

269 }

270 return Ret;

271 }

272

273 void replaceFeatures(Function &F, const std::string &Features) {

274 F.removeFnAttr("target-features");

275 F.removeFnAttr("target-cpu");

276 F.addFnAttr("target-features", Features);

277 }

278

279 bool stripAtomics(Module &M) {

280

281

282 bool Stripped = false;

283 for (auto &F : M) {

284 for (auto &B : F) {

285 for (auto &I : B) {

286 if (I.isAtomic()) {

287 Stripped = true;

288 goto done;

289 }

290 }

291 }

292 }

293

294 done:

295 if (!Stripped)

296 return false;

297

300 for (auto &F : M)

302

303 return true;

304 }

305

306 bool stripThreadLocals(Module &M) {

307 bool Stripped = false;

308 for (auto &GV : M.globals()) {

309 if (GV.isThreadLocal()) {

310

312 if (IntrinsicInst *II = dyn_cast(U.getUser())) {

313 if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&

314 II->getArgOperand(0) == &GV) {

315 II->replaceAllUsesWith(&GV);

316 II->eraseFromParent();

317 }

318 }

319 }

320

321 Stripped = true;

322 GV.setThreadLocal(false);

323 }

324 }

325 return Stripped;

326 }

327

328 void recordFeatures(Module &M, const FeatureBitset &Features, bool Stripped) {

330 if (Features[KV.Value]) {

331

332 std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str();

333 M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,

335 }

336 }

337

338

339

340

341

342 if (Stripped) {

343 M.addModuleFlag(Module::ModFlagBehavior::Error, "wasm-feature-shared-mem",

345 }

346 }

347};

348char CoalesceFeaturesAndStripAtomics::ID = 0;

349

350

352public:

355

357 return getTM();

358 }

359

360 FunctionPass *createTargetRegisterAllocator(bool) override;

361

362 void addIRPasses() override;

363 void addISelPrepare() override;

364 bool addInstSelector() override;

365 void addOptimizedRegAlloc() override;

366 void addPostRegAlloc() override;

367 bool addGCPasses() override { return false; }

368 void addPreEmitPass() override;

369 bool addPreISel() override;

370

371

372 bool addRegAssignAndRewriteFast() override { return false; }

373

374

375 bool addRegAssignAndRewriteOptimized() override { return false; }

376};

377}

378

382 return WebAssemblyFunctionInfo::create(Allocator, F,

384}

385

389}

390

393 return new WebAssemblyPassConfig(*this, PM);

394}

395

396FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {

397 return nullptr;

398}

399

405

407

408

409 if (WasmEnableEmEH && WasmEnableEH)

411 "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh");

412

413 if (WasmEnableEmSjLj && WasmEnableSjLj)

415 "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");

416

417 if (WasmEnableEmEH && WasmEnableSjLj)

419 "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj");

420

421

422

423

424

425

426

427

428

429

430 TM->Options.ExceptionModel = TM->getMCAsmInfo()->getExceptionHandlingType();

431

432

435 report_fatal_error("-exception-model should be either 'none' or 'wasm'");

438 "-enable-emscripten-cxx-exceptions");

441 "-wasm-enable-eh only allowed with -exception-model=wasm");

444 "-wasm-enable-sjlj only allowed with -exception-model=wasm");

445 if ((!WasmEnableEH && !WasmEnableSjLj) &&

448 "-exception-model=wasm only allowed with at least one of "

449 "-wasm-enable-eh or -wasm-enable-sjlj");

450

451

452

453

454}

455

456

457

458

459

460

461void WebAssemblyPassConfig::addIRPasses() {

462

464

465

467

468

469

471

472

475

477

478

479

480

481

482

483

484 if (!WasmEnableEmEH && !WasmEnableEH) {

486

487

489 }

490

491

492

493

494

495 if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)

497

498

500

502}

503

504void WebAssemblyPassConfig::addISelPrepare() {

505

506

508

509 addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine()));

510

511

513

515}

516

517bool WebAssemblyPassConfig::addInstSelector() {

519 addPass(

521

522

523

525

526

527

529

530

532

533

534

536

537 return false;

538}

539

540void WebAssemblyPassConfig::addOptimizedRegAlloc() {

541

542

543

544

545

546

547

551}

552

553void WebAssemblyPassConfig::addPostRegAlloc() {

554

555

556

557

558

568

569

570

572

574}

575

576void WebAssemblyPassConfig::addPreEmitPass() {

578

579

581

582

585

586

587

590

591

592

593

595

596

598

600

601

603

604

605

606

607

608

610

611

612

613

615 }

616

617

618

620

621

623

624

627

628

630

631

634

635

637

638

641

642

644}

645

646bool WebAssemblyPassConfig::addPreISel() {

649 return false;

650}

651

655}

656

661}

662

669 return false;

670}

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_EXTERNAL_VISIBILITY

static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")

uint64_t IntrinsicInst * II

static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")

FunctionAnalysisManager FAM

Target-Independent Code Generator Pass Configuration Options pass.

This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.

This file provides WebAssembly-specific target descriptions.

This file declares WebAssembly-specific per-machine-function information.

This file registers the WebAssembly target.

static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM, const Triple &TT)

LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget()

static void basicCheckForEHAndSjLj(TargetMachine *TM)

static cl::opt< bool > WasmDisableExplicitLocals("wasm-disable-explicit-locals", cl::Hidden, cl::desc("WebAssembly: output implicit locals in" " instruction output for test purposes only."), cl::init(false))

static cl::opt< bool > WasmDisableFixIrreducibleControlFlowPass("wasm-disable-fix-irreducible-control-flow-pass", cl::Hidden, cl::desc("webassembly: disables the fix " " irreducible control flow optimization pass"), cl::init(false))

This file declares the WebAssembly-specific subclass of TargetMachine.

This file declares the WebAssembly-specific subclass of TargetLoweringObjectFile.

This file a TargetTransformInfo::Concept conforming object specific to the WebAssembly target machine...

This file contains the declaration of the WebAssembly-specific utility functions.

This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.

A container for analyses that lazily runs them and caches their results.

StringRef getValueAsString() const

Return the attribute's value as a string.

bool isValid() const

Return true if the attribute is any kind of attribute.

Allocate memory in an ever growing pool, as if by bump-pointer.

implements a set of functionality in the TargetMachine class for targets that make use of the indepen...

Lightweight error class with error context and mandatory checking.

Container class for subtarget features.

FunctionPass class - This class is used to implement most global optimizations.

A wrapper class for inspecting calls to intrinsic functions.

A pass that lowers atomic intrinsic into non-atomic intrinsics.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &)

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

A Module instance is used to store all the information related to an LLVM module.

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...

Represents a range in source code.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

Primary interface to the complete machine description for the target machine.

Triple TargetTriple

Triple string, CPU name, and target feature strings the TargetMachine instance is created with.

StringRef getTargetFeatureString() const

StringRef getTargetCPU() const

std::unique_ptr< const MCSubtargetInfo > STI

void setTargetFeatureString(StringRef FS)

void resetTargetOptions(const Function &F) const

Reset the target options based on the function's attributes.

unsigned UniqueSectionNames

unsigned FunctionSections

Emit functions into separate sections.

unsigned NoTrapAfterNoreturn

Do not emit a trap instruction for 'unreachable' IR instructions behind noreturn calls,...

unsigned DataSections

Emit data into separate sections.

unsigned TrapUnreachable

Emit target-specific trap instruction for 'unreachable' IR instructions.

Target-Independent Code Generator Pass Configuration Options.

virtual void addPostRegAlloc()

This method may be implemented by targets that want to run passes after register allocation pass pipe...

virtual bool addInstSelector()

addInstSelector - This method should install an instruction selector pass, which converts from LLVM c...

virtual bool addPreISel()

Methods with trivial inline returns are convenient points in the common codegen pass pipeline where t...

virtual void addOptimizedRegAlloc()

addOptimizedRegAlloc - Add passes related to register allocation.

virtual void addPreEmitPass()

This pass may be implemented by targets that want to run passes immediately before machine code is em...

virtual void addIRPasses()

Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...

virtual void addISelPrepare()

Add common passes that perform LLVM IR to IR transforms in preparation for instruction selection.

TargetSubtargetInfo - Generic base class for all target subtargets.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

Target - Wrapper for Target specific information.

Triple - Helper class for working with autoconf configuration names.

A Use represents the edge between a Value definition and its users.

This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...

yaml::MachineFunctionInfo * createDefaultFuncInfoYAML() const override

Allocate and return a default initialized instance of the YAML representation for the MachineFunction...

bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, PerFunctionMIParsingState &PFS, SMDiagnostic &Error, SMRange &SourceRange) const override

Parse out the target's MachineFunctionInfo from the YAML reprsentation.

WebAssemblyTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT)

Create an WebAssembly architecture model.

TargetPassConfig * createPassConfig(PassManagerBase &PM) override

Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...

const WebAssemblySubtarget * getSubtargetImpl() const

MachineFunctionInfo * createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override

Create the target's instance of MachineFunctionInfo.

~WebAssemblyTargetMachine() override

TargetTransformInfo getTargetTransformInfo(const Function &F) const override

Get a TargetTransformInfo implementation for the target.

yaml::MachineFunctionInfo * convertFuncInfoToYAML(const MachineFunction &MF) const override

Allocate and initialize an instance of the YAML representation of the MachineFunctionInfo.

PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

cl::opt< bool > WasmUseLegacyEH

cl::opt< bool > WasmEnableEH

cl::opt< bool > WasmEnableSjLj

cl::opt< bool > WasmEnableEmEH

cl::opt< bool > WasmEnableEmSjLj

initializer< Ty > init(const Ty &Val)

@ WASM_FEATURE_PREFIX_USED

@ WASM_FEATURE_PREFIX_DISALLOWED

This is an optimization pass for GlobalISel generic memory operations.

void initializeOptimizeReturnedPass(PassRegistry &)

FunctionPass * createIndirectBrExpandPass()

void initializeWebAssemblyLowerBrUnlessPass(PassRegistry &)

FunctionPass * createWebAssemblyLowerRefTypesIntPtrConv()

FunctionPass * createWebAssemblyRegNumbering()

FunctionPass * createUnreachableBlockEliminationPass()

createUnreachableBlockEliminationPass - The LLVM code generator does not work well with unreachable b...

ModulePass * createWebAssemblyAddMissingPrototypes()

char & RegisterCoalescerID

RegisterCoalescer - This pass merges live ranges to eliminate copies.

FunctionPass * createWebAssemblyLateEHPrepare()

const SubtargetFeatureKV WebAssemblyFeatureKV[WebAssembly::NumSubtargetFeatures]

void initializeWebAssemblyLateEHPreparePass(PassRegistry &)

@ None

No exception support.

@ Wasm

WebAssembly Exception Handling.

FunctionPass * createWebAssemblyFixBrTableDefaults()

void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &)

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

char & PatchableFunctionID

This pass implements the "patchable-function" attribute.

void initializeWebAssemblyExceptionInfoPass(PassRegistry &)

char & PostRASchedulerID

PostRAScheduler - This pass performs post register allocation scheduling.

char & RemoveLoadsIntoFakeUsesID

RemoveLoadsIntoFakeUses pass.

void initializeWebAssemblyRegNumberingPass(PassRegistry &)

void initializeWebAssemblyLowerRefTypesIntPtrConvPass(PassRegistry &)

void initializeWebAssemblyDAGToDAGISelLegacyPass(PassRegistry &)

FunctionPass * createWebAssemblyReplacePhysRegs()

void initializeWebAssemblyRegColoringPass(PassRegistry &)

CodeModel::Model getEffectiveCodeModel(std::optional< CodeModel::Model > CM, CodeModel::Model Default)

Helper method for getting the code model, returning Default if CM does not have a value.

FunctionPass * createWebAssemblyMemIntrinsicResults()

char & ShrinkWrapID

ShrinkWrap pass. Look for the best place to insert save and restore.

char & MachineLateInstrsCleanupID

MachineLateInstrsCleanup - This pass removes redundant identical instructions after register allocati...

FunctionPass * createWebAssemblyDebugFixup()

ModulePass * createLowerGlobalDtorsLegacyPass()

FunctionPass * createLowerInvokePass()

void initializeLowerGlobalDtorsLegacyPassPass(PassRegistry &)

Target & getTheWebAssemblyTarget32()

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

void initializeWebAssemblyNullifyDebugValueListsPass(PassRegistry &)

char & StackMapLivenessID

StackMapLiveness - This pass analyses the register live-out set of stackmap/patchpoint intrinsics and...

void initializeWebAssemblyFixIrreducibleControlFlowPass(PassRegistry &)

FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOptLevel OptLevel)

This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling.

char & FuncletLayoutID

This pass lays out funclets contiguously.

void initializeWebAssemblyRegStackifyPass(PassRegistry &)

FunctionPass * createWebAssemblyCFGStackify()

FunctionPass * createWebAssemblyOptimizeLiveIntervals()

char & PostRAMachineSinkingID

This pass perform post-ra machine sink for COPY instructions.

CodeGenOptLevel

Code generation optimization level.

FunctionPass * createWebAssemblyOptimizeReturned()

FunctionPass * createWebAssemblyRefTypeMem2Local()

FunctionPass * createWebAssemblyCleanCodeAfterTrap()

void initializeWebAssemblyOptimizeLiveIntervalsPass(PassRegistry &)

FunctionPass * createWebAssemblySetP2AlignOperands()

ModulePass * createWebAssemblyLowerEmscriptenEHSjLj()

void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &)

FunctionPass * createWebAssemblyArgumentMove()

FunctionPass * createWebAssemblyExplicitLocals()

Target & getTheWebAssemblyTarget64()

void initializeWebAssemblyMemIntrinsicResultsPass(PassRegistry &)

void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &)

void initializeWebAssemblyExplicitLocalsPass(PassRegistry &)

FunctionPass * createWebAssemblyFixIrreducibleControlFlow()

ModulePass * createWebAssemblyFixFunctionBitcasts()

FunctionPass * createWebAssemblyLowerBrUnless()

void initializeFixFunctionBitcastsPass(PassRegistry &)

FunctionPass * createWebAssemblyRegColoring()

void initializeWebAssemblyPeepholePass(PassRegistry &)

ModulePass * createWebAssemblyMCLowerPrePass()

void initializeWebAssemblyRefTypeMem2LocalPass(PassRegistry &)

char & MachineBlockPlacementID

MachineBlockPlacement - This pass places basic blocks based on branch probabilities.

FunctionPass * createAtomicExpandLegacyPass()

AtomicExpandPass - At IR level this pass replace atomic instructions with __atomic_* library calls,...

FunctionPass * createWebAssemblyRegStackify()

FunctionPass * createWebAssemblyCFGSort()

void initializeWebAssemblyCFGSortPass(PassRegistry &)

void initializeWebAssemblyFixBrTableDefaultsPass(PassRegistry &)

FunctionPass * createWebAssemblyNullifyDebugValueLists()

void initializeWebAssemblyCFGStackifyPass(PassRegistry &)

void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &)

void initializeWebAssemblyDebugFixupPass(PassRegistry &)

char & MachineCopyPropagationID

MachineCopyPropagation - This pass performs copy propagation on machine instructions.

void initializeWebAssemblyArgumentMovePass(PassRegistry &)

FunctionPass * createWebAssemblyPeephole()

void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &)

MachineFunctionInfo - This class can be derived from and used by targets to hold private target-speci...

RegisterTargetMachine - Helper template for registering a target machine implementation,...

Used to provide key value pairs for feature and CPU bit flags.

Targets should override this in a way that mirrors the implementation of llvm::MachineFunctionInfo.