Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decoding to section mangler #3

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c186d0e
refactor(AST): introduce AstVisitor trait (#1231)
riederm Jun 12, 2024
b545e41
codegen: Add mangling for global variables
CohenArthur Mar 20, 2024
7a29d58
rusty: Update testsuite for new global variable section names
CohenArthur Mar 20, 2024
f880974
section_mangler: Change API for `SectionMangler::with_return_type`
CohenArthur Apr 18, 2024
15b8704
codegen: Propagate errors better when creating section names
CohenArthur Apr 18, 2024
92e586a
Merge pull request #1198 from embecosm/move-variables-to-sections
ghaith Jun 12, 2024
823dc54
section_mangler: Encode structs and enums
CohenArthur Mar 20, 2024
28b6b41
codegen: Mangle struct and enum types properly
CohenArthur Mar 20, 2024
06ece68
section-mangler: Add base for handling arrays
CohenArthur Mar 20, 2024
2e628ea
codegen: Handle more complex types in mangle_type
CohenArthur Mar 20, 2024
8c8f973
codegen: Mangle type aliases properly
CohenArthur Mar 20, 2024
54e08eb
rusty: Accept snapshots with new section names
CohenArthur Mar 20, 2024
a9d55a1
Merge pull request #1199 from embecosm/encode-complex-types
ghaith Jun 13, 2024
07e893f
section_mangler: Add base for decoding mangled names
CohenArthur Mar 20, 2024
10363b5
section-mangler: Add prefix constant, derive Debug and PartialEq
CohenArthur Mar 27, 2024
9d1ef35
section_mangler: Add struct decoding
CohenArthur Mar 28, 2024
a261e79
section_mangler: Add decoding of enum types
CohenArthur Mar 28, 2024
2df6561
section_mangler: Derive Clone on SectionMangler
CohenArthur Mar 29, 2024
6370241
section_mangler: Add .name() method
CohenArthur Mar 29, 2024
48a1f00
section_mangler: Add parsing of mangled functions
CohenArthur Mar 29, 2024
10d7826
rusty: Update insta testsuite for section mangling.
CohenArthur Apr 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,6 @@ pub enum AstStatement {
DefaultValue(DefaultValue),
// Literals
Literal(AstLiteral),
CastStatement(CastStatement),
MultipliedStatement(MultipliedStatement),
// Expressions
ReferenceExpr(ReferenceExpr),
Expand Down Expand Up @@ -735,9 +734,6 @@ impl Debug for AstNode {
}
AstStatement::ContinueStatement(..) => f.debug_struct("ContinueStatement").finish(),
AstStatement::ExitStatement(..) => f.debug_struct("ExitStatement").finish(),
AstStatement::CastStatement(CastStatement { target, type_name }) => {
f.debug_struct("CastStatement").field("type_name", type_name).field("target", target).finish()
}
AstStatement::ReferenceExpr(ReferenceExpr { access, base }) => {
f.debug_struct("ReferenceExpr").field("kind", access).field("base", base).finish()
}
Expand Down
1 change: 1 addition & 0 deletions compiler/plc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod control_statements;
pub mod literals;
mod pre_processor;
pub mod provider;
pub mod visitor;
714 changes: 714 additions & 0 deletions compiler/plc_ast/src/visitor.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: "results.join(\"\\n\")"
; ModuleID = 'main.st'
source_filename = "main.st"

define i16 @main() section "fn-main:i16" {
define i16 @main() section "fn-$RUSTY$main:i16" {
entry:
%main = alloca i16, align 2
store i16 0, i16* %main, align 2
Expand All @@ -14,9 +14,9 @@ entry:
ret i16 %main_ret
}

declare i16 @external() section "fn-external:i16"
declare i16 @external() section "fn-$RUSTY$external:i16"

; ModuleID = 'external.st'
source_filename = "external.st"

declare i16 @external() section "fn-external:i16"
declare i16 @external() section "fn-$RUSTY$external:i16"
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ expression: "results.join(\"\\n\")"
; ModuleID = 'main.st'
source_filename = "main.st"

@x = external global i16
@y = external global i16
@x = external global i16, section "var-$RUSTY$x:i16"
@y = external global i16, section "var-$RUSTY$y:i16"

define i16 @main() section "fn-main:i16" {
define i16 @main() section "fn-$RUSTY$main:i16" {
entry:
%main = alloca i16, align 2
store i16 0, i16* %main, align 2
Expand All @@ -19,12 +19,12 @@ entry:
ret i16 %main_ret
}

declare i16 @external() section "fn-external:i16"
declare i16 @external() section "fn-$RUSTY$external:i16"

; ModuleID = 'external.st'
source_filename = "external.st"

@x = external global i16
@y = external global i16
@x = external global i16, section "var-$RUSTY$x:i16"
@y = external global i16, section "var-$RUSTY$y:i16"

declare i16 @external() section "fn-external:i16"
declare i16 @external() section "fn-$RUSTY$external:i16"
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ source_filename = "app/file1.st"

%mainProg = type {}

@mainProg_instance = external global %mainProg, !dbg !0
@mainProg_instance = external global %mainProg, section "var-$RUSTY$mainProg_instance:r0", !dbg !0

define i16 @main() section "fn-main:i16" !dbg !10 {
define i16 @main() section "fn-$RUSTY$main:i16" !dbg !10 {
entry:
%main = alloca i16, align 2, !dbg !14
call void @llvm.dbg.declare(metadata i16* %main, metadata !15, metadata !DIExpression()), !dbg !17
Expand All @@ -19,7 +19,7 @@ entry:
ret i16 %main_ret, !dbg !14
}

declare !dbg !18 void @mainProg(%mainProg*) section "fn-mainProg:v"
declare !dbg !18 void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
Expand Down Expand Up @@ -54,9 +54,9 @@ source_filename = "lib/file2.st"

%mainProg = type {}

@mainProg_instance = global %mainProg zeroinitializer, !dbg !0
@mainProg_instance = global %mainProg zeroinitializer, section "var-$RUSTY$mainProg_instance:r0", !dbg !0

define void @mainProg(%mainProg* %0) section "fn-mainProg:v" !dbg !10 {
define void @mainProg(%mainProg* %0) section "fn-$RUSTY$mainProg:v" !dbg !10 {
entry:
call void @llvm.dbg.declare(metadata %mainProg* %0, metadata !13, metadata !DIExpression()), !dbg !14
ret void, !dbg !14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ source_filename = "file1.st"

%mainProg = type {}

@mainProg_instance = external global %mainProg, !dbg !0
@mainProg_instance = external global %mainProg, section "var-$RUSTY$mainProg_instance:r0", !dbg !0

define i16 @main() section "fn-main:i16" !dbg !10 {
define i16 @main() section "fn-$RUSTY$main:i16" !dbg !10 {
entry:
%main = alloca i16, align 2, !dbg !14
call void @llvm.dbg.declare(metadata i16* %main, metadata !15, metadata !DIExpression()), !dbg !17
Expand All @@ -19,7 +19,7 @@ entry:
ret i16 %main_ret, !dbg !14
}

declare !dbg !18 void @mainProg(%mainProg*) section "fn-mainProg:v"
declare !dbg !18 void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
Expand Down Expand Up @@ -54,9 +54,9 @@ source_filename = "file2.st"

%mainProg = type {}

@mainProg_instance = global %mainProg zeroinitializer, !dbg !0
@mainProg_instance = global %mainProg zeroinitializer, section "var-$RUSTY$mainProg_instance:r0", !dbg !0

define void @mainProg(%mainProg* %0) section "fn-mainProg:v" !dbg !10 {
define void @mainProg(%mainProg* %0) section "fn-$RUSTY$mainProg:v" !dbg !10 {
entry:
call void @llvm.dbg.declare(metadata %mainProg* %0, metadata !13, metadata !DIExpression()), !dbg !14
ret void, !dbg !14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ source_filename = "external_file1.st"

%mainProg = type {}

@mainProg_instance = external global %mainProg
@mainProg_instance = external global %mainProg, section "var-$RUSTY$mainProg_instance:r0"

define i16 @main() section "fn-main:i16" {
define i16 @main() section "fn-$RUSTY$main:i16" {
entry:
%main = alloca i16, align 2
store i16 0, i16* %main, align 2
Expand All @@ -18,16 +18,16 @@ entry:
ret i16 %main_ret
}

declare void @mainProg(%mainProg*) section "fn-mainProg:v"
declare void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"

; ModuleID = 'external_file2.st'
source_filename = "external_file2.st"

%mainProg = type {}

@mainProg_instance = global %mainProg zeroinitializer
@mainProg_instance = global %mainProg zeroinitializer, section "var-$RUSTY$mainProg_instance:r0"

define void @mainProg(%mainProg* %0) section "fn-mainProg:v" {
define void @mainProg(%mainProg* %0) section "fn-$RUSTY$mainProg:v" {
entry:
ret void
}
1 change: 1 addition & 0 deletions compiler/section_mangler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ version = "0.0.1"
edition = "2021"

[dependencies]
nom = "7.1"
61 changes: 39 additions & 22 deletions compiler/section_mangler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,25 @@

use std::fmt;

mod parser;

/// The main builder type of this crate. Use it to create mangling contexts, in
/// order to encode and decode binary type information.
// TODO: Add example code for using this builder
#[derive(Debug, PartialEq, Clone)]
pub enum SectionMangler {
Function(FunctionMangler),
Variable(VariableMangler),
}

#[derive(Debug, PartialEq, Clone)]
pub struct FunctionMangler {
name: String,
parameters: Vec<FunctionArgument>,
return_type: Option<Type>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct VariableMangler {
name: String,
ty: Type,
Expand All @@ -72,6 +77,13 @@ impl SectionMangler {
SectionMangler::Variable(VariableMangler { name: name.into(), ty })
}

pub fn name(&self) -> &str {
match self {
SectionMangler::Function(FunctionMangler { name, .. })
| SectionMangler::Variable(VariableMangler { name, .. }) => name,
}
}

pub fn with_parameter(self, param: FunctionArgument) -> SectionMangler {
match self {
SectionMangler::Function(f) => {
Expand All @@ -84,9 +96,11 @@ impl SectionMangler {
}
}

pub fn with_return_type(self, return_type: Option<Type>) -> SectionMangler {
pub fn with_return_type(self, return_type: Type) -> SectionMangler {
match self {
SectionMangler::Function(f) => SectionMangler::Function(FunctionMangler { return_type, ..f }),
SectionMangler::Function(f) => {
SectionMangler::Function(FunctionMangler { return_type: Some(return_type), ..f })
}
SectionMangler::Variable(_) => unreachable!("global variables do not have a return type."),
}
}
Expand All @@ -111,6 +125,7 @@ impl SectionMangler {
// NOTE: This is called `variable_linkage` in the `MemberInfo` struct.

/// We have to encode this because if it changes, the function needs to be reloaded - this is an ABI breakage
#[derive(Debug, PartialEq, Clone)]
pub enum FunctionArgument {
ByValue(Type),
ByRef(Type),
Expand All @@ -127,6 +142,7 @@ impl fmt::Display for FunctionArgument {
}

// TODO: Do we have to encode this? Does that affect ABI? Probably
#[derive(Debug, PartialEq, Clone)]
pub enum StringEncoding {
// TODO: Should we encode this differently? this could cause problems compared to encoding unsigned types
/// Encoded as `8u`
Expand All @@ -146,6 +162,7 @@ impl fmt::Display for StringEncoding {

// This maps directly to the [`DataTypeInformation`] enum in RuSTy - we simply remove some fields and add the ability to encode/decode serialize/deserialize
// TODO: Do we have to handle Generic?
#[derive(Debug, PartialEq, Clone)]
pub enum Type {
/// Encoded as `v`
Void,
Expand All @@ -158,7 +175,9 @@ pub enum Type {
semantic_size: Option<u32>,
},
/// Encoded as `f<size>`
Float { size: u32 },
Float {
size: u32,
},
/// Encoded as `s<encoding><size>`
String {
size: usize, // FIXME: Is that okay? will all the constant expressions be folded at that point? Can we have TypeSize::Undetermined still?
Expand All @@ -170,23 +189,12 @@ pub enum Type {
// TODO: Is changing the `auto_deref` mode an ABI break?
// auto_deref: bool,
},

// --- UNIMPLEMENTED

// FIXME: Do we need any info here? How are structs codegened?
Struct {
// name: TypeId,
// members: Vec<VariableIndexEntry>,
// source: StructSource,
members: Vec<Type>,
},

// FIXME: Same here
Enum {
// name: TypeId,
// referenced_type: TypeId,
// // TODO: Would it make sense to store `VariableIndexEntry`s similar to how the `Struct` variant does?
// // This would allow us to pattern match in the index `find_member` method
// elements: Vec<String>,
referenced_type: Box<Type>,
elements: usize,
},
Array {
inner: Box<Type>,
Expand Down Expand Up @@ -224,27 +232,36 @@ impl fmt::Display for Type {
Type::Float { size } => write!(f, "f{size}"),
Type::String { size, encoding } => write!(f, "s{encoding}{size}",),
Type::Pointer { inner } => write!(f, "p{}", inner),
Type::Struct { members } => {
write!(
f,
"r{}{}",
members.len(),
members.iter().fold(String::new(), |acc, m| format!("{acc}{m}"))
)
}
Type::Enum { referenced_type, elements } => write!(f, "e{elements}{referenced_type}"),
Type::Array { inner } => write!(f, "a{inner}"),
// -- Unimplemented
Type::Struct {} => todo!(),
Type::Enum {} => todo!(),
Type::Array { .. } => todo!(),
Type::SubRange {} => todo!(),
Type::Alias {} => todo!(),
Type::Generic {} => todo!(),
}
}
}

pub const PREFIX: &str = "$RUSTY$";

// TODO: How to encode variadics?
fn mangle_function(FunctionMangler { name, parameters, return_type }: FunctionMangler) -> String {
let mangled = parameters
.into_iter()
/* FIXME: Is that correct? */
.fold(return_type.unwrap_or(Type::Void).to_string(), |mangled, arg| format!("{mangled}[{arg}]"));

format!("{name}:{mangled}")
format!("{PREFIX}{name}:{mangled}")
}

fn mangle_variable(VariableMangler { name, ty }: VariableMangler) -> String {
format!("{name}:{ty}")
format!("{PREFIX}{name}:{ty}")
}
Loading
Loading