end
redef class ModelBuilder
- # The compilation directory
- var compile_dir: String
-
# Simple indirection to `Toolchain::write_and_make`
protected fun write_and_make(compiler: AbstractCompiler)
do
var platform = compiler.target_platform
var toolchain = platform.toolchain(toolcontext, compiler)
- compile_dir = toolchain.compile_dir
+ compiler.toolchain = toolchain
toolchain.write_and_make
end
end
# Compiler of the target program
var compiler: AbstractCompiler
- # Directory where to generate all C files
- fun compile_dir: String
+ # Directory where to generate all files
+ #
+ # The option `--compile_dir` change this directory.
+ fun root_compile_dir: String
do
var compile_dir = toolcontext.opt_compile_dir.value
- if compile_dir == null then compile_dir = ".nit_compile"
+ if compile_dir == null then compile_dir = "nit_compile"
return compile_dir
end
+ # Directory where to generate all C files
+ #
+ # By default it is `root_compile_dir` but some platform may require that it is a subdirectory.
+ fun compile_dir: String do return root_compile_dir
+
# Write all C files and compile them
fun write_and_make is abstract
end
do
var compile_dir = compile_dir
+ # Remove the compilation directory unless explicitly set
+ var auto_remove = toolcontext.opt_compile_dir.value == null
+
# Generate the .h and .c files
# A single C file regroups many compiled rumtime functions
# Note that we do not try to be clever an a small change in a Nit source file may change the content of all the generated .c files
var time0 = get_time
self.toolcontext.info("*** WRITING C ***", 1)
+ root_compile_dir.mkdir
compile_dir.mkdir
var cfiles = new Array[String]
compile_c_code(compile_dir)
+ if auto_remove then
+ sys.system("rm -r -- '{root_compile_dir.escape_to_sh}/'")
+ end
+
time1 = get_time
self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
end
var outpath = real_outpath.escape_to_mk
if outpath != real_outpath then
# If the name is crazy and need escaping, we will do an indirection
- # 1. generate the binary in the .nit_compile dir under an escaped name
+ # 1. generate the binary in the nit_compile dir under an escaped name
# 2. copy the binary at the right place in the `all` goal.
outpath = mainmodule.c_name
end
# The modelbuilder used to know the model and the AST
var modelbuilder: ModelBuilder is protected writable
+ # The associated toolchain
+ #
+ # Set by `modelbuilder.write_and_make` and permit sub-routines to access the current toolchain if required.
+ var toolchain: Toolchain is noinit
+
# Is hardening asked? (see --hardening)
fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
# Binds the generated C function names to Nit function names
fun build_c_to_nit_bindings
do
- var compile_dir = modelbuilder.compile_dir
+ var compile_dir = toolchain.compile_dir
var stream = new FileWriter.open("{compile_dir}/c_functions_hash.c")
stream.write("#include <string.h>\n")
self.header.add_decl("#include <string.h>")
self.header.add_decl("#include <sys/types.h>\n")
self.header.add_decl("#include <unistd.h>\n")
+ self.header.add_decl("#include <stdint.h>\n")
self.header.add_decl("#include \"gc_chooser.h\"")
self.header.add_decl("#ifdef ANDROID")
self.header.add_decl(" #include <android/log.h>")
return res
end
+ # Generate a byte value
+ fun byte_instance(value: Byte): RuntimeVariable
+ do
+ var t = mmodule.byte_type
+ var res = new RuntimeVariable("((unsigned char){value.to_s})", t, t)
+ return res
+ end
+
# Generate a char value
fun char_instance(value: Char): RuntimeVariable
do
else if mclass.name == "Bool" then
return "short int"
else if mclass.name == "Char" then
- return "char"
+ return "uint32_t"
else if mclass.name == "Float" then
return "double"
+ else if mclass.name == "Byte" then
+ return "unsigned char"
else if mclass.name == "NativeString" then
- return "char*"
+ return "unsigned char*"
else if mclass.name == "NativeArray" then
return "val*"
else
return "c"
else if mclass.name == "Float" then
return "d"
+ else if mclass.name == "Byte" then
+ return "b"
else if mclass.name == "NativeString" then
return "str"
else if mclass.name == "NativeArray" then
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
+ else if pname == "to_b" then
+ v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+ return true
else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+ v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Char" then
if pname == "output" then
- v.add("printf(\"%c\", {arguments.first});")
+ v.add("printf(\"%c\", ((unsigned char){arguments.first}));")
return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null)))
return true
else if pname == "ascii" then
- v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+ v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+ return true
+ end
+ else if cname == "Byte" then
+ if pname == "output" then
+ v.add("printf(\"%x\\n\", {arguments.first});")
+ return true
+ else if pname == "object_id" then
+ v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+ return true
+ else if pname == "+" then
+ v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "-" then
+ v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "unary -" then
+ v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+ return true
+ else if pname == "unary +" then
+ v.ret(arguments[0])
+ return true
+ else if pname == "*" then
+ v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "/" then
+ v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "%" then
+ v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "lshift" then
+ v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "rshift" then
+ v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "==" then
+ v.ret(v.equal_test(arguments[0], arguments[1]))
+ return true
+ else if pname == "!=" then
+ var res = v.equal_test(arguments[0], arguments[1])
+ v.ret(v.new_expr("!{res}", ret.as(not null)))
+ return true
+ else if pname == "<" then
+ v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == ">" then
+ v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "<=" then
+ v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == ">=" then
+ v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+ return true
+ else if pname == "to_i" then
+ v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+ return true
+ else if pname == "to_f" then
+ v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+ return true
+ else if pname == "ascii" then
+ v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Bool" then
else if pname == "to_i" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
+ else if pname == "to_b" then
+ v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+ return true
end
else if cname == "NativeString" then
if pname == "[]" then
- v.ret(v.new_expr("{arguments[0]}[{arguments[1]}]", ret.as(not null)))
+ v.ret(v.new_expr("(uint32_t){arguments[0]}[{arguments[1]}]", ret.as(not null)))
return true
else if pname == "[]=" then
- v.add("{arguments[0]}[{arguments[1]}]={arguments[2]};")
+ v.add("{arguments[0]}[{arguments[1]}]=(unsigned char){arguments[2]};")
return true
else if pname == "copy_to" then
v.add("memmove({arguments[1]}+{arguments[4]},{arguments[0]}+{arguments[3]},{arguments[2]});")
v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
return true
else if pname == "new" then
- v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
+ v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null)))
return true
end
else if cname == "NativeArray" then
v.ret(v.new_expr("glob_sys", ret.as(not null)))
return true
else if pname == "calloc_string" then
- v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
+ v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null)))
return true
else if pname == "calloc_array" then
v.calloc_array(ret.as(not null), arguments)
redef fun expr(v) do return v.int_instance(self.value.as(not null))
end
+redef class AByteExpr
+ redef fun expr(v) do return v.byte_instance(self.value.as(not null))
+end
+
redef class AFloatExpr
redef fun expr(v) do return v.float_instance("{self.n_float.text}") # FIXME use value, not n_float
end