diff --git a/Makefile b/Makefile index 0dcf18ca8..55aca45ba 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,7 @@ include poincare/Makefile include escher/Makefile # Executable Makefiles include apps/Makefile +include build/struct_layout/Makefile include quiz/Makefile # Quiz needs to be included at the end products += $(objs) diff --git a/build/struct_layout/Makefile b/build/struct_layout/Makefile new file mode 100644 index 000000000..9579e8091 --- /dev/null +++ b/build/struct_layout/Makefile @@ -0,0 +1,8 @@ +products += build/struct_layout/apps_container_layout.json +build/struct_layout/apps_container_layout.json: + @echo "AST $@" + @clang -cc1 -x c++ -v -fdump-record-layouts apps/main.cpp -Iescher/include -Ikandinsky/include -Iion/include -Ipoincare/include -std=c++11 -emit-llvm-only -o /dev/null > foo.txt + @echo "JSON $@" + @cat foo.txt | ruby build/struct_layout/ast_to_json.rb AppsContainer > $@ + @rm foo.txt + diff --git a/build/struct_layout/ast_to_json.rb b/build/struct_layout/ast_to_json.rb new file mode 100644 index 000000000..38726ec4e --- /dev/null +++ b/build/struct_layout/ast_to_json.rb @@ -0,0 +1,83 @@ +#!/usr/bin/env ruby + +# Takes an clang-generated AST in stdin +# Outputs a D3-compliant JSON file + +require 'json' + +class CodeStruct + attr_accessor :name, :starts_at, :size + + def initialize(parent, name, starts_at) + @parent = parent + @name = name + @starts_at = starts_at + @size = 0 + @children = [] + @parent.add_child(self) unless @parent.nil? + end + + def ends_at(offset) + @size = offset-@starts_at + end + + def add_child(s) + @children.push(s) + end + + def as_d3_dict + res = {name: name} + if @children.empty? + res[:value] = size + else + res[:children] = @children.map{|c| c.as_d3_dict} + end + res + end + + def log(space = 0) + puts (" "*space) + "#{name} (SIZE=#{size})" + @children.each do |child| + child.log(space+2) + end + end +end + +def handleNewLine(line, index, stack) + # Example : " 213736 | class Timer (primary base)" + offset, depth, name = line.match(/\s*([0-9]+)\s\|(\s+)(.*)/).captures + offset = offset.to_i + depth = (depth.size-1)/2 + + parent = stack[depth-1] + stack[depth..-1].each do |finished| + finished.ends_at(offset) + end + stack = stack[0...depth] + struct = CodeStruct.new(parent, name, offset) + stack.push(struct) + + return stack +end + +class_name = ARGV[0] + +stack = [] +ignore_line = true +STDIN.each_line.with_index do |l,i| + if l == " 0 | class #{class_name}\n" + ignore_line = false + end + if l.start_with?(" | ") && ignore_line == false + ignore_line = true + end_offset = l.match(/sizeof=([0-9]+)/).captures.first + end_offset = end_offset.to_i + stack[-1].ends_at(end_offset) + stack[0].ends_at(end_offset) + end + unless ignore_line + stack = handleNewLine(l, i, stack) + end +end + +puts JSON.generate(stack[0].as_d3_dict) diff --git a/build/struct_layout/visualisation.html b/build/struct_layout/visualisation.html new file mode 100644 index 000000000..88d0d59c5 --- /dev/null +++ b/build/struct_layout/visualisation.html @@ -0,0 +1,243 @@ + + + +AppsContainer size breakdown + + +

AppsContainer size breakdown

+ +

+ + +