multiversal/executor.rb
2019-09-16 22:45:24 +02:00

156 lines
No EOL
4.3 KiB
Ruby

require './generator'
class ExecutorGenerator < Generator
def initialize
super
@need_guest = false
@noguest_types = Set.new(["void"])
end
def need_guest
if @need_guest then
return yield
else
@need_guest = true
result = yield
@need_guest = false
return result
end
end
def type_needs_guest?(type)
size_of_type(type) != 1 and not @noguest_types.include?(type)
end
def guestify_type(type, guest)
type.strip!
return type, "", "" if not type_needs_guest?(type)
if type =~ /^(.*)(\[[^\[\]]*\])$/ then
post = $2
type1, _, _ = guestify_type($1, true)
if guest then
return "GUEST<#{type1}#{post}>", "", ""
else
return type1, "", post
end
elsif type =~ /^(.*)\*$/ then
type1, _, _ = guestify_type($1, true)
if guest then
return "GUEST<#{type1}*>", "", ""
else
return type1, "*", ""
end
elsif guest then
if type =~ /^const[ \t]+(.*)$/ and not type_needs_guest?($1) then
return type
else
return "GUEST<#{type}>"
end
else
return type, "", ""
end
end
def decl(type, thing=nil)
t1, pre, post = guestify_type(type, @need_guest)
return "#{t1} #{pre}#{thing}#{post}"
end
def convert_expression(expr)
return expr.gsub(/\'([^\']+)\'/) {|x| "\"#{$1}\"_4"}
end
def declare_struct_union(what, value)
@noguest_types << value["name"]
@out << "#{what} #{value["name"]}"
if value["members"] then
@out << "{"
@out << "GUEST_STRUCT;"
need_guest { declare_members(value["members"]) }
@out << "}"
end
@out << ";"
end
def declare_dispatcher(value)
@out << "DISPATCHER_TRAP(#{value["name"]}, "
@out << "#{hexlit(value["trap"])}, #{value["selector-location"]});\n"
end
def declare_lowmem(value)
@out << "const LowMemGlobal<#{decl(value["type"])}> #{value["name"]}"
@out << "{ #{hexlit(value["address"],12)} };"
end
def declare_function(fun)
renamed = true
name = fun["name"]
dispatcher = (fun["dispatcher"] and $global_name_map[fun["dispatcher"]]["dispatcher"])
trap = (fun["trap"] or (dispatcher and dispatcher["trap"]))
cname = renamed ? "C_"+name : name
@out << (fun["return"] or "void") << " " << cname
args = (fun["args"] or [])
@out << "(" << (args.map {|arg| decl(arg["type"], arg["name"])}).join(", ") << ");"
if fun["returnreg"] or args.any? {|arg| arg["register"]} then
elsif fun["selector"] then
@out << "PASCAL_SUBTRAP(#{name}, #{hexlit(trap)}, "
@out << "#{hexlit(fun["selector"])}, #{hexlit(fun["dispatcher"])});\n"
elsif trap then
@out << "PASCAL_TRAP(#{name}, #{hexlit(trap)});\n"
else
end
end
def declare_funptr(value)
name = value["name"]
args = (value["args"] or [])
@out << "using #{name} = UPP<"
@out << (value["return"] or "void") << "("
args = (value["args"] or [])
@out << args.map {|arg|decl(arg["type"], arg["name"])}.join(", ")
@out << ")>;\n"
if args.any? {|arg| arg["register"]} then
procinfo = 42;
print "WARNING UNSUPPORTED register funptr: #{name}\n"
end
end
def generate_preamble(header)
super
@out << "#pragma once\n"
header.included.each do |file|
@out << "#include \"#{file}.h\"\n"
end
@out << "\n"
@out << "#define MODULE_NAME #{header.name}\n"
@out << "#include <base/api-module.h>\n"
@out << "\n\n"
@out << "namespace Executor {\n\n"
end
def generate_postamble(header)
@out << "} /* namespace Executor */"
end
def generate(defs)
FileUtils.mkdir_p "out/executor"
defs.topsort.each do |name|
formatted_file "out/executor/#{name}.h" do |f|
f << generate_header(defs.headers[name])
end
end
end
end