Skip to content

Commit 4da19e6

Browse files
committed
another world-changing.. a previously XFAIL test passes now, though, yay
1 parent 6dd15e8 commit 4da19e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2076
-381
lines changed

ejs

+135-103
Original file line numberDiff line numberDiff line change
@@ -7,141 +7,174 @@ compiler = require 'compiler'
77
util = require 'echo-util'
88
{ spawn } = require 'child_process'
99

10-
# this needs to be ".slice 1" for the ejs compiled form.
11-
# we probably need some global property so we can do:
12-
#
13-
# slice_count = if ejs? then 1 else 2
14-
# argv = process.argv.slice slice_count
15-
#
16-
argv = process.argv.slice 2
10+
slice_count = if __ejs? then 1 else 2
11+
argv = process.argv.slice slice_count
12+
13+
external_modules = []
14+
files = []
15+
16+
add_external_module = (modinfo) ->
17+
[library,module_name,module_entrypoint,link_flags] = modinfo.split ','
18+
external_modules.push { library, module_name, module_entrypoint, link_flags }
1719

1820
options =
19-
# our defaults:
20-
output_filename: null
21-
combine_scripts: false
22-
show_help: false
21+
# our defaults:
22+
output_filename: null
23+
combine_scripts: false
24+
show_help: false
25+
link_with_cxx: false
2326

2427
args =
25-
"-s": { flag: "combine_scripts", help: "treat all toplevels as being 1 context, evaluating them in the order present on the command line" }
26-
"-o": { option: "output_filename", help: "name of the output file." }
27-
"--help": { flag: "show_help", help: "output this help info." }
28+
"-s": { flag: "combine_scripts", help: "treat all toplevels as being 1 context, evaluating them in the order present on the command line" }
29+
"-o": { option: "output_filename", help: "name of the output file." }
30+
"-cxx": { flag: "link_with_cxx", help: "use clang++ to do the final link (default = no)" }
31+
"--module": { handler: add_external_module, help: "--module library.a,module-name,module_init,link_flags" }
32+
"--help": { flag: "show_help", help: "output this help info." }
2833

2934
output_usage = ->
30-
console.warn 'Usage:';
31-
console.warn ' ejs [options] file1.js file2.js file.js ...'
35+
console.warn 'Usage:';
36+
console.warn ' ejs [options] file1.js file2.js file.js ...'
3237

3338
output_options = ->
34-
console.warn 'Options:'
35-
for a of args
36-
console.warn " #{a}: #{args[a].help}"
37-
38-
files = []
39+
console.warn 'Options:'
40+
for a of args
41+
console.warn " #{a}: #{args[a].help}"
42+
3943
if argv.length > 0
40-
for ai in [0..argv.length-1]
41-
if args[argv[ai]]?
42-
o = args[argv[ai]]
43-
if o.flag?
44-
options[o.flag] = true
45-
else if o.option?
46-
options[o.option] = argv[++ai]
47-
else
48-
# end of options signals the rest of the array is files
49-
files = argv.slice ai
50-
break
44+
for ai in [0..argv.length-1]
45+
if args[argv[ai]]?
46+
o = args[argv[ai]]
47+
if o.flag?
48+
options[o.flag] = true
49+
else if o.option?
50+
options[o.option] = argv[++ai]
51+
else if o.handler?
52+
o.handler argv[++ai]
53+
else
54+
# end of options signals the rest of the array is files
55+
files = argv.slice ai
56+
break
5157

5258
if options.show_help
53-
output_usage()
54-
console.warn ''
55-
output_options()
56-
process.exit 0
59+
output_usage()
60+
console.warn ''
61+
output_options()
62+
process.exit 0
5763

5864
if files.length is 0
59-
output_usage()
60-
process.exit 0
65+
output_usage()
66+
process.exit 0
6167

6268
files_remaining = 0
6369

64-
s_filenames = []
70+
o_filenames = []
6571

6672
base_filenames = (path.basename file for file in files)
6773

6874
compiled_modules = []
6975

