Skip to content

Commit 6eb264b

Browse files
authored
Add support for -S, -emit-llvm and output to stdout (-o -) (#9014)
1 parent 3022d10 commit 6eb264b

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

emcc.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -974,12 +974,22 @@ def optimizing(opts):
974974

975975
newargs = [a for a in newargs if a is not '']
976976

977-
# -c means do not link in gcc, and for us, the parallel is to not go all the way to JS, but stop at bitcode
978977
has_dash_c = '-c' in newargs
979-
if has_dash_c:
980-
assert has_source_inputs or has_header_inputs, 'Must have source code or header inputs to use -c'
981-
target = target_basename + '.o'
982-
final_suffix = '.o'
978+
has_dash_S = '-S' in newargs
979+
if has_dash_c or has_dash_S:
980+
assert has_source_inputs or has_header_inputs, 'Must have source code or header inputs to use -c or -S'
981+
if has_dash_c:
982+
if '-emit-llvm' in newargs:
983+
final_suffix = '.bc'
984+
else:
985+
final_suffix = '.o'
986+
elif has_dash_S:
987+
if '-emit-llvm' in newargs:
988+
final_suffix = '.ll'
989+
else:
990+
final_suffix = '.s'
991+
target = target_basename + final_suffix
992+
983993
if '-E' in newargs:
984994
final_suffix = '.eout' # not bitcode, not js; but just result from preprocessing stage of the input file
985995
if '-M' in newargs or '-MM' in newargs:
@@ -1787,7 +1797,8 @@ def compile_source_file(i, input_file):
17871797
logger.debug("running: " + ' '.join(shared.Building.doublequote_spaces(args))) # NOTE: Printing this line here in this specific format is important, it is parsed to implement the "emcc --cflags" command
17881798
if run_process(args, check=False).returncode != 0:
17891799
exit_with_error('compiler frontend failed to generate LLVM bitcode, halting')
1790-
assert(os.path.exists(output_file))
1800+
if output_file != '-':
1801+
assert(os.path.exists(output_file))
17911802

17921803
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
17931804
for i, input_file in input_files:
@@ -1839,9 +1850,9 @@ def compile_source_file(i, input_file):
18391850

18401851
# Decide what we will link
18411852
executable_endings = JS_CONTAINING_ENDINGS + ('.wasm',)
1842-
stop_at_bitcode = final_suffix not in executable_endings
1853+
compile_only = final_suffix not in executable_endings or has_dash_c or has_dash_S
18431854

1844-
if stop_at_bitcode or not shared.Settings.WASM_BACKEND:
1855+
if compile_only or not shared.Settings.WASM_BACKEND:
18451856
# Filter link flags, keeping only those that shared.Building.link knows
18461857
# how to deal with. We currently can't handle flags with options (like
18471858
# -Wl,-rpath,/bin:/lib, where /bin:/lib is an option for the -rpath
@@ -1855,8 +1866,8 @@ def supported(f):
18551866

18561867
linker_inputs = [val for _, val in sorted(temp_files + link_flags)]
18571868

1858-
# If we were just asked to generate bitcode, stop there
1859-
if stop_at_bitcode:
1869+
# If we were just compiling stop here
1870+
if compile_only:
18601871
if not specified_target:
18611872
assert len(temp_files) == len(input_files)
18621873
for tempf, inputf in zip(temp_files, input_files):
@@ -1885,7 +1896,7 @@ def supported(f):
18851896
# we have multiple files: Link them
18861897
logger.debug('link: ' + str(linker_inputs) + specified_target)
18871898
shared.Building.link_to_object(linker_inputs, specified_target)
1888-
logger.debug('stopping at object file')
1899+
logger.debug('stopping after compile phase')
18891900
if shared.Settings.SIDE_MODULE:
18901901
exit_with_error('SIDE_MODULE must only be used when compiling to an executable shared library, and not when emitting an object file. That is, you should be emitting a .wasm file (for wasm) or a .js file (for asm.js). Note that when compiling to a typical native suffix for a shared library (.so, .dylib, .dll; which many build systems do) then Emscripten emits an object file, which you should then compile to .wasm or .js with SIDE_MODULE.')
18911902
if final_suffix.lower() in ('.so', '.dylib', '.dll'):

tests/test_other.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4480,6 +4480,28 @@ def test_syscall_without_filesystem(self):
44804480
}''')
44814481
run_process([PYTHON, EMCC, 'src.c', '-s', 'NO_FILESYSTEM=1'])
44824482

4483+
def test_dashS(self):
4484+
run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-S'])
4485+
self.assertExists('hello_world.s')
4486+
4487+
def test_dashS_stdout(self):
4488+
stdout = run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-S', '-o', '-'], stdout=PIPE).stdout
4489+
self.assertEqual(os.listdir('.'), [])
4490+
self.assertContained('hello_world.c', stdout)
4491+
4492+
def test_emit_llvm(self):
4493+
# TODO(https://github.com/emscripten-core/emscripten/issues/9016):
4494+
# We shouldn't need to copy the file here but if we don't then emcc will
4495+
# internally clobber the hello_world.ll in tests.
4496+
shutil.copyfile(path_from_root('tests', 'hello_world.c'), 'hello_world.c')
4497+
run_process([PYTHON, EMCC, 'hello_world.c', '-S', '-emit-llvm'])
4498+
self.assertExists('hello_world.ll')
4499+
bitcode = open('hello_world.ll').read()
4500+
self.assertContained('target triple = "', bitcode)
4501+
4502+
run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-c', '-emit-llvm'])
4503+
self.assertTrue(Building.is_bitcode('hello_world.bc'))
4504+
44834505
def test_dashE(self):
44844506
create_test_file('src.cpp', r'''#include <emscripten.h>
44854507
__EMSCRIPTEN_major__ __EMSCRIPTEN_minor__ __EMSCRIPTEN_tiny__ EMSCRIPTEN_KEEPALIVE

0 commit comments

Comments
 (0)