Index: test/wasm/Inputs/data-segments-a.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/data-segments-a.ll @@ -0,0 +1,15 @@ +; ModuleID = '/home/fitzgen/scratch/wasm-linking/a.c' +source_filename = "/home/fitzgen/scratch/wasm-linking/a.c" +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +@A_HELLO = hidden global [6 x i8] c"hello\00", align 1 +@A_GOODBYE = hidden global [8 x i8] c"goodbye\00", align 1 +@A_WHATEVER = hidden global [9 x i8] c"whatever\00", align 1 +@N_ITERATIONS = hidden global i32 42, align 4 + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 7.0.0 (https://git.llvm.org/git/clang.git/ d80c081db0b2df5b98af66ca9331c8cc1630eba1) (https://git.llvm.org/git/llvm.git 013b5ae046d55ad6c09587aae96123e8a2ffff56)"} Index: test/wasm/Inputs/data-segments-b.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/data-segments-b.ll @@ -0,0 +1,52 @@ +; ModuleID = '/home/fitzgen/scratch/wasm-linking/b.c' +source_filename = "/home/fitzgen/scratch/wasm-linking/b.c" +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +@N_ITERATIONS = external global i32, align 4 +@A_HELLO = external global i8*, align 4 +@A_GOODBYE = external global i8*, align 4 +@A_WHATEVER = external global i8*, align 4 + +; Function Attrs: noinline nounwind optnone +define void @printem() #0 { +entry: + %i = alloca i32, align 4 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32, i32* %i, align 4 + %1 = load i32, i32* @N_ITERATIONS, align 4 + %cmp = icmp slt i32 %0, %1 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %2 = load i8*, i8** @A_HELLO, align 4 + call void @print(i8* %2) + %3 = load i8*, i8** @A_GOODBYE, align 4 + call void @print(i8* %3) + %4 = load i8*, i8** @A_WHATEVER, align 4 + call void @print(i8* %4) + br label %for.inc + +for.inc: ; preds = %for.body + %5 = load i32, i32* %i, align 4 + %inc = add nsw i32 %5, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +declare void @print(i8*) #1 + +attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 7.0.0 (https://git.llvm.org/git/clang.git/ d80c081db0b2df5b98af66ca9331c8cc1630eba1) (https://git.llvm.org/git/llvm.git 013b5ae046d55ad6c09587aae96123e8a2ffff56)"} Index: test/wasm/merge-data-segments.test =================================================================== --- /dev/null +++ test/wasm/merge-data-segments.test @@ -0,0 +1,13 @@ +# RUN: llc -filetype=obj %p/Inputs/data-segments-a.ll -o %t.data-segments-a.o +# RUN: llc -filetype=obj %p/Inputs/data-segments-b.ll -o %t.data-segments-b.o +# RUN: wasm-ld --allow-undefined -o %t.wasm %t.data-segments-a.o %t.data-segments-b.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +CHECK: - Type: DATA +CHECK: Segments: +CHECK: - SectionOffset: 7 +CHECK: MemoryIndex: 0 +CHECK: Offset: +CHECK: Opcode: I32_CONST +CHECK: Value: 1024 +CHECK: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000 Index: test/wasm/no-merge-data-segments.test =================================================================== --- /dev/null +++ test/wasm/no-merge-data-segments.test @@ -0,0 +1,31 @@ +# RUN: llc -filetype=obj %p/Inputs/data-segments-a.ll -o %t.data-segments-a.o +# RUN: llc -filetype=obj %p/Inputs/data-segments-b.ll -o %t.data-segments-b.o +# RUN: wasm-ld --allow-undefined --no-merge-data-segments -o %t.wasm %t.data-segments-a.o %t.data-segments-b.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +CHECK: - Type: DATA +CHECK: Segments: +CHECK: - SectionOffset: 7 +CHECK: MemoryIndex: 0 +CHECK: Offset: +CHECK: Opcode: I32_CONST +CHECK: Value: 1024 +CHECK: Content: 68656C6C6F00 +CHECK: - SectionOffset: 19 +CHECK: MemoryIndex: 0 +CHECK: Offset: +CHECK: Opcode: I32_CONST +CHECK: Value: 1030 +CHECK: Content: 676F6F6462796500 +CHECK: - SectionOffset: 33 +CHECK: MemoryIndex: 0 +CHECK: Offset: +CHECK: Opcode: I32_CONST +CHECK: Value: 1038 +CHECK: Content: '776861746576657200' +CHECK: - SectionOffset: 48 +CHECK: MemoryIndex: 0 +CHECK: Offset: +CHECK: Opcode: I32_CONST +CHECK: Value: 1048 +CHECK: Content: 2A000000 Index: wasm/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -25,6 +25,7 @@ bool GcSections; bool ImportMemory; bool ImportTable; + bool MergeDataSegments; bool PrintGcSections; bool Relocatable; bool StripAll; Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -293,6 +293,9 @@ Config->Relocatable = Args.hasArg(OPT_relocatable); Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable); + Config->MergeDataSegments = + Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, + !Config->Relocatable); Config->PrintGcSections = Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); Config->SearchPaths = args::getStrings(Args, OPT_L); Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -40,6 +40,10 @@ "Enable garbage collection of unused sections", "Disable garbage collection of unused sections">; +defm merge_data_segments: B<"merge-data-segments", + "Enable merging data segments", + "Disable merging data segments">; + def help: F<"help">, HelpText<"Print option help">; def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"">, Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -858,7 +858,7 @@ } static StringRef getOutputDataSegmentName(StringRef Name) { - if (Config->Relocatable) + if (!Config->MergeDataSegments) return Name; if (Name.startswith(".text.")) return ".text";