7076
compileFile = (filename, content, compileCallback) ->
71-
parse_tree = esprima.parse content, loc: true, raw: true
72-
73-
base_filename = util.genFreshFileName path.basename filename
74-
compiled_module = compiler.compile parse_tree, base_filename
75-
76-
ll_filename = "/tmp/#{base_filename}.ll"
77-
bc_filename = "/tmp/#{base_filename}.bc"
78-
bc_opt_filename = "/tmp/#{base_filename}.bc.opt"
79-
ll_opt_filename = "/tmp/#{base_filename}.ll.opt"
80-
s_filename = "/tmp/#{base_filename}.s"
81-
82-
llvm_as_args = ["-o=#{bc_filename}", ll_filename]
83-
opt_args = ["-O3", "-mem2reg", "-o=#{bc_opt_filename}", bc_filename]
84-
llvm_dis_args = ["-o=#{ll_opt_filename}", bc_opt_filename]
85-
llc_args = ["-march=x86-64", "-O2", "-o=#{s_filename}", ll_opt_filename]
86-
87-
compiled_module.writeToFile ll_filename
88-
89-
compiled_modules.push filename: filename, module_toplevel: compiled_module.toplevel_name
90-
91-
llvm_as = spawn "llvm-as", llvm_as_args
92-
llvm_as.stderr.on "data", (data) -> console.warn "#{data}"
93-
llvm_as.on "exit", (code) ->
94-
opt = spawn "opt", opt_args
95-
opt.stderr.on "data", (data) -> console.warn "#{data}"
96-
opt.on "exit", (code) ->
97-
llvm_dis = spawn "llvm-dis", llvm_dis_args
98-
llvm_dis.stderr.on "data", (data) -> console.warn "#{data}"
99-
llvm_dis.on "exit", (code) ->
100-
llc = spawn "llc", llc_args
101-
llc.stderr.on "data", (data) -> console.warn "#{data}"
102-
llc.on "exit", (code) ->
103-
s_filenames.push s_filename
104-
compileCallback()
77+
try
78+
parse_tree = esprima.parse content, loc: true, raw: true
79+
catch e
80+
console.warn "parse error at #{filename}:"
81+
process.exit -1
82+
83+
base_filename = util.genFreshFileName path.basename filename
84+
compiled_module = compiler.compile parse_tree, base_filename
85+
86+
ll_filename = "/tmp/#{base_filename}.ll"
87+
bc_filename = "/tmp/#{base_filename}.bc"
88+
bc_opt_filename = "/tmp/#{base_filename}.bc.opt"
89+
ll_opt_filename = "/tmp/#{base_filename}.ll.opt"
90+
s_filename = "/tmp/#{base_filename}.s"
91+
o_filename = "/tmp/#{base_filename}.o"
92+
93+
llvm_as_args = ["-o=#{bc_filename}", ll_filename]
94+
opt_args = ["-O3", "-mem2reg", "-o=#{bc_opt_filename}", bc_filename]
95+
llvm_dis_args = ["-o=#{ll_opt_filename}", bc_opt_filename]
96+
llc_args = ["-march=x86-64", "-O2", "-o=#{s_filename}", ll_opt_filename]
97+
clang_args = ["-march=x86-64", "-O2", "-c", "-o", o_filename, s_filename]
98+
99+
compiled_module.writeToFile ll_filename
100+
101+
compiled_modules.push filename: filename, module_toplevel: compiled_module.toplevel_name
102+
103+
llvm_as = spawn "llvm-as", llvm_as_args
104+
llvm_as.stderr.on "data", (data) -> console.warn "#{data}"
105+
llvm_as.on "exit", (code) ->
106+
opt = spawn "opt", opt_args
107+
opt.stderr.on "data", (data) -> console.warn "#{data}"
108+
opt.on "exit", (code) ->
109+
llvm_dis = spawn "llvm-dis", llvm_dis_args
110+
llvm_dis.stderr.on "data", (data) -> console.warn "#{data}"
111+
llvm_dis.on "exit", (code) ->
112+
llc = spawn "llc", llc_args
113+
llc.stderr.on "data", (data) -> console.warn "#{data}"
114+
llc.on "exit", (code) ->
115+
clang = spawn "clang", clang_args
116+
clang.stderr.on "data", (data) -> console.warn "#{data}"
117+
clang.on "exit", (code) ->
118+
o_filenames.push o_filename
119+
compileCallback()
105120

