diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -631,9 +631,7 @@ return Triple.getArch() == llvm::Triple::arm || Triple.getArch() == llvm::Triple::armeb || Triple.getArch() == llvm::Triple::thumb || - Triple.getArch() == llvm::Triple::thumbeb || - Triple.getArch() == llvm::Triple::wasm32 || - Triple.getArch() == llvm::Triple::wasm64; + Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm(); } else if (Model == "posix") return true; @@ -999,9 +997,8 @@ SanitizerKind::Nullability | SanitizerKind::LocalBounds; if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64 || - getTriple().getArch() == llvm::Triple::arm || - getTriple().getArch() == llvm::Triple::wasm32 || - getTriple().getArch() == llvm::Triple::wasm64 || getTriple().isAArch64()) + getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() || + getTriple().isAArch64()) Res |= SanitizerKind::CFIICall; if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().isAArch64()) Res |= SanitizerKind::ShadowCallStack; diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -37,7 +37,7 @@ bool importMemory; bool sharedMemory; bool importTable; - bool is64; + llvm::Optional is64; bool mergeDataSegments; bool pie; bool printGcSections; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -380,7 +380,6 @@ args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared); // Parse wasm32/64. - config->is64 = false; if (auto *arg = args.getLastArg(OPT_m)) { StringRef s = arg->getValue(); if (s == "wasm32") @@ -528,7 +527,7 @@ static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable, int value) { llvm::wasm::WasmGlobal wasmGlobal; - if (config->is64) { + if (config->is64.getValueOr(false)) { wasmGlobal.Type = {WASM_TYPE_I64, isMutable}; wasmGlobal.InitExpr.Value.Int64 = value; wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I64_CONST; @@ -570,16 +569,18 @@ if (config->isPic) { - WasmSym::stackPointer = createUndefinedGlobal( - "__stack_pointer", - config->is64 ? &mutableGlobalTypeI64 : &mutableGlobalTypeI32); + WasmSym::stackPointer = + createUndefinedGlobal("__stack_pointer", config->is64.getValueOr(false) + ? &mutableGlobalTypeI64 + : &mutableGlobalTypeI32); // For PIC code, we import two global variables (__memory_base and // __table_base) from the environment and use these as the offset at // which to load our static data and function table. // See: // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md WasmSym::memoryBase = createUndefinedGlobal( - "__memory_base", config->is64 ? &globalTypeI64 : &globalTypeI32); + "__memory_base", + config->is64.getValueOr(false) ? &globalTypeI64 : &globalTypeI32); WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32); WasmSym::memoryBase->markLive(); WasmSym::tableBase->markLive(); @@ -604,9 +605,9 @@ WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1); WasmSym::initTLS = symtab->addSyntheticFunction( "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN, - make(config->is64 ? i64ArgSignature - : i32ArgSignature, - "__wasm_init_tls")); + make( + config->is64.getValueOr(false) ? i64ArgSignature : i32ArgSignature, + "__wasm_init_tls")); } } diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -335,10 +335,12 @@ LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName() << " count=" << relocations.size() << "\n"); - unsigned opcode_ptr_const = - config->is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST; - unsigned opcode_ptr_add = - config->is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD; + unsigned opcode_ptr_const = config->is64.getValueOr(false) + ? WASM_OPCODE_I64_CONST + : WASM_OPCODE_I32_CONST; + unsigned opcode_ptr_add = config->is64.getValueOr(false) + ? WASM_OPCODE_I64_ADD + : WASM_OPCODE_I32_ADD; // TODO(sbc): Encode the relocations in the data section and write a loop // here to apply them. diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -576,10 +576,16 @@ obj = check(lto::InputFile::create(MemoryBufferRef( mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier())))); Triple t(obj->getTargetTriple()); - if (t.getArch() != Triple::wasm32) { - error(toString(this) + ": machine type must be wasm32"); + if (!t.isWasm()) { + error(toString(this) + ": machine type must be wasm32 or wasm64"); return; } + bool is64 = t.getArch() == Triple::wasm64; + if (config->is64.hasValue() && *config->is64 != is64) { + error(toString(this) + ": machine type for all bitcode files must match"); + return; + } + config->is64 = is64; std::vector keptComdats; for (StringRef s : obj->getComdatTable()) keptComdats.push_back(symtab->addComdat(s)); diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -139,7 +139,7 @@ } if (config->sharedMemory) import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; - if (config->is64) + if (config->is64.getValueOr(false)) import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64; writeImport(os, import); } @@ -236,7 +236,7 @@ flags |= WASM_LIMITS_FLAG_HAS_MAX; if (config->sharedMemory) flags |= WASM_LIMITS_FLAG_IS_SHARED; - if (config->is64) + if (config->is64.getValueOr(false)) flags |= WASM_LIMITS_FLAG_IS_64; writeUleb128(os, flags, "memory limits flags"); writeUleb128(os, numMemoryPages, "initial pages"); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -304,7 +304,8 @@ if (WasmSym::heapBase) WasmSym::heapBase->setVirtualAddress(memoryPtr); - uint64_t maxMemorySetting = 1ULL << (config->is64 ? 48 : 32); + uint64_t maxMemorySetting = 1ULL + << (config->is64.getValueOr(false) ? 48 : 32); if (config->initialMemory != 0) { if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize)) diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -282,6 +282,7 @@ bool HasLinkingSection = false; bool HasDylinkSection = false; bool SeenCodeSection = false; + bool HasMemory64 = false; wasm::WasmLinkingData LinkingData; uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -957,6 +957,8 @@ break; case wasm::WASM_EXTERNAL_MEMORY: Im.Memory = readLimits(Ctx); + if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64) + HasMemory64 = true; break; case wasm::WASM_EXTERNAL_TABLE: Im.Table = readTable(Ctx); @@ -1019,7 +1021,10 @@ uint32_t Count = readVaruint32(Ctx); Memories.reserve(Count); while (Count--) { - Memories.push_back(readLimits(Ctx)); + auto Limits = readLimits(Ctx); + if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64) + HasMemory64 = true; + Memories.push_back(Limits); } if (Ctx.Ptr != Ctx.End) return make_error("Memory section ended prematurely", @@ -1576,11 +1581,15 @@ return section_iterator(SectionRef(Ref, this)); } -uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } +uint8_t WasmObjectFile::getBytesInAddress() const { + return HasMemory64 ? 8 : 4; +} StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } -Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; } +Triple::ArchType WasmObjectFile::getArch() const { + return HasMemory64 ? Triple::wasm64 : Triple::wasm32; +} SubtargetFeatures WasmObjectFile::getFeatures() const { return SubtargetFeatures();