106121
generate_require_map = ->
107-
sanitize = (filename, c_callable) ->
108-
filename = filename.replace /\.js$/, ""
109-
if c_callable
110-
filename = filename.replace /[.,-\/\\]/g, "_" # this is insanely inadequate
111-
filename
112-
map_path = "/tmp/#{util.genFreshFileName path.basename files[0]}-require-map.c"
113-
map = fs.createWriteStream map_path
114-
map.write "typedef struct _EJSValue EJSValue;\n"
115-
map.write "typedef int EJSBool;\n"
116-
map.write "typedef EJSValue* (*ToplevelFunc) (EJSValue *env, EJSValue *this, int argc, EJSValue *exports);\n"
117-
map.write "typedef struct { const char* name; ToplevelFunc func; EJSValue *cached_exports; } EJSRequire;\n"
118-
compiled_modules.forEach ({ filename, module_toplevel }) ->
119-
sanitized = sanitize filename, true
120-
map.write "extern EJSValue* #{module_toplevel} (EJSValue* env, EJSValue *this, int argc, EJSValue *exports);\n"
121-
122-
123-
map.write "EJSRequire _ejs_require_map[] = {\n"
124-
compiled_modules.forEach ({ filename, module_toplevel }) ->
125-
map.write " { \"#{sanitize (path.basename filename), false}\", #{module_toplevel}, 0 },\n"
126-
map.write " { 0, 0, 0 }\n"
127-
map.write "};\n"
128-
map.write "const char *entry_filename = \"#{sanitize base_filenames[0], false}\";\n";
129-
map.end()
130-
map_path
122+
sanitize = (filename, c_callable) ->
123+
filename = filename.replace /\.js$/, ""
124+
if c_callable
125+
filename = filename.replace /[.,-\/\\]/g, "_" # this is insanely inadequate
126+
filename
127+
map_path = "/tmp/#{util.genFreshFileName path.basename files[0]}-require-map.#{if options.link_with_cxx then 'cpp' else 'c'}"
128+
map = fs.createWriteStream map_path
129+
if options.link_with_cxx
130+
map.write "extern \"C\" {"
131+
map.write "typedef struct _EJSValue EJSValue;\n"
132+
map.write "typedef int EJSBool;\n"
133+
map.write "typedef EJSValue* (*ExternalModuleEntry) (EJSValue *exports);\n"
134+
map.write "typedef struct { const char* name; ExternalModuleEntry func; EJSValue *cached_exports; } EJSExternalModuleRequire;\n"
135+
map.write "typedef EJSValue* (*ToplevelFunc) (EJSValue *env, EJSValue *_this, int argc, EJSValue **args);\n"
136+
map.write "typedef struct { const char* name; ToplevelFunc func; EJSValue *cached_exports; } EJSRequire;\n"
137+
external_modules.forEach ({ module_entrypoint }) ->
138+
map.write "extern EJSValue* #{module_entrypoint} (EJSValue *exports);\n"
139+
140+
compiled_modules.forEach ({ filename, module_toplevel }) ->
141+
sanitized = sanitize filename, true
142+
map.write "extern EJSValue* #{module_toplevel} (EJSValue* env, EJSValue *_this, int argc, EJSValue **args);\n"
143+
144+
map.write "EJSRequire _ejs_require_map[] = {\n"
145+
compiled_modules.forEach ({ filename, module_toplevel }) ->
146+
map.write " { \"#{sanitize (path.basename filename), false}\", #{module_toplevel}, 0 },\n"
147+
map.write " { 0, 0, 0 }\n"
148+
map.write "};\n"
149+
150+
map.write "EJSExternalModuleRequire _ejs_external_module_require_map[] = {\n"
151+
external_modules.forEach ({ module_name, module_entrypoint }) ->
152+
map.write " { \"#{module_name}\", #{module_entrypoint}, 0 },\n"
153+
map.write " { 0, 0, 0 }\n"
154+
map.write "};\n"
155+
156+
map.write "const char *entry_filename = \"#{sanitize base_filenames[0], false}\";\n";
157+
158+
if options.link_with_cxx
159+
map.write "};"
160+
map.end()
161+
map_path
131162

132163

133164
file_compiled = ->
134-
console.log "done compiling file"
135165
files_remaining = files_remaining - 1
136-
console.log "files remaining == #{files_remaining}"
137166
if files_remaining is 0
138167
map_filename = generate_require_map compiled_modules
139168

140-
clang_args = ["-o", options.output_filename || "#{files[0]}.exe"].concat s_filenames
169+
clang_args = ["-v", "-o", options.output_filename || "#{files[0]}.exe"].concat o_filenames
141170
clang_args.push map_filename
142171
clang_args.push path.resolve (path.dirname process.argv[1]), "runtime/libecho.a"
172+
for extern_module in external_modules
173+
clang_args.push extern_module.library
174+
clang_args = clang_args.concat extern_module.link_flags.split " "
143175

144-
clang = spawn "clang", clang_args
176+
console.warn "clang command line #{(if options.link_with_cxx then 'clang++' else 'clang')} #{clang_args.join ' '}"
177+
clang = spawn (if options.link_with_cxx then "g++" else "clang"), clang_args
145178
clang.stderr.on "data", (data) -> console.warn "#{data}"
146179
clang.on "exit", (code) ->
147180
console.warn "done."
@@ -155,5 +188,4 @@ if options.combine_scripts
155188
else
156189
files_remaining = files.length
157190
files.forEach (filename) ->
158-
compileFile filename, (fs.readFileSync filename, 'utf-8'), file_compiled
159-
191+
compileFile filename, (fs.readFileSync filename, 'utf-8'), file_compiled

ejs-llvm/Makefile

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
SOURCES=type.cpp \
2+
functiontype.cpp \
3+
structtype.cpp \
4+
ejs-llvm.cpp
5+
6+
CXX=clang++
7+
CXXFLAGS=-I../runtime -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-rtti -fno-common -Woverloaded-virtual -Wcast-qual
8+
9+
OBJECTS=$(SOURCES:%.cpp=%.o)
10+
11+
libejsllvm-module.a: $(OBJECTS)
12+
ar cru $@ $(OBJECTS)
13+
14+
clean:
15+
rm -f $(OBJECTS) libejsllvm-module.a

ejs-llvm/ejs-llvm.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include "ejs-llvm.h"
2+
#include "type.h"
3+
#include "functiontype.h"
4+
#include "structtype.h"
5+
#if notyet
6+
#include "value.h"
7+
#include "function.h"
8+
#include "basicblock.h"
9+
#include "phinode.h"
10+
#include "irbuilder.h"
11+
#include "module.h"
12+
#include "constant.h"
13+
#include "constantfp.h"
14+
#endif
15+
16+
std::string& trim(std::string& str)
17+
{
18+
str.erase(0, str.find_first_not_of(" \n")); //prefixing spaces
19+
str.erase(str.find_last_not_of(" \n")+1); //surfixing spaces
20+
return str;
21+
}
22+
23+
24+
extern "C" {
25+
void
26+
_ejs_llvm_init (EJSValue* global)
27+
{
28+
_ejs_llvm_Type_init (global);
29+
_ejs_llvm_FunctionType_init (global);
30+
_ejs_llvm_StructType_init (global);
31+
#if notyet
32+
_ejs_llvm_Value_init (global);
33+
_ejs_llvm_Function_init (global);
34+
_ejs_llvm_BasicBlock_init (global);
35+
_ejs_llvm_PHINode_init (global);
36+
_ejs_llvm_IRBuilder_init (global);
37+
_ejs_llvm_Module_init (global);
38+
_ejs_llvm_Constant_init (global);
39+
_ejs_llvm_ConstantFP_init (global);
40+
#endif
41+
}
42+
43+
44+
};

0 commit comments

Comments
 (